Various guides on the net describe how to register routes in Sitecore and also plain old ASP.NET. However, in the context of Sitecore (especially newer versions), you may run into the following error:
`{"Message":"An error has occurred.","ExceptionMessage":"The object has not yet been initialized. Ensure that HttpConfiguration.EnsureInitialized() is called in the application's startup code after all other initialization code.","ExceptionType":"System.InvalidOperationException","StackTrace":" at System.Web.Http.Routing.RouteCollectionRoute.get_SubRoutes()\r\n at System.Web.Http.Routing.RouteCollectionRoute.GetRouteData(String virtualPathRoot, HttpRequestMessage request)\r\n at System.Web.Http.WebHost.Routing.HttpWebRoute.GetRouteData(HttpContextBase httpContext)"}`
In order to overcome this issue or prevent any future issues, make sure to register your routes properly.
Create the following files in your Helix project:
- /App_Config/Include/Feature.config
- RegisterFeatureRoute.cs
- /Controllers/FeatureController.cs
/App_Config/Include/Feature.config
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<initialize>
<processor type="Fishtank.Foundation.Feature.RegisterFeatureRoute, Fishtank.Foundation.Feature" patch:before="processor[@type='Sitecore.Mvc.Pipelines.Loader.InitializeRoutes, Sitecore.Mvc']" />
</initialize>
</pipelines>
</sitecore>
</configuration>
RegisterFeatureRoute.cs
using System.Web.Http;
using System.Web.Routing;
using Sitecore.Pipelines;
namespace Fishtank.Foundation.Feature
{
public class RegisterFeatuerRoute
{
public virtual void Process(PipelineArgs args)
{
RegisterRoute(RouteTable.Routes);
}
protected virtual void RegisterRoute(RouteCollection routes)
{
RouteTable.Routes.MapHttpRoute("routeName",
"your-route-here", /* do not include a forward slash in front of the route */
new {controller = "SiteMap", action = "Generate"} /* controller name should not have the "Controller" suffix */
);
}
}
}
/Controllers/FeatureController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Web.Http;
using Sitecore.Data.Items;
using Sitecore.Links;
using Sitecore.Mvc.Extensions;
using Sitecore.Services.Infrastructure.Web.Http;
using Sitecore.Sites;
namespace Fishtank.Foundation.Feature.Controllers
{
// If you want to take advantage of Sitecore security, use the ServicesApiController. If you want to use the .NET controller, use ApiController
public class FeatureController : ServicesApiController
{
[HttpGet]
public IHttpActionResult Generate()
{
var resp = new HttpResponseMessage
{
Content = new StringContent("Some Content", Encoding.UTF8, "text/xml")
};
// Your code here
return ResponseMessage(resp);
}
}
}
Consider the difference between the `ServicesApiController` and the `ApiController` class inheritance. For many simple APIs, the Sitecore `ServicesApiController` class wrapper will cause issues in distributed environments with CM and CD servers. If you want a controller that will work without extra considerations and configurations, use the standard .NET `ApiController` while noting the possible security issues that may arise.
Keep on coding,
Marcel