Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.net MVC custom route handler/constraint

I need to implement an MVC site with urls per below:

  • category1/product/1/wiki
  • category1/product/2/wiki
  • category1/sub-category2/product/3/wiki
  • category1/sub-category2/sub-category3/product/4/wiki
  • etc. etc.

where the matching criteria is that the url ends with "wiki".

Unfortunately the below catch-all works only in the last part of the url:

routes.MapRoute("page1", // Route name
                "{*path}/wiki", // URL with parameters
                new { controller = "Wiki", action = "page", version = "" } // Parameter defaults

I have not had the time to go through the MVC extensibility options so I was wondering what are the possible choices for implementing this? Any sample/example would be just fantastic!

like image 710
Kumar Avatar asked Jul 10 '09 03:07

Kumar


People also ask

Can we add constraints to the route in MVC?

Attribute Routing is introduced in MVC 5.0. We can also define parameter constraints by placing a constraint name after the parameter name separated by a colon. There are many builtin routing constraints available. We can also create custom routing constraints.

How do you add a constraint to a route?

Creating Route Constraint to a Set of Specific Values routes. MapRoute( "Default", // Route name "{controller}/{action}/{id}", // Route Pattern new { controller = "Home", action = "Index", id = UrlParameter. Optional }, // Default values for parameters new { controller = "^H.

Which method is used to apply a route constraint in an ASP.NET MVC web application?

The Route Constraint in ASP.NET MVC Routing allows us to apply a regular expression to a URL segment to restrict whether the route will match the request. In simple words, we can say that the Route constraint is a way to put some validation around the defined route.

Which is the syntax for custom routes in ASP.NET MVC?

aspx file Register Route method. //Custom Route With Regular Expression Constraints routes. MapRoute( "Blog", "Archive/{entrydate}", new { Controller = "Blog", action = "Archive" }, new { entryDate = @"\d{2}-\d{2}-\d{4}" });


1 Answers

As you mentioned, the catch-all parameter can only appear at the end of a route - the code that you have posted will throw a run-time error and give you the yellow screen of death if you even try to run your application.

There are several extensibility points for building custom routing scenarios. These are - Route, RouteBase, and IRouteHandler.

You can create a generated list of routes to handle by extending RouteBase. Typically you would follow the pattern of having a constructor that takes in a resource (controller name), and then assigning it a list of routes it was responsible for, and then mapping it in your global.asax. Here is some example code you can build from:

public class MyRoute : RouteBase
{
    private List<Route> _routes = new List<Route>();

    public MyRoute(string resource)
    {
        // make a Resource property, not shown in this example
        this.Resource = resource;

        // Generate all your routes here
        _routes.Add(
            new Route("some/url/{param1}",
            new McvRouteHandler {
                Defaults = new RouteValueDictionary(new {
                    controller = resource,
                    action = actionName
                }),
            Constraints = new RouteValueDictionary()
        );
        _routes.Add(...); // another new route   
    }

    public override RouteData GetRouteData(HttpContextBase context)
    {
        foreach (var route in _routes)
        {
            var data = route.GetRouteData(context);
            if (data != null)
            { 
                return data;
            }
        }
        return null;
    }

    public override VirtualPathData GetVirtualPath(RequestContext context, RouteValueDictionary rvd)
    {
        foreach (var route in _routes)
        {
            var path = route.GetVirtualPath(context, rvd);
            if (path != null)
            { 
                return path;
            }
        }
        return null;
    }
}

To use your routing class, do a routes.Add(new MyRoute("page1")); in your Global.asax.

If you need even more control, you can implement an IRouteHandler, and instead of creating MvcRouteHandlers() for your routes as shown in the above example, use your own IRouteHandler. This would allow you to override the logic of selecting the controller from the request data.

The entire framework is extremely extensible, but you would need to learn quite a bit in order to do it properly. I would suggest simply rearranging your URL's if possible to take advantage of the catch-all parameter if you can.

like image 195
womp Avatar answered Sep 24 '22 19:09

womp