Ho due metodi di azione che sono in conflitto. Fondamentalmente, voglio essere in grado di ottenere la stessa vista utilizzando due percorsi diversi, sia per l'ID di un articolo o per il nome dell'oggetto e dei suoi genitori (gli articoli possono avere lo stesso nome su genitori diversi). Un termine di ricerca può essere utilizzato per filtrare l'elenco.Metodi di azione ambigua di ASP.NET MVC
Per esempio ...
Items/{action}/ParentName/ItemName
Items/{action}/1234-4321-1234-4321
Qui sono i miei metodi di azione (ci sono anche Remove
metodi d'azione) ...
// 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) { ... }
E qui sono gli itinerari ...
routes.MapRoute("AssignRemove",
"Items/{action}/{itemId}",
new { controller = "Items" }
);
routes.MapRoute("AssignRemovePretty",
"Items/{action}/{parentName}/{itemName}",
new { controller = "Items" }
);
Capisco perché si sta verificando l'errore, dal momento che il parametro page
può essere nullo, ma non riesco a capire il modo migliore per risolverlo. Il mio design è scarso per cominciare? Ho pensato di estendere la firma di Method #1
per includere i parametri di ricerca e spostare la logica in Method #2
in un metodo privato che entrambi chiamerebbero, ma non credo che in realtà risolverà l'ambiguità.
Qualsiasi aiuto sarebbe molto apprezzato.
Actual Solution (in base alla risposta di Levi)
ho aggiunto la seguente classe ...
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; }
}
E poi decorato i metodi di azione ...
[RequireRouteValues(new[] { "parentName", "itemName" })]
public ActionResult Assign(string parentName, string itemName) { ... }
[RequireRouteValues(new[] { "itemId" })]
public ActionResult Assign(string itemId) { ... }
Grazie per aver pubblicato l'implementazione effettiva. Di certo aiuta le persone con problemi simili. Come ho avuto oggi. :-P –
Incredibile! Suggerimento per il cambiamento minore: (molto utile) 1) params string [] valoreNomi per rendere più concisa la dichiarazione dell'attributo e (preferenza) 2) sostituire il corpo del metodo IsValidForRequest con 'return ValueNames.All (v => controllerContext.RequestContext.RouteData. Values.ContainsKey (v)); ' –
Ciao Jon, penso di non sottovalutare qualcosa, perché dove sono i parametri di query in RouteData? – fravelgue