I got an email today where someone had built a REST(ful/ish) API with ASP.NET Web API that had a customer who was against the idea of using GET, POST, PUT, and DELETE, and insisted that they only use GET and POST.
我今天收到一封电子邮件,其中有人使用ASP.NET Web API构建了REST(ful / ish)API,该客户的客户反对使用GET,POST,PUT和DELETE的想法,并坚持认为他们仅使用GET和POST。
Sometimes this is because of a browser or client limitaton, sometimes it's a really tense corporate firewall. They wanted to know what they could do.
有时是由于浏览器或客户端的限制,有时是真正紧张的公司防火墙。 他们想知道他们能做什么。
One thing you can do is to "tunnel" HTTP Methods inside another HTTP Header. Basically you have a header that says "No, seriously, I know I got here via a POST, but use this one instead." You would still POST, but then you'd have "X-HTTP-Method-Override:PUT" as a header.
您可以做的一件事是在另一个HTTP标头中“隧道化” HTTP方法。 基本上,您有一个标头,上面写着:“不,是的,我知道我是通过POST到达这里的,但是请改用它。” 您仍然可以进行POST,但随后会有“ X-HTTP-Method-Override:PUT”作为标题。
Here is a PUT in the Postman REST client:
这是Postman REST客户端中的PUT:
![image image](https://i-blog.csdnimg.cn/blog_migrate/41caf071e60f0303bb29695e067a490a.png)
So that's:
所以那是:
PUT /api/Person/4 HTTP/1.1
Host: localhost:10320
Content-Type: application/json
Cache-Control: no-cache
And here's the same PUT, except as a POST plus an X-HTTP-Method-Override header.
除了POST加上X-HTTP-Method-Override标头之外,这里是相同的PUT。
![image image](https://i-blog.csdnimg.cn/blog_migrate/5fabc90e5724e5100ac8138db40b1a62.png)
Raw, that's like this:
原始的是这样的:
POST /api/Person/4 HTTP/1.1
Host: localhost:10320
Content-Type: application/json
X-HTTP-Method-Override: PUT
Cache-Control: no-cache
Now, how do you get ASP.NET Web API to respect this new way to route things? You may have a Web API Controller like this:
现在,如何使ASP.NET Web API尊重这种新的路由方式? 您可能具有这样的Web API控制器:
public IEnumerable<Person> Get() { }
// GET api/person/5
public Person Get(int id) { }
// POST api/person
public void Post([FromBody]Person value) { }
// PUT api/person/5
public void Put(int id, [FromBody]Person value) { }
// DELETE api/person/5
public void Delete(int id) { }
And you likely don't want to change it. Make a MethodOverrideHandler like this one. You can add the code yourself, get it from a NuGet package, or use one from the WebAPIContrib project. It's up to you.
而且您可能不想更改它。 像这样制作一个MethodOverrideHandler。 您可以自己添加代码,从NuGet包中获取代码,或从WebAPIContrib项目中使用代码。 由你决定。
public class MethodOverrideHandler : DelegatingHandler
{
readonly string[] _methods = { "DELETE", "HEAD", "PUT" };
const string _header = "X-HTTP-Method-Override";
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
// Check for HTTP POST with the X-HTTP-Method-Override header.
if (request.Method == HttpMethod.Post && request.Headers.Contains(_header))
{
// Check if the header value is in our methods list.
var method = request.Headers.GetValues(_header).FirstOrDefault();
if (_methods.Contains(method, StringComparer.InvariantCultureIgnoreCase))
{
// Change the request method.
request.Method = new HttpMethod(method);
}
}
return base.SendAsync(request, cancellationToken);
}
}
You see it checks if it's a post, looks for the extra header, then changes the request's Method property after the message has been received, but before it's been sent through the pipeline. It'll show up on the right method just as if a PUT had been sent, because from its perspective, a PUT was sent.
您会看到它检查是否为帖子,查找额外的标题,然后在收到消息之后但在通过管道发送消息之前更改请求的Method属性。 它将像发送PUT一样显示在正确的方法上,因为从其角度来看,已发送PUT 。
You need to register this new MethodOverrideHandler in your WebApiConfig like this, just by adding to the MessageHandlers collection, next to the rest of the configuration and routing code.
您需要像这样在WebApiConfig中注册这个新的MethodOverrideHandler,只需将其添加到MessageHandlers集合中,其余配置和路由代码旁边即可。
public static void Register(HttpConfiguration config)
{
config.MessageHandlers.Add(new MethodOverrideHandler());
//OTHER REGULAR STUFF HERE
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
On the client side, you can keep sending a post with your .ajax call in jQuery, for example, just make sure the override header in there.
在客户端,您可以继续使用jQuery中的.ajax调用发送帖子,例如,只需确保其中的override标头即可。
$.ajax({
url: "http://localhost:10320/api/Person/4",
type: "POST",
data: JSON.stringify(whatever),
headers: {
"Content-Type": "application/json",
"X-HTTP-Method-Override": "PUT" },
})
That's the general idea, enjoy!
那是一般的想法,请尽情享受!