我正在使用ASP.NET MVC实现RESTful API的原型,除了奇怪的bug之外,我已经实现了我在开始时提出的所有要求,除了调用者能够使用{ {1}}自定义标头覆盖HTTP方法。
我想要的是以下要求......
X-HTTP-Method-Override
...将被调度到我的控制器方法,该方法实现GET /someresource/123 HTTP/1.1
X-HTTP-Method-Override: DELETE
功能而不是该操作的DELETE
功能(假设有多个方法实现该操作,并且它们已被标记具有不同的GET
属性)。因此,考虑到以下两种方法,我希望将上述请求分派到第二个方法:
[AcceptVerbs]
有人知道这是否可行?这样做会有多少工作......?
答案 0 :(得分: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);
答案 1 :(得分: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的related post。
希望这有助于某人。
答案 2 :(得分:3)
插入表单:
<%= Html.HttpMethodOverride(HttpVerbs.Delete) %>
答案 3 :(得分:2)
这次谈话有点旧,但我想用mvc 2分享我发现的内容:
浏览器支持两个HTTP谓词:GET和POST,但ASP.NET MVC 2允许您使用Html.HttpMethodOverride辅助方法模拟Put,Get和Delete。在内部,这通过在X-HTTP-Method-Override表单字段中发送动词来工作。 HttpMethodOverride的行为由[AcceptVerbs]属性以及新的较短动词属性使用:
例如,行动声明:
[ActionName("someresource")]
[HttpDelete]
public ActionResult DeleteSomeResource()
应对您的X-HTTP-Method-Override设置为Delete的获取请求负责。
答案 4 :(得分:1)
你看过Simply Restful Routing了吗?它已经做到了。
2010年2月编辑添加:方法覆盖内置于MVC 2中。
答案 5 :(得分:1)
我很惊讶这还没有被提及,但ASP.NET MVC本身支持X-HTTP-Method-Override并且至少从版本2开始这样做。没有必要编写自定义代码来处理此
它的工作方式如下:
在AcceptVerbsAttribute内部(也由[HttpPut],[HttpPost]等代理),有一个IsValidForRequest方法。在该方法中,它使用Request.GetHttpMethodOverride()进行检查,该方法返回具有以下条件的正确覆盖HTTP方法:
如果你真的很好奇,这里是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;
}
}
答案 6 :(得分:0)
X-HTTP-Method-Override
是自定义标头,您的网络容器很可能不支持。
你是从网页上调用的吗?如果是这样,您应该将XmlHttpRequest
与DELETE
(或您想要的任何动词)一起使用。更好的是,使用JS框架为您做繁重的工作。
答案 7 :(得分:0)
您可以创建一个实现OnActionExecuting
的ActionFilter,它在调用控制器操作之前触发。然后,您可以询问请求标头,并根据X-HTTP-Method-Override
标头的值重定向(如果存在)。