Wieloznaczne metody działania ASP.NET MVC
Mam dwie sprzeczne metody działania. Zasadniczo chcę być w stanie dostać się do tego samego widoku za pomocą dwóch różnych tras, albo przez identyfikator przedmiotu, albo przez nazwę przedmiotu i jego rodziców (przedmioty mogą mieć tę samą nazwę dla różnych rodziców). Wyszukiwanego terminu można użyć do filtrowania listy.
Na przykład...
<code>Items/{action}/ParentName/ItemName Items/{action}/1234-4321-1234-4321 </code>
Oto moje metody działania (są teżRemove
metody akcji) ...
<code>// 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) { ... } </code>
A oto trasy ...
<code>routes.MapRoute("AssignRemove", "Items/{action}/{itemId}", new { controller = "Items" } ); routes.MapRoute("AssignRemovePretty", "Items/{action}/{parentName}/{itemName}", new { controller = "Items" } ); </code>
Rozumiem, dlaczego błąd występuje, ponieważpage
parametr może mieć wartość NULL, ale nie mogę znaleźć najlepszego sposobu na jego rozwiązanie. Czy mój projekt jest kiepski? Myślałem o przedłużeniuMethod #1
podpis do uwzględnienia parametrów wyszukiwania i przeniesienia logikiMethod #2
do prywatnej metody, którą oboje dzwoniliby, ale nie wierzę, że to rzeczywiście rozwiąże dwuznaczność.
Każda pomoc byłaby bardzo mile widziana.
Rzeczywiste rozwiązanie (na podstawie odpowiedzi Levi'ego)
Dodałem następującą klasę ...
<code>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; } } </code>
A następnie udekorował metody działania ...
<code>[RequireRouteValues(new[] { "parentName", "itemName" })] public ActionResult Assign(string parentName, string itemName) { ... } [RequireRouteValues(new[] { "itemId" })] public ActionResult Assign(string itemId) { ... } </code>