Mehrdeutige ASP.NET MVC-Aktionsmethoden

Ich habe zwei Aktionsmethoden, die in Konflikt stehen. Grundsätzlich möchte ich in der Lage sein, auf zwei verschiedenen Wegen zur gleichen Ansicht zu gelangen, entweder anhand der ID eines Elements oder anhand des Namens des Elements und des übergeordneten Elements (Elemente können über verschiedene übergeordnete Elemente hinweg denselben Namen haben). Ein Suchbegriff kann zum Filtern der Liste verwendet werden.

Zum Beispiel...

<code>Items/{action}/ParentName/ItemName
Items/{action}/1234-4321-1234-4321
</code>

Hier sind meine Aktionsmethoden (gibt es auch)Remove Aktionsmethoden) ...

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

Und hier sind die Routen ...

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

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

Ich verstehe, warum der Fehler auftritt, da diepage Parameter kann null sein, aber ich kann nicht herausfinden, wie man es am besten löst. Ist mein Design von Anfang an schlecht? Ich habe darüber nachgedacht zu verlängernMethod #1Unterschrift, um die Suchparameter einzuschließen und die Logik einzufügenMethod #2 zu einer privaten Methode heraus, die sie beide aufrufen würden, aber ich glaube nicht, dass das die Mehrdeutigkeit wirklich auflöst.

Jede Hilfe wäre sehr dankbar.

Tatsächliche Lösung (basierend auf Levis Antwort)

Ich habe folgende Klasse hinzugefügt ...

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

Und dann die Aktionsmethoden dekoriert ...

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

[RequireRouteValues(new[] { "itemId" })]
public ActionResult Assign(string itemId) { ... }
</code>

Antworten auf die Frage(5)

Ihre Antwort auf die Frage