With this configured my custom RouteHandler runs into a null reference exception when executing the FindContent method. The umbracoContext is null:
Is there any solution to this? Am I doing something wrong? I really need to work with a dynamic {controller} placeholder as I have lot’s of controllers in my application and I don’t want to create a route for each one.
I'm not really sure why you're getting a null exception here. I just tried in a sample project and the context is not null in my tests and it finds my node. Could you provide a sample project where this is happening, then I'll try taking a look at it.
However - in regards to the route you're trying to define you'll have some problems as registered MVC routes are ignored by the Umbraco pipeline.
When you define a route like the one you specified here, it is basically a catch-all route. Anything you type in for a URL could be matched (and will be matched unless something else registered in MVC matches before this). This means you will never get into Umbraco's pipeline where the various content finders trigger to render your Umbraco content pages.
So by doing what you're doing you're pretty much making sure Umbraco content will not be able to render on the expected URLs and the only thing that will work is controllers you have created in your project.
You have a few options here to prevent this from happening:
As you mention yourself, you can define routes for each of your controllers. This is not really a good solution for you as you would have to define a lot of routes for all your controllers.
You can register a route like you do, but with a URL prefix to make sure anything that shouldn't hit one of your controllers, actually hits the Umbraco pipeline instead. For example a route definition like: "someprefix/{controller}/{action}". This will make sure all your controllers are registered automatically, but it comes with a downside of having to use a prefixed URL.
You can define constraints on your route definitions. This is the solution I consider to be the best one for something like this. You can have just one entry for registering controllers (like the one you have above) and then you will just need to put in an object for the constraint part of the MVC route definition:
new { controller = "MyController|AnotherController|AThirdController" }
This will ensure that only requests fitting with this contraint will be ignored by the Umbraco pipeline and everything else will be handled. Yes - it is a little more manual work since you have to update the constraint when adding a new controller, but I don't think this is too bad.
I'm not sure if this will solve your initial problem - if not then I'll need that sample site in order to replicate the problem.
I was able to briefly replicate the NullReferenceException above in a sample project, but now even a new project doesn't produce it. The RouteWithLayoutHandler works just like it should.
As for the constraint option:
RouteTable.Routes.MapUmbracoRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "home", action = "index", id = UrlParameter.Optional},
new RouteWithLayoutHandler(),
new { controller = "account" });
Routing works, more or less. Umbraco routes its content, and controller routes bypass Umbraco. But when I request /account:
AccountController : Controller
→ System.InvalidOperationException: Unable to resolve type: UmbracoRoutingTest.Controllers.AccountController, service name:
AccountController : SurfaceController
→ System.MissingMethodException: Cannot create an instance of an interface.
Custom Route with {controller} placeholder
Hi,
I'm trying to define the following route in Umbraco 8:
Note that I’m using the {controller} placeholder. So my URL could be
I do not want to hardcode the controller name in the route itself like it's done in the docs (https://our.umbraco.com/documentation/Implementation/Custom-Routing/)
With this configured my custom RouteHandler runs into a null reference exception when executing the FindContent method. The umbracoContext is null:
Is there any solution to this? Am I doing something wrong? I really need to work with a dynamic {controller} placeholder as I have lot’s of controllers in my application and I don’t want to create a route for each one.
Kind regrads
Hi Daniel,
I'm not really sure why you're getting a null exception here. I just tried in a sample project and the context is not null in my tests and it finds my node. Could you provide a sample project where this is happening, then I'll try taking a look at it.
However - in regards to the route you're trying to define you'll have some problems as registered MVC routes are ignored by the Umbraco pipeline.
When you define a route like the one you specified here, it is basically a catch-all route. Anything you type in for a URL could be matched (and will be matched unless something else registered in MVC matches before this). This means you will never get into Umbraco's pipeline where the various content finders trigger to render your Umbraco content pages.
So by doing what you're doing you're pretty much making sure Umbraco content will not be able to render on the expected URLs and the only thing that will work is controllers you have created in your project.
You have a few options here to prevent this from happening:
As you mention yourself, you can define routes for each of your controllers. This is not really a good solution for you as you would have to define a lot of routes for all your controllers.
You can register a route like you do, but with a URL prefix to make sure anything that shouldn't hit one of your controllers, actually hits the Umbraco pipeline instead. For example a route definition like: "someprefix/{controller}/{action}". This will make sure all your controllers are registered automatically, but it comes with a downside of having to use a prefixed URL.
You can define constraints on your route definitions. This is the solution I consider to be the best one for something like this. You can have just one entry for registering controllers (like the one you have above) and then you will just need to put in an object for the constraint part of the MVC route definition:
new { controller = "MyController|AnotherController|AThirdController" }
This will ensure that only requests fitting with this contraint will be ignored by the Umbraco pipeline and everything else will be handled. Yes - it is a little more manual work since you have to update the constraint when adding a new controller, but I don't think this is too bad.
I'm not sure if this will solve your initial problem - if not then I'll need that sample site in order to replicate the problem.
Hi Claus,
thanks for your help!
I'll test no. 3 and let you know if it works :)
Kind regards
Hi Claus,
I was able to briefly replicate the NullReferenceException above in a sample project, but now even a new project doesn't produce it. The RouteWithLayoutHandler works just like it should.
As for the constraint option:
Routing works, more or less. Umbraco routes its content, and controller routes bypass Umbraco. But when I request
/account
:AccountController : Controller
→ System.InvalidOperationException: Unable to resolve type: UmbracoRoutingTest.Controllers.AccountController, service name:
AccountController : SurfaceController
→ System.MissingMethodException: Cannot create an instance of an interface.
I've uploaded the sample project.
Kind regards
Hi Claus,
Have you had a chance to take a look at this yet?
Kind regards
is working on a reply...