一尘不染

ASP.NET MVC歧义操作方法

c#

我有两种冲突的操作方法。基本上,我希望能够使用两条不同的路线(通过项的ID或项的名称及其父项(在不同的父项中,项可以具有相同的名称))进入同一视图。搜索词可用于过滤列表。

例如…

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

这是我的动作方法(也有Remove动作方法)…

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

这是路线…

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

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

我理解为什么会发生错误,因为page参数可以为null,但是我无法找出解决此问题的最佳方法。一开始我的设计不好吗?我曾考虑过将`Method

1的签名扩展为包括搜索参数,并将逻辑Method #2`移到它们都将调用的私有方法中,但是我认为这不会真正解决歧义。

任何帮助将不胜感激。


实际解决方案 (基于李维斯的答案)

我添加了以下课程…

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

然后修饰动作方法…

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

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

阅读 220

收藏
2020-05-19

共1个答案

一尘不染

MVC不支持仅基于签名的方法重载,因此将失败:

public ActionResult MyMethod(int someInt) { /* ... */ }
public ActionResult MyMethod(string someString) { /* ... */ }

但是,它 确实 支持基于属性的方法重载:

[RequireRequestValue("someInt")]
public ActionResult MyMethod(int someInt) { /* ... */ }

[RequireRequestValue("someString")]
public ActionResult MyMethod(string someString) { /* ... */ }

public class RequireRequestValueAttribute : ActionMethodSelectorAttribute {
    public RequireRequestValueAttribute(string valueName) {
        ValueName = valueName;
    }
    public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo) {
        return (controllerContext.HttpContext.Request[ValueName] != null);
    }
    public string ValueName { get; private set; }
}

在上面的示例中,该属性只说“如果请求中存在键 xxx,
则此方法匹配”。如果更适合您的目的,您还可以按路由(controllerContext.RequestContext)中包含的信息进行筛选。

2020-05-19