c# - ASP.NET MVC 不明确的操作方法

标签 c# asp.net-mvc asp.net-mvc-routing

我有两个相互冲突的操作方法。基本上,我希望能够使用两条不同的路线到达相同的 View ,通过项目的 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 中的逻辑移到它们都将调用的私有(private)方法中,但是我不认为这会真正解决歧义。

如有任何帮助,我们将不胜感激。


实际解决方案(基于 Levi 的回答)

我添加了以下类...

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

然后装饰 Action 方法...

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

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

最佳答案

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) 中包含的信息进行过滤。

关于c# - ASP.NET MVC 不明确的操作方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1045316/

相关文章:

c# - 为什么我应该只在应用程序生命周期的早期创建 MemoryCache?

asp.net-mvc - 如何在 Visual Studio MVC View 中关闭大括号和编码元素的自动更正

ASP.NET MVC 包罗万象的路由

asp.net-mvc-routing - 使用新的 "[controller]/[action]" token 和区域的 MVC 6 属性路由

c# - 有没有一种方法可以轻松地将大量依赖于 SqlConnection 的代码切换到 MySqlConnection

c# - 当使用任务管理器暂停特定应用程序进程时如何捕获事件?

javascript - 如何在 Javascript 中引用 MVC 内容文件夹

c# - 哪个效率更高 : traditional routing or attribute routing?

c# - 在 C# 中实现标记系统的最佳方法是什么(没有数据库;没有 asp.net)?

c# - ASP.NET MVC 表单问题