asp.net-mvcroutesurl-routingasp.net-mvc-routingmvcsitemapprovider

MVC Routing bogus URLs allowed


I am currently using MVC Routing and MvcSiteMapProvider. I have just noticed something which I am unsure about:

[Route("mypath/{param1}/{param2}/{param3:int}/", Name = "myaction")]
[MvcSiteMapNode(Title = "My Thing", ParentKey = "myparent", Key = "myaction", PreservedRouteParameters = "param1, param2, param3")]
public ActionResult myaction(string param1, string param2, int param3)
{
    mymodel model = gd.getmydata(param3);
    var node = SiteMaps.Current.CurrentNode;
    node.Title = model.name;
    node.ParentNode.Title = location;
    node.ParentNode.RouteValues["param"] = location;

    return View(model);
} 

When I test the url is how I designed it:

http://localhost:12345/mypath/param1/param2/param3

However if I bastardise the URL with drivel in param2 or param3 the view still resolves with no error. Only by changing mypath or param3 does it 404:

http://localhost:12345/mypath/drivel/param2/param3
http://localhost:12345/mypath/param1/drivel/param3

Am I missing something? Should I have parameter validation in the controller?


Solution

  • The tokens in the URL parameter of the route act like variables. The way you have your route configured, it will always match any URL starting with mypath/ and containing 3 additional segments. The route does not care what values are put into those segments, it will make them into route keys named param1, param2, and param3 containing whatever values are in the actual URL.

    If you want the route only to match the URL /mypath/param1/param2/param3, you will need to use literal route segments.

    [Route("mypath/param1/param2/param3/", Name = "myaction")]
    

    But then, since your param3 segment is an integer value and your URL contains a string, it is difficult to tell what you are trying to achieve. If you declare it an integer, you must place an integer in the URL or you will get an error.

    /mypath/param1/param2/123
    

    Another thing to note if you are using literal segments in your URL is that they are not converted into route values, so there is no need to use PreservedRouteParamters in that case.

    So, if you declare your route with variables, it should not be a surprise that any value works. If you want an explicit route, declare it with literal segments. If you want variables but want to restrict the route to a certain range of possible values, then you need to use route constraints.