tag route net for data asp all asp.net-mvc asp.net-mvc-4

asp.net-mvc - route - tag helpers asp net core



Agregar una matriz de tipos complejos a RouteValueDictionary (2)

También encontré este problema y usé el código de Zack pero encontré un error. Si IEnumerable es una matriz de cadena (cadena []), entonces hay un problema. Así que pensé que compartiría mi versión extendida.

public static RouteValueDictionary ToRouteValueDictionaryWithCollection(this RouteValueDictionary routeValues) { var newRouteValues = new RouteValueDictionary(); foreach(var key in routeValues.Keys) { object value = routeValues[key]; if(value is IEnumerable && !(value is string)) { int index = 0; foreach(object val in (IEnumerable)value) { if(val is string || val.GetType().IsPrimitive) { newRouteValues.Add(String.Format("{0}[{1}]", key, index), val); } else { var properties = val.GetType().GetProperties(); foreach(var propInfo in properties) { newRouteValues.Add( String.Format("{0}[{1}].{2}", key, index, propInfo.Name), propInfo.GetValue(val)); } } index++; } } else { newRouteValues.Add(key, value); } } return newRouteValues; }

Me preguntaba si existe una manera elegante de agregar una matriz de tipos complejos a un tipo de RouteValueDictionary o compatible.

Por ejemplo, si tengo una clase y una acción:

public class TestObject { public string Name { get; set; } public int Count { get; set; } public TestObject() { } public TestObject(string name, int count) { this.Name = name; this.Count = count; } } public ActionResult Test(ICollection<TestObjects> t) { return View(); }

entonces sé que si llamo a esta acción a través de la URL "/Test?t[0].Name=One&t[0].Count=1&t[1].Name=Two&t[1].Count=2" que MVC mapeará esos parámetros de cadenas de consulta regresan al tipo ICollection automáticamente. Sin embargo, si estoy creando manualmente un enlace en algún lugar usando Url.Action (), y quiero pasar un RouteValueDictionary de los parámetros, cuando agrego un ICollection al RouteValueDictionary, Url.Action simplemente lo representa como el tipo, como & t = System.Collections.Generic.List.

Por ejemplo:

RouteValueDictionary routeValDict = new RouteValueDictionary(); List<TestObject> testObjects = new List<TestObject>(); testObjects.Add(new TestObject("One", 1)); testObjects.Add(new TestObject("Two", 2)); routeValDict.Add("t", testObjects); // Does not properly create the parameters for the List<TestObject> collection. string url = Url.Action("Test", "Test", routeValDict);

¿Hay alguna manera de hacer que muestre automáticamente esa colección en el formato que MVC también entiende cómo mapear, o debo hacerlo de forma manual?

¿Qué es lo que me estoy perdiendo, por qué lo harían para que este hermoso mapeo exista en una Acción pero no brinde una manera de trabajar manualmente en la dirección opuesta para crear URL?


Bueno, estoy abierto a otras soluciones (más elegantes), pero lo conseguí trabajando tomando el método de extensión encontrado en este q / a: https://.com/a/5208050/1228414 y adaptándolo para usar el reflejo para propiedades de tipo complejo en lugar de asumir matrices de tipo primitivo.

Mi código:

public static RouteValueDictionary ToRouteValueDictionaryWithCollection(this RouteValueDictionary routeValues) { RouteValueDictionary newRouteValues = new RouteValueDictionary(); foreach (var key in routeValues.Keys) { object value = routeValues[key]; if (value is IEnumerable && !(value is string)) { int index = 0; foreach (object val in (IEnumerable)value) { PropertyInfo[] properties = val.GetType().GetProperties(); foreach (PropertyInfo propInfo in properties) { newRouteValues.Add( String.Format("{0}[{1}].{2}", key, index, propInfo.Name), propInfo.GetValue(val)); } index++; } } else { newRouteValues.Add(key, value); } } return newRouteValues; }