ASP.Net MVC Manejo de segmentos con ruta

Soy nuevo en ASP.Net MVC y tengo un problema. Aquí está.

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

Y aquí está mi método de controlador.

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

cuando toco la url siempre obtengo nulo en el parámetro de categoría

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

Me sale este error

Object reference not set to an instance of an object

Como puedo solucionar este problema. Necesito extraer el id de segmento y usarlo. Del mismo modo, necesito procesar el fabricante y las cadenas de atributos también.

Una cosa más

¿Cómo puedo hacer que mi función obtenga al menos un parámetro independientemente del orden? Quiero decir que quiero hacer funciones como que puedo manejar categoría o fabricante o atributos o categoría + fabricante y todas las combinaciones /

Un marcador de posición (como {category} ) actúa como una variable, puede contener cualquier valor. El marco debe ser capaz de entender lo que significan los parámetros en la URL. Puedes hacer esto de tres maneras:

  1. Proporcionarlos en un orden específico y para un número específico de segmentos
  2. Póngalos en la cadena de consulta para que tenga pares de nombre / valor para identificar lo que son
  3. Haga una serie de rutas con segmentos literales para proporcionar nombres para identificar cuáles son los parámetros

Aquí hay un ejemplo de la opción n. ° 3. Es un poco complicado en comparación con el uso de parámetros de cadena de consulta, pero sin duda es posible siempre que proporciones algún tipo de identificador para cada segmento de ruta.

Extensiones IEnumerable

Esto agrega soporte LINQ para poder obtener todas las permutaciones posibles de valores de parámetros.

 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> Combinations(this IEnumerable 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 Prepend(this IEnumerable source, TSource item) { if (source == null) throw new ArgumentNullException("source"); yield return item; foreach (var element in source) yield return element; } public static IEnumerable> Permutations(this IEnumerable 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 }; } } 

Extensiones de RouteCollection

Extendemos el método de extensión MapRoute , agregando la capacidad de agregar un conjunto de rutas para que coincida con todas las permutaciones posibles de la 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 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 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 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 dictionary = values as IDictionary; if (dictionary != null) { return new RouteValueDictionary(dictionary); } return new RouteValueDictionary(values); } } 

Uso

 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 } ); } } 

Esto agrega un conjunto completo de rutas para que coincida con los patrones de URL:

 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} 

Ahora cuando usa la siguiente URL:

 Home/CategoryProducts/category/c_50_ShowcasesDisplays 

Se HomeController la acción CategoryProducts HomeController en HomeController . El valor de su parámetro de categoría será c_50_ShowcasesDisplays .

También creará la URL correspondiente cuando use ActionLink , RouteLink , Url.Action o UrlHelper .

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