【问题标题】:Why is the MVC action method selector not choosing my HttpPut action?为什么 MVC 操作方法选择器没有选择我的 HttpPut 操作?
【发布时间】:2024-05-15 18:50:02
【问题描述】:

给定以下路线:

context.MapRoute(null, "widgets", 
    new { controller = "Widgets", action = "Add" }, 
    new { httpMethod = new HttpMethodConstraint("PUT") });

还有以下控制器:

public class WidgetsController
{
    [HttpPut]
    public ActionResult Add(WidgetForm model)
    {
        return DoStuff(); // code here doesn't matter
    }
}

以及呈现以下表单的视图(使用HtmlHelper.@Html.HttpMethodOverride(HttpVerbs.Put):

<form action="/widgets" method="post">
    <!-- many form elements, then -->
    <input name="X-HTTP-Method-Override" type="hidden" value="PUT" />
</form>

提交表单时,MVC动作方法选择器没有选择上述动作方法。如果我在左大括号上设置断点,它永远不会被命中。在浏览器中,它返回 404 页面(我相信这是默认的 ActionNotFound 行为)。

但是,操作方法选择器确实选择了具有以下路由的 Add HttpPut 方法:

context.MapRoute(null, "widgets", 
    new { controller = "Widgets", action = "Add" }, 
    new { httpMethod = new HttpMethodConstraint("PUT", "POST") });

这似乎不对……是吗?在我看来,我应该能够在没有 POST 约束的情况下做到这一点。 action 方法没有用 HttpPost 修饰,那么为什么需要 POST 约束呢?

【问题讨论】:

    标签: asp.net-mvc routing http-post http-put actionmethod


    【解决方案1】:

    没错。更深入地了解它在 MVC 管道中的工作原理,实际上是 MVC(ActionMethodSelectorAttribute、ActionInvoker、RedirectToRoute)处理这个问题,而不是 RouteModule。

    所以在路由模块中,它仍然是一个“POST”请求,而不是一个“PUT”。

    【讨论】:

    • 我不认为我可以使用 PUT 作为表单方法。我使用@Html.BeginForm 来呈现表单,它的参数采用Post 或Get 的枚举。 http 规范中没有关于仅支持 post 和 get 的浏览器表单的内容吗?
    • 深入了解它在 MVC 管道中是如何工作的,实际上是 MVC(ActionMethodSelectorAttribute、ActionInvoker、RedirectToRoute)处理这个问题,而不是 RouteModule
    • 对,我知道这是动作方法选择器(见原始问题标题)。所以我应该同时拥有 POST 和 PUT?
    • 如果你不添加“POST”约束,那么路由将不匹配。对路由模块来说,这是一个 POST 请求,还不是 PUT。
    最近更新 更多