Tom Schreck
Tom Schreck

Reputation: 5287

ASP.Net MVC routing with RouteConstraint not working

Just when I think I have routing figured out, it doesn't work the way I think it should. I'm using ASP.Net MVC 4 RC. Here's my RouteConfig:

        routes.MapRoute
        (
            "TwoIntegers",
            "{controller}/{action}/{id1}/{id2}",
            new { controller = "Gallery", action = "Index", id1 = new Int32Constraint(), id2 = new Int32Constraint() }
        );

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

Here's my route constraint:

public class Int32Constraint : IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        if (values.ContainsKey(parameterName))
        {
            int intValue;
            return int.TryParse(values[parameterName].ToString(), out intValue) && (intValue != int.MinValue) && (intValue != int.MaxValue);
        }

        return false;
    }
}

/{domain.com}/PageSection/Edit/21

It is getting stopped at the "TwoIntegers" route. It's very clear there's not a second integer being passed.

Here's my 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)' in 'SolutiaConsulting.Web.ContentManager.Controllers.PageSectionController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter. Parameter name: parameters

What am I doing wrong? I have the more specific route listed first. Please help.

Upvotes: 0

Views: 1551

Answers (1)

Darin Dimitrov
Darin Dimitrov

Reputation: 1039200

Your constraints are not correctly specified. Make sure you are using the correct overload of the MapRoute extension method:

routes.MapRoute(
    "TwoIntegers",
    "{controller}/{action}/{id1}/{id2}",
    new { controller = "Gallery", action = "Index" },
    new { id1 = new Int32Constraint(), id2 = new Int32Constraint() }
);

Notice the 4th argument that is used to specify constraints, not the 3rd.

Btw, you could make your code more readable using named parameters:

routes.MapRoute(
    name: "TwoIntegers",
    url: "{controller}/{action}/{id1}/{id2}",
    defaults: new { controller = "Gallery", action = "Index" },
    constraints: new { id1 = new Int32Constraint(), id2 = new Int32Constraint() }
);

Also how about a regex?

routes.MapRoute(
    name: "TwoIntegers",
    url: "{controller}/{action}/{id1}/{id2}",
    defaults: new { controller = "Gallery", action = "Index" },
    constraints: new { id1 = @"\d+", id2 = @"\d+" }
);

Upvotes: 2

Related Questions