Maddhacker24
Maddhacker24

Reputation: 1875

How do I use constraints in ASP.net MVC 4 RouteConfig.cs?

I'm trying to get some routing constraints working using the latest asp.net mvc 4 architecture. Under App_Start there is a file called RouteConfig.cs.

If I remove the constraints section from my example below, the url works. But I need to add some constraints so that the url doesnt match on everything.

Should work: /videos/rating/1

Shold NOT work: /videos/2458/Text-Goes-Here

This is what I have:

//URL: /videos/rating/1
routes.MapRoute(
    name: "Videos",
    url: "videos/{Sort}/{Page}",
    defaults: new { controller = "VideoList", action = "Index", Sort = UrlParameter.Optional, Page = UrlParameter.Optional },
    constraints: new { Sort = @"[a-zA-Z]", Page = @"\d+"}
);

Upvotes: 7

Views: 10271

Answers (2)

Tolani
Tolani

Reputation: 609

My input maybe rather late, but for others still searching for answers.To keep things simple, i would use the following in my RoutesConfig file

 routes.MapRoute(
     name: "Videos",
     url: "{controller}/{action}/{id}",
     defaults: new { controller = "VideoList", action = "Index", id="" },
     constraints: new { id = @"\d+"}
     );

Depending on your choice of implementation, id could be UriParameter.Optional, but in this scenario it is going to be id="" ,because we will be passing a string/int during runtime.

This style was adopted from http://www.asp.net/mvc/overview/older-versions-1/controllers-and-routing/creating-a-route-constraint-cs

One thing to keep in mind by convention controller classes always end with controller e.g VideoListController class. This class should be listed under the controller folder containing the following method

public ActionResult Index(string id)
{
    // note this maps to the action
    // random implementation
    ViewBag.Message=id;
    View()
}

// note this approach still matches any string... To match only integers, the Index method has to be rewritten

public ActionResult Index(int id)
{
     // note this maps to the action
     ViewBag.Message=id;
     View()
}

Consequently, this approach works for VideoList/Index/12 but upon putting VideoList/Index/somerandomtext it throws an error during runtime. This could be solved by employing error pages. I hope this helps. Vote if its quite useful.

Upvotes: 1

Nick Larsen
Nick Larsen

Reputation: 18877

If you want multiple optional parameters on the same route, you will run into trouble because your urls must always specify the first one in order to use the second one. Just because you use constraints doesn't stop it from evaluating the parameters, it instead fails to match this route.

Take this for example: /videos/3

When this is trying to match, it finds videos, and says, "OK, I still match". Then it looks at the next parameter, which is Sort and it gets the value 3, then checks it against the constraint. The constraint fails, and so it says "OPPS, I don't match this route", and it moves on to the next route. In order to specify the page without the sort parameter defined, you should instead define 2 routes.

//URL: /videos/rating/1
routes.MapRoute(
    name: "Videos",
    url: "videos/{Sort}/{Page}",
    defaults: new { controller = "VideoList", action = "Index", Page = UrlParameter.Optional },
    constraints: new { Sort = @"[a-zA-Z]+", Page = @"\d+"}
);

//URL: /videos/1
routes.MapRoute(
    name: "Videos",
    url: "videos/{Page}",
    defaults: new { controller = "VideoList", action = "Index", Sort = "the actual default sort value", Page = UrlParameter.Optional },
    constraints: new { Page = @"\d+"}
);

I put the most specific routes first when possible and end with the least specific, but in this case the order should not matter because of the constraints. What I mean by specific is most defined values, so in this case you must define the sort in the first route, and you also can specify the page, so it is more specific than the route with just the page parameter.

Upvotes: 12

Related Questions