ASP.Net MVC Segmentos de manejo con ruta
asp.net-mvc routes (1)
Soy nuevo en ASP.Net MVC y enfrento 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 controlador.
public ActionResult CategoryProducts(string category, string manufacturer, string attribute)
{
string[] categoryParameter = category.Split(''_'');
.
.
.
return View();
}
cuando llego a la URL siempre obtengo un valor 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 la identificación del segmento y usarla. 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 esa, 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 comprender qué significan los parámetros en la URL.
Puedes hacer esto de tres maneras:
- Proporcionarlos en un orden específico y para un número específico de segmentos.
- Póngalos en la cadena de consulta para que tenga pares de nombre / valor para identificar cuáles son
- 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 # 3. Es un poco complicado en comparación con el uso de parámetros de cadena de consulta, pero ciertamente es posible siempre que proporcione algún tipo de identificador para cada segmento de ruta.
I Extensiones numerables
Esto agrega compatibilidad con LINQ para poder obtener todas las permutaciones posibles de los valores de los 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://.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://.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 };
}
}
Extensiones 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<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);
}
}
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
en el
HomeController
.
El valor del 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