ASP.Net MVC Route Segment Processing

I am new to ASP.Net MVC and ran into a problem. Here it is.

routes.MapRoute( "SearchResults",// Route name "{controller}/{action}/{category}/{manufacturer}/{attribute}", new { controller = "Home", action = "CategoryProducts", category = UrlParameter.Optional, manufacturer = UrlParameter.Optional, attribute = UrlParameter.Optional } ); 

And here is my controller method.

 public ActionResult CategoryProducts(string category, string manufacturer, string attribute) { string[] categoryParameter = category.Split('_'); . . . return View(); } 

when i click url i always get null in category parameter

 http://localhost:50877/Home/CategoryProducts/c_50_ShowcasesDisplays 

I get this error

Object reference not set to an instance of an object

How can I fix this problem. I need to extract an identifier from a segment and use it. Similarly, I need to process the producer and attribute string as well.

One more thing

How can I make my function get at least one parameter regardless of order? I mean, I want to do functions that can handle a category or manufacturer or attributes or producer of category +, and all combinations /

+2
source share
1 answer

A placeholder (for example, {category} ) acts like a variable - it can contain any value. The framework should be able to understand what the parameters in the URL mean. You can do this in one of three ways:

  • Provide them in a specific order and for a certain number of segments
  • Put them in the query string so that you have name / value pairs to determine what they represent.
  • Make a series of routes with literal segments to specify names to define parameters

Here is an example of option No. 3. This is slightly related to the use of query string parameters, but it is certainly possible if you provide some kind of identifier for each segment of the route.

IEnumerable Extensions

This adds LINQ support for the ability to get every possible permutation of parameter values.

 using System; using System.Collections.Generic; using System.Linq; public static class IEnumerableExtensions { // Can be used to get all permutations at a certain level // Source: http://stackoverflow.com/questions/127704/algorithm-to-return-all-combinations-of-k-elements-from-n#1898744 public static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> elements, int k) { return k == 0 ? new[] { new T[0] } : elements.SelectMany((e, i) => elements.Skip(i + 1).Combinations(k - 1).Select(c => (new[] { e }).Concat(c))); } // This one came from: http://stackoverflow.com/questions/774457/combination-generator-in-linq#12012418 private static IEnumerable<TSource> Prepend<TSource>(this IEnumerable<TSource> source, TSource item) { if (source == null) throw new ArgumentNullException("source"); yield return item; foreach (var element in source) yield return element; } public static IEnumerable<IEnumerable<TSource>> Permutations<TSource>(this IEnumerable<TSource> source) { if (source == null) throw new ArgumentNullException("source"); var list = source.ToList(); if (list.Count > 1) return from s in list from p in Permutations(list.Take(list.IndexOf(s)).Concat(list.Skip(list.IndexOf(s) + 1))) select p.Prepend(s); return new[] { list }; } } 

Extensions RouteCollection

We are expanding the MapRoute extension method by adding the ability to add a set of routes to match all possible permutations of the URL.

 using System; using System.Collections.Generic; using System.Web.Mvc; using System.Web.Routing; public static class RouteCollectionExtensions { public static void MapRoute(this RouteCollection routes, string url, object defaults, string[] namespaces, string[] optionalParameters) { MapRoute(routes, url, defaults, null, namespaces, optionalParameters); } public static void MapRoute(this RouteCollection routes, string url, object defaults, object constraints, string[] namespaces, string[] optionalParameters) { if (routes == null) { throw new ArgumentNullException("routes"); } if (url == null) { throw new ArgumentNullException("url"); } AddAllRoutePermutations(routes, url, defaults, constraints, namespaces, optionalParameters); } private static void AddAllRoutePermutations(RouteCollection routes, string url, object defaults, object constraints, string[] namespaces, string[] optionalParameters) { // Start with the longest routes, then add the shorter ones for (int length = optionalParameters.Length; length > 0; length--) { foreach (var route in GetRoutePermutations(url, defaults, constraints, namespaces, optionalParameters, length)) { routes.Add(route); } } } private static IEnumerable<Route> GetRoutePermutations(string url, object defaults, object constraints, string[] namespaces, string[] optionalParameters, int length) { foreach (var combination in optionalParameters.Combinations(length)) { foreach (var permutation in combination.Permutations()) { yield return GenerateRoute(url, permutation, defaults, constraints, namespaces); } } } private static Route GenerateRoute(string url, IEnumerable<string> permutation, object defaults, object constraints, string[] namespaces) { var newUrl = GenerateUrlPattern(url, permutation); var result = new Route(newUrl, new MvcRouteHandler()) { Defaults = CreateRouteValueDictionary(defaults), Constraints = CreateRouteValueDictionary(constraints), DataTokens = new RouteValueDictionary() }; if ((namespaces != null) && (namespaces.Length > 0)) { result.DataTokens["Namespaces"] = namespaces; } return result; } private static string GenerateUrlPattern(string url, IEnumerable<string> permutation) { string result = url; foreach (string param in permutation) { result += "/" + param + "/{" + param + "}"; } System.Diagnostics.Debug.WriteLine(result); return result; } private static RouteValueDictionary CreateRouteValueDictionary(object values) { IDictionary<string, object> dictionary = values as IDictionary<string, object>; if (dictionary != null) { return new RouteValueDictionary(dictionary); } return new RouteValueDictionary(values); } } 

Using

 public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( url: "Home/CategoryProducts", defaults: new { controller = "Home", action = "CategoryProducts" }, namespaces: null, optionalParameters: new string[] { "category", "manufacturer", "attribute" }); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } } 

This adds a complete set of routes to match URL patterns:

 Home/CategoryProducts/category/{category}/manufacturer/{manufacturer}/attribute/{attribute} Home/CategoryProducts/category/{category}/attribute/{attribute}/manufacturer/{manufacturer} Home/CategoryProducts/manufacturer/{manufacturer}/category/{category}/attribute/{attribute} Home/CategoryProducts/manufacturer/{manufacturer}/attribute/{attribute}/category/{category} Home/CategoryProducts/attribute/{attribute}/category/{category}/manufacturer/{manufacturer} Home/CategoryProducts/attribute/{attribute}/manufacturer/{manufacturer}/category/{category} Home/CategoryProducts/category/{category}/manufacturer/{manufacturer} Home/CategoryProducts/manufacturer/{manufacturer}/category/{category} Home/CategoryProducts/category/{category}/attribute/{attribute} Home/CategoryProducts/attribute/{attribute}/category/{category} Home/CategoryProducts/manufacturer/{manufacturer}/attribute/{attribute} Home/CategoryProducts/attribute/{attribute}/manufacturer/{manufacturer} Home/CategoryProducts/category/{category} Home/CategoryProducts/manufacturer/{manufacturer} Home/CategoryProducts/attribute/{attribute} 

Now when you use the following url:

 Home/CategoryProducts/category/c_50_ShowcasesDisplays 

The CategoryProducts action on the HomeController will be called. The parameter value for your category will be c_50_ShowcasesDisplays .

It will also build the appropriate URL when using ActionLink , RouteLink , Url.Action or UrlHelper .

 @Html.ActionLink("ShowcasesDisplays", "CategoryProducts", "Home", new { category = "c_50_ShowcasesDisplays" }, null) // Generates URL /Home/CategoryProducts/category/c_50_ShowcasesDisplays 
+4
source

Source: https://habr.com/ru/post/1487740/


All Articles