ASP.NET MVC: Route with optional parameter, but if supplied, must match \d+

Viewed 28002

I'm trying to write a route with a nullable int in it. It should be possible to go to both /profile/ but also /profile/\d+.

routes.MapRoute("ProfileDetails", "profile/{userId}",
                new {controller = "Profile",
                     action = "Details",
                     userId = UrlParameter.Optional},
                new {userId = @"\d+"});

As you can see, I say that userId is optional but also that it should match the regular expression \d+. This does not work and I see why.

But how would I construct a route that matches just /profile/ but also /profile/ followed by a number?

6 Answers

I needed to validate a few things with more than just a RegEx but was still getting an issue similar to this. My approach was to write a constraint wrapper for any custom route constraints I may already have:

public class OptionalRouteConstraint : IRouteConstraint
{
    public IRouteConstraint Constraint { get; set; }

    public bool Match
        (
            HttpContextBase httpContext,
            Route route,
            string parameterName,
            RouteValueDictionary values,
            RouteDirection routeDirection
        )
    {
        var value = values[parameterName];

        if (value != UrlParameter.Optional)
        {
            return Constraint.Match(httpContext, route, parameterName, values, routeDirection);
        }
        else
        {
            return true;
        }
    }
}

And then, in constraints under a route in RouteConfig.cs, it would look like this:

defaults: new {
    //... other params
    userid = UrlParameter.Optional
}
constraints: new
{
    //... other constraints
    userid = new OptionalRouteConstraint { Constraint = new UserIdConstraint() }
}
Related