开发者

ASP.NET MVC Route not working with constraint

I'm having trouble getting a Route working in order to constrain the parameters of an action of a controller to only be integers.

I have a a controller action as follows:

    [RequiresRole(RoleToCheckFor = "Administrator"), AcceptVerbs(HttpVerbs.Get)]
    public ActionResult Edit(int id)
    {
       ...
    }

and the following routes in Global.asax.cs:

        routes.MapRoute(
            "UserEdit",       
            "user/edit/{id}",       
            new {controller = "user", action = "edit"},   
            new {id = @"\d+"}
            );

        routes.MapRoute(
            "Default",                                              
            "{controller}/{action}/{id}",                           
            new { controller = "Home", action = "Index", id = "" }  
            );

        routes.MapRoute("Error",
                "{*url}",
                new { controller = "Error", action = "notfound" });

I'm therefore expecting that if i enter http://domain.com/user/edit/ABCD i shouldn't get the following usual error:

The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult Edit(Int32)'

This (i think) is precisely what is al开发者_C百科so said at http://www.asp.net/%28S%28pdfrohu0ajmwt445fanvj2r3%29%29/learn/mvc/tutorial-24-cs.aspx

However, i'm still seeing the "...null entry..." error.

Any ideas why this is so? Am i doing something wrong with the route setup?

Thanks


your second route

routes.MapRoute(
        "Default",                                              
        "{controller}/{action}/{id}",                           
        new { controller = "Home", action = "Index", id = "" }  
        );

is catching it and is unconstrained.

Use Phil Haacks route debugger for such issues


As Paul points out, the route is correctly being skipped because the constraint isn't matching. Thus, the routing system continues to the next route and tries to match it. Because the second route is not constrained, it will match and be processed.

There are a number of ways to work around this.

One of the simplest ways is to remove the constraint from the route and to do the parameter validation checkin in the controller action.

Another way is to add an additional route immediately after the edit route that serves to display errors:

    routes.MapRoute(
        "UserEditError",
        "user/edit/{id}",
        new {controller = "user", action = "EditError"}
        ); 

Note that this route has no constraint on it and goes to an EditError action. This way you might be able to provide better errors for people who type in invalid URLs.


A mistake I always manage to make is to put

controller = "HomeController" instead of controller = "Home". That'll break your routes every time :-)

  context.MapRoute(
     name: "RedirectAll",
     url: "{*url}",
     defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
     namespaces: new[] { typeof(HomeController).Namespace },
                  constraints: new { host = new HostConstraint("defenderrazor.com") });
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜