Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Daniel 6 posts 76 karma points
    Dec 10, 2019 @ 10:13
    Daniel
    0

    Custom Route with {controller} placeholder

    Hi,

    I'm trying to define the following route in Umbraco 8:

    RouteTable.Routes.MapUmbracoRoute(
                    "Default",
                    "{controller}/{action}/{id}",
                    new { controller = "home", action = "index", id = UrlParameter.Optional }, new RouteWithLayoutHandler());
    

    Note that I’m using the {controller} placeholder. So my URL could be

    • mysite.com/account/login
    • mysite.com/products/index/5
    • mysite.com/documentation/someAction

    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: enter image description here

    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

  • Claus Jensen 49 posts 157 karma points hq
    Apr 01, 2020 @ 22:49
    Claus Jensen
    0

    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:

    1. 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.

    2. 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.

    3. 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.

  • Daniel 6 posts 76 karma points
    Apr 02, 2020 @ 08:28
    Daniel
    0

    Hi Claus,

    thanks for your help!

    I'll test no. 3 and let you know if it works :)

    Kind regards

  • Daniel 6 posts 76 karma points
    Apr 07, 2020 @ 10:08
    Daniel
    0

    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:

    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.

    I've uploaded the sample project.

    Kind regards

  • Daniel 6 posts 76 karma points
    Jun 05, 2020 @ 13:09
    Daniel
    0

    Hi Claus,

    Have you had a chance to take a look at this yet?

    Kind regards

Please Sign in or register to post replies

Write your reply to:

Draft