views:

253

answers:

2

Hi,

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 also 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

+2  A: 

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

Paul Creasey
A: 

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.

Eilon