Tengo dos métodos de acción que son contradictorios. Básicamente, quiero poder acceder a la misma vista usando dos rutas diferentes, ya sea por el ID de un elemento o por el nombre del elemento y el de su padre (los elementos pueden tener el mismo nombre en diferentes padres). Un término de búsqueda puede usarse para filtrar la lista.ASP.NET MVC métodos de acción ambiguos
Por ejemplo ...
Items/{action}/ParentName/ItemName
Items/{action}/1234-4321-1234-4321
Éstos son mis métodos de acción (también hay Remove
métodos de acción) ...
// Method #1
public ActionResult Assign(string parentName, string itemName) {
// Logic to retrieve item's ID here...
string itemId = ...;
return RedirectToAction("Assign", "Items", new { itemId });
}
// Method #2
public ActionResult Assign(string itemId, string searchTerm, int? page) { ... }
Y aquí son las rutas ...
routes.MapRoute("AssignRemove",
"Items/{action}/{itemId}",
new { controller = "Items" }
);
routes.MapRoute("AssignRemovePretty",
"Items/{action}/{parentName}/{itemName}",
new { controller = "Items" }
);
Entiendo por qué ocurre el error, ya que el parámetro page
puede ser nulo, pero no puedo encontrar la mejor manera de resolverlo. ¿Es mi diseño pobre para empezar? He pensado en extender la firma de Method #1
para incluir los parámetros de búsqueda y mover la lógica en Method #2
a un método privado que ambos llamarían, pero no creo que eso resuelva la ambigüedad.
Cualquier ayuda sería muy apreciada.
solución real (basado en la respuesta de Levi)
que añade la siguiente clase ...
public class RequireRouteValuesAttribute : ActionMethodSelectorAttribute {
public RequireRouteValuesAttribute(string[] valueNames) {
ValueNames = valueNames;
}
public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo) {
bool contains = false;
foreach (var value in ValueNames) {
contains = controllerContext.RequestContext.RouteData.Values.ContainsKey(value);
if (!contains) break;
}
return contains;
}
public string[] ValueNames { get; private set; }
}
y decorada los métodos de acción ...
[RequireRouteValues(new[] { "parentName", "itemName" })]
public ActionResult Assign(string parentName, string itemName) { ... }
[RequireRouteValues(new[] { "itemId" })]
public ActionResult Assign(string itemId) { ... }
Gracias por publicar la implementación real. Seguro que ayuda a personas con problemas similares. Como lo tuve hoy. :-P –
¡Asombroso! Sugerencia de cambio menor: (realmente útil) 1) params string [] valueNames para hacer que la declaración de atributo sea más concisa y (preferencia) 2) reemplace el cuerpo del método IsValidForRequest con 'return ValueNames.All (v => controllerContext.RequestContext.RouteData. Values.ContainsKey (v)); ' –
Hola Jon, creo que no entiendo nada, porque ¿dónde están los parámetros de consulta en RouteData? – fravelgue