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...

Items/{action}/ParentName/ItemName
Items/{action}/1234-4321-1234-4321

Oto moje metody działania (są teżRemove metody akcji) ...

// 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) { ... }

A oto trasy ...

routes.MapRoute("AssignRemove",
                "Items/{action}/{itemId}",
                new { controller = "Items" }
                );

routes.MapRoute("AssignRemovePretty",
                "Items/{action}/{parentName}/{itemName}",
                new { controller = "Items" }
                );

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 #1podpis 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ę ...

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; }
}

A następnie udekorował metody działania ...

[RequireRouteValues(new[] { "parentName", "itemName" })]
public ActionResult Assign(string parentName, string itemName) { ... }

[RequireRouteValues(new[] { "itemId" })]
public ActionResult Assign(string itemId) { ... }