ASP.NET MVC Route Contraints with {ID}-{Slug} Form

2019-07-13 10:51发布

问题:

I have a route like following, ideally I would like it to match:

domain.com/layout/1-slug-is-the-name-of-the-page

        routes.MapRoute(
            "Layout",                                                // Route name
            "layout/{id}-{slug}",                                           // URL with parameters
            new { controller = "Home", action = "Index"}, new {id = @"\d+$"}
        );

But when I hit the url, I am keep on getting this exception:

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

The above route will match the following though:

domain.com/layout/1-slug or domain.com/layout/1-slug_permalink

Seems like the hyphen that separates the ID from the Slug is causing issues.

回答1:

As the first step of processing, the Routing module performs pattern matching of the incoming URL against the declared route. This pattern matching is eager (so the id gets all hyphens up to the last one, which marks the beginning of the slug parameter). Constraints (like "\d+") run after pattern matching. So what's tripping you up is that the eager pattern matching is setting id to an invalid value, then it's failing the constraint, which causes the overall route not to match, so the pipeline moves on trying to match the incoming request to the next route in the collection.

The best (e.g. easiest to understand, non-trickery) way to work around this is to match the entire segment as an idAndSlug parameter, then use a proper regex within the controller to split this string back out into its id and slug constituents.

Alternatively, consider using the slash, as suggested by mxmissile.