5

我正在使用 ASP.NET MVC 实现一个 RESTful API 的原型,除了这里和那里的奇怪错误之外,我已经实现了我在开始时提出的所有要求,除了调用者能够使用X-HTTP-Method-Override自定义标头覆盖HTTP 方法。

我想要的是以下请求......

GET /someresource/123 HTTP/1.1
X-HTTP-Method-Override: DELETE

...将被分派到实现DELETE功能而不是该GET操作的功能的控制器方法(假设有多个方法实现该操作,并且它们标记有不同的[AcceptVerbs]属性)。因此,鉴于以下两种方法,我希望将上述请求发送到第二种方法:

[ActionName("someresource")]
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult GetSomeResource(int id) { /* ... */ }

[ActionName("someresource")]
[AcceptVerbs(HttpVerbs.Delete)]
public ActionResult DeleteSomeResource(int id) { /* ... */ }

有人知道这是否可能吗?这样做需要做多少工作......?

4

8 回答 8

5

您将无法按原样使用 [AcceptVerbs] 属性,因为它与请求的实际 HTTP 动词相关联。幸运的是 [AcceptVerbs] 属性非常简单;您可以在以下位置查看自己的来源http://www.codeplex.com/aspnet/SourceControl/changeset/view/21528#266431

简而言之,子类 AcceptsVerbsAttribute 并覆盖 IsValidForRequest() 方法。实现将类似于以下内容:

string incomingVerb = controllerContext.HttpContext.Request.Headers["X-HTTP-Method-Override"] ?? controllerContext.HttpContext.Request.Method;
return Verbs.Contains(incomingVerb, StringComparer.OrdinalIgnoreCase);
于 2009-01-29T07:06:25.437 回答
3

利威尔的回答很棒。此外,我在自定义 AcceptsVerbsAttribute 中添加了一个检查,该检查还检查了 FORM 集合,因此您可以简单地放置一个隐藏的输入来触发 DELETE(类似于 MVC 2 的Html.HttpMethodOverride(HttpVerbs.Delete))。

<input name="X-HTTP-Method-Override" type="hidden" value="DELETE" />

将incomingVerb 赋值更改为:

string incomingVerb = controllerContext.HttpContext.Request.Headers["X-HTTP-Method-Override"] ?? controllerContext.HttpContext.Request.Form["X-HTTP-Method-Override"] ??controllerContext.HttpContext.Request.HttpMethod;

小心这种方法!请参阅 Stephen Walther 的相关帖子

希望这可以帮助某人。

于 2010-02-18T00:40:44.910 回答
3

插入表格:

<%= Html.HttpMethodOverride(HttpVerbs.Delete) %>
于 2010-06-07T04:03:09.563 回答
2

这个对话有点老了,但我想分享一下我使用 mvc 2 发现的内容:

浏览器支持两个 HTTP 动词:GET 和 POST,但 ASP.NET MVC 2 允许您使用 Html.HttpMethodOverride 辅助方法模拟 Put、Get 和 Delete。在内部,这是通过在 X-HTTP-Method-Override 表单字段中发送动词来实现的。[AcceptVerbs] 属性以及新的较短动词属性使用 HttpMethodOverride 的行为:

例如,动作声明:

[ActionName("someresource")]
[HttpDelete]
public ActionResult DeleteSomeResource()

应该对将 X-HTTP-Method-Override 设置为 Delete 的 get 请求负责。

于 2010-10-21T20:12:46.583 回答
2

我很惊讶这还没有被提及,但是 ASP.NET MVC 本身就支持 X-HTTP-Method-Override 并且至少从版本 2 开始就已经这样做了。不需要编写自定义代码来处理这个问题。

它以下列方式工作:

在 AcceptVerbsAttribute(也由 [HttpPut]、[HttpPost] 等代理)内部,有一个 IsValidForRequest 方法。在该方法中,它使用 Request.GetHttpMethodOverride() 进行检查,该方法返回具有以下条件的正确覆盖的 HTTP 方法:

  • 仅在 POST 请求中支持覆盖。所有其他都被忽略。
  • 如果 X-HTTP-Method-Override 值为 GET 或 POST,则会被忽略。这是有道理的,因为您永远不需要覆盖这些值。
  • 它在此优先级的以下位置查找 X-HTTP-Method-Override:1)HTTP 标头 2)表单正文 3)查询字符串

如果你真的很好奇,下面是 GetHttpMethodOverride() 的样子(来自 MVC 3 的源代码):

public static class HttpRequestExtensions {
    internal const string XHttpMethodOverrideKey = "X-HTTP-Method-Override";

    public static string GetHttpMethodOverride(this HttpRequestBase request) {
        if (request == null) {
            throw new ArgumentNullException("request");
        }

        string incomingVerb = request.HttpMethod;

        if (!String.Equals(incomingVerb, "POST", StringComparison.OrdinalIgnoreCase)) {
            return incomingVerb;
        }

        string verbOverride = null;
        string headerOverrideValue = request.Headers[XHttpMethodOverrideKey];
        if (!String.IsNullOrEmpty(headerOverrideValue)) {
            verbOverride = headerOverrideValue;
        }
        else {
            string formOverrideValue = request.Form[XHttpMethodOverrideKey];
            if (!String.IsNullOrEmpty(formOverrideValue)) {
                verbOverride = formOverrideValue;
            }
            else {
                string queryStringOverrideValue = request.QueryString[XHttpMethodOverrideKey];
                if (!String.IsNullOrEmpty(queryStringOverrideValue)) {
                    verbOverride = queryStringOverrideValue;
                }
            }
        }
        if (verbOverride != null) {
            if (!String.Equals(verbOverride, "GET", StringComparison.OrdinalIgnoreCase) &&
                !String.Equals(verbOverride, "POST", StringComparison.OrdinalIgnoreCase)) {
                incomingVerb = verbOverride;
            }
        }
        return incomingVerb;
    }
}
于 2013-05-31T14:09:36.623 回答
1

你看过简单的宁静路由吗?它已经这样做了。

2010 年 2 月编辑添加:方法覆盖内置于 MVC 2 中。

于 2009-01-22T14:13:37.913 回答
0

X-HTTP-Method-Override是一个自定义标头,您的 Web 容器很可能不支持。

你是从网页调用这个吗?如果是这样,您可能应该使用XmlHttpRequestwith DELETE(或任何您想要的动词)。更好的是,使用 JS 框架为您完成繁重的工作。

于 2009-01-21T23:57:49.513 回答
0

您可以创建一个实现的 ActionFilter OnActionExecuting,它在调用控制器操作之前触发。然后,您可以询问请求标头,并根据标头的值进行重定向X-HTTP-Method-Override(如果存在)。

于 2009-01-22T00:05:41.883 回答