简体   繁体   中英

Routing in asp.net mvc with multiple optional parameters

I am developing a asp.net mvc 4 application where I need a custom route which will handle multiple parameters like this:

routes.MapRoute(
   "Default",                                              
   "FilteredResults/Filter1-{1stParam}/Filter2-{2ndParam}/..../Filter-N{nthParam}",                           // URL with parameters
   new { controller = "Home", action = "Index", id = "" }   defaults
    );

I want to be able to pass only a subset of the parameters to the route(depending if some filters are selected or not)

For example if I have only the second Filter selected, I want to reference it this way:

<a href="/FilteredResults/Filter2-1000">

Is this possible to do this in a single route without creating a lot of routes for each combination of filters?

You can try with following example

On RouteConfig :

routes.MapRoute("Name", "tag/{*tags}", new { controller = ..., action = ... });

On Controller :

ActionResult MyAction(string tags) {
    foreach(string tag in tags.Split("/")) {
        ...
    }
}

You could create a custom RouteBase implementation that could handle this detail.

public class FilteredRoute : RouteBase
{
    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        RouteData result = null;
        var path = httpContext.Request.Path;
        // Path always starts with a "/", so ignore it.
        var segments = path.Substring(1).Split('/');

        if (segments.Any() && segments[0].Equals("FilteredResults", StringComparison.OrdinalIgnoreCase))
        {
            var result = new RouteData(this, new MvcRouteHandler());

            result.Values["controller"] = "Filter";
            result.Values["action"] = "ProcessFilters";

            // Add filters to route data (skip the first segment)
            var filters = segments.Skip(1).ToArray();

            foreach (var filter in filters)
            {
                string key = ParseRouteKey(filter);
                var value = ParseRouteValue(filter);

                result.Values[key] = value;
            }
        }

        // Make sure to return null if this route does not match
        return result;
    }

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
        VirtualPathData result = null;

        // Process outgoing route here (to rebuild the URL from @Html.ActionLink)

        return result;
    }
}

Note that if you do it this way, it won't matter what order the filters are supplied in as long as the URL starts with /FilteredResults/ .

Then you just add it to your route configuration like this.

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    // Add the filtered route
    routes.Add("Filtered", new FilteredRoute());

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM