Search code examples
asp.net-mvcasp.net-mvc-routinghtml.beginform

MVC custom route and BeginForm behaviour


I have added a custom route:

RouteTable.Routes.Insert(
    0,
    new Route(
        "common/scripts",
        new EmbeddedScriptRouteHandler()
    )
);

Now, whenever I use BeginForm to render a Form tag in a view, the URL generated by the BeginForm has changed. So, for example, without this custom route, @Html.BeginForm("Index", "Home") would generate a Form tag with the action "/Home/Index". As soon as I add this new Route, the Form tag action becomes "/common/scripts?action=Index&controller=Home". Why has this changed?

My desired result is that any URL "/common/scripts" is handled by my custom route, but all other URLs are handled by the default route.


Solution

  • It has changed because that route is included as the first route, so when MVC tries to generate a url it will always find that one. Because it has no segments or default values, the route always match and any parameters like the controller/action are included as query string values.

    You can add a segment in the route definition for scriptName (even if it won´t be used by your route handler). That way, this route won´t be picked when generating a Url unless you pass a value for scriptName.

    RouteTable.Routes.Insert(0,
        new Route(
            "common/scripts/{scriptName}",
            new EmbeddedScriptRouteHandler()
        )
    );
    

    Another option would be setting a default value for controller, that matches none of your controllers. This way when generating urls in MVC, this route would always be excluded as none of your controllers will match that value. This should have no other effect when resolving incoming routes, as you use your custom route handler.

    Something like this:

    RouteTable.Routes.Insert(0,
        new Route(
            "common/scripts",    
            new RouteValueDictionary(new { controller = "AControllerThatDoesntExists"}),
            new EmbeddedScriptRouteHandler()
        )
    );