Custom MVC Routes
This feature was introduced in Umbraco 7.3.0+
Documentation about how to setup your own custom controllers and routes that need to exist alongside of the Umbraco pipeline
Where to put your routing logic?
In Umbraco the best place to put your routing logic is in a custom Umbraco.Core.ApplicationEventHandler
class and override the ApplicationStarted
method. There you can add any custom routing logic you like and you can be sure that the Umbraco application has completed its booting sequence.
User defined routes
Umbraco doesn't interfere with any user defined routes that you wish to have. Your custom routes to your own custom controllers will work perfectly and seamlessly alongside of Umbraco.
Custom routes within the Umbraco pipeline
You can specify your own custom MVC routes to work within the Umbraco pipeline. This requires you to use an implementation of Umbraco.Web.Mvc.UmbracoVirtualNodeRouteHandler
with your custom route.
As an example:
protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
// Custom route to MyProductController which will use a node with a specific ID as the
// IPublishedContent for the current rendering page
RouteTable.Routes.MapUmbracoRoute(
"ProductCustomRoute",
"Products/{action}/{sku}",
new
{
controller = "MyProduct",
sku = UrlParameter.Optional
},
new ProductsRouteHandler(_productsNodeId));
}
This is using a extension method: MapUmbracoRoute
which takes in the normal routing parameters (you can also include constraints, namespaces, etc….) but also takes in an instance of UmbracoVirtualNodeRouteHandler
.
The instance of UmbracoVirtualNodeRouteHandler
is responsible for associating an IPublishedContent
with this route. It has one abstract method which must be implemented:
IPublishedContent FindContent(RequestContext requestContext, UmbracoContext umbracoContext)
It has another virtual method that can be overridden which will allow you to manipulate the PublishedContentRequest however you’d like:
PreparePublishedContentRequest(PublishedContentRequest publishedContentRequest)
So how do you find content to associate with the route? Well that’s up to you, one way (as seen above) would be to specify a node Id. In the example ProductsRouteHandler
is inheriting from UmbracoVirtualNodeByIdRouteHandler
which has an abstract method:
IPublishedContent FindContent(RequestContext requestContext, UmbracoContext umbracoContext, IPublishedContent baseContent);
So based on all this information provided in these methods, you can associate whatever IPublishedContent item you want to the request.
Virtual Content
This implementation expects any instance of IPublishedContent
, so this means you can create your own virtual nodes with any custom properties you want. Generally speaking you’ll probably have a real Umbraco IPublishedContent
instance as a reference point, so you could create your own virtual IPublishedContent
item based on PublishedContentWrapped
, pass in this real node and then override whatever properties you want, like the page Name, etc..
Whatever instance of IPublishedContent
returned in the FindContent
method will be converted to a RenderModel
for use in your controllers.
Controllers
Controllers are straight forward and work like any other routed controller except that the Action will have an instance of RenderModel mapped to it’s parameter.
public class MyProductController : RenderMvcController
{
public ActionResult Product(RenderModel model, string sku)
{
// in my case, the IPublishedContent attached to this
// model will be my products node in Umbraco which i
// can now use to traverse to display the product list
// or lookup the product by sku
if (string.IsNullOrEmpty(sku))
{
// render the products list if no sku
return RenderProductsList(model);
}
else
{
return RenderProduct(model, sku);
}
}
}