如果调用ASP.NET Web API不能发送PUT/DELETE请求怎么办?
理想的RESTful Web API采用面向资源的架构,并使用请求的HTTP方法表示针对目标资源的操作类型。但是理想和现实是有距离的,虽然HTTP协议提供了一系列原生的HTTP方法,但是在具体的网络环境中,很多是不支持的。比如有的浏览器只能发送GET和POST请求,客户端发送的PUT请求也不一定能够被服务器理解。除了客户端和服务器对请求采用的HTTP方法的制约外,像代理(Proxy)、网关(Gateway)等这些中间部件都具有针对HTTP方法的限制。[本文已经同步到《How ASP.NET Web API Works?》]
我们一般采用“HTTP方法重写”的方式来解决这个问题。具体来说,Web API依然针对标准HTTP方法具有的资源操作语义来定义。客户端发送的请求只能采用网络允许的HTTP方法(一般来说,GET和POST总是被支持的),但是与资源操作方式相匹配的HTTP方法名称会通过一个请求报头发送给服务器。服务器在根据请求实施操作选择之前,它会提取该请求报头携带的HTTP方法,请求自身的HTTP方法会被它重写或者覆盖。按照约定,我们将这个携带“覆盖当前请求HTTP方法”的报头命名为“X-HTTP-Method-Override”。
ASP.NET Web API采用管道式的设计,这个旨在解决部分HTTP方法在网络环境中不被支持的HTTP方法重写机制可以很容易地通过自定义HttpMessageHandler来实现。具体来说,由于消息处理管道根据表示请求的HttpRequestMessage对象的Method属性确定请求采用的HTTP方法,并且这是一个可读写的属性,如果我们利用注册的HttpMessageHandler根据“X-HTTP-Method-Override”报头值来设置当前HttpRequestMessage的Method属性,那么管道后续部分将会针对这个覆盖的HTTP方法进行处理。
为此我们定义了如下一个HttpMethodOverrideHandler类型,它继承自DelegatingHandler。我们在重写的SendAsync方法中实现了对“X-HTTP-Method-Override”报头的提取和对HTTP方法的重写,最后调用基类的同名方法将处理后的请求传递给后续的HttpMessageHandler。
1: public class HttpMethodOverrideHandler: DelegatingHandler
2: {
3: protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
4: {
5: IEnumerable<string> methodOverrideHeader;
6: if (request.Headers.TryGetValues("X-HTTP-Method-Override", out methodOverrideHeader))
7: {
8: request.Method = new HttpMethod(methodOverrideHeader.First());
9: }
10: return base.SendAsync(request, cancellationToken);
11: }
12: }
我们在一个空ASP.NET Web API应用中定义了如下一个继承自ApiController的DemoController,并在其中定义了4个用于返回自身方法名称的Action方法(Get、Post、Put和Delete)。按照ASP.NET Web API默认提供的HTTP方法与Action方法名称之间的映射机制,这4个Action方法支持HTTP方法与自身的方法名称一致。
1: public class DemoController : ApiController
2: {
3: public string Get()
4: {
5: return "Get";
6: }
7:
8: public string Post()
9: {
10: return "Post";
11: }
12:
13: public string Put()
14: {
15: return "Put";
16: }
17:
18: public string Delete()
19: {
20: return "Delete";
21: }
22: }
在Global.asax文件中,我们采用如下的代码将一个HttpMethodOverrideHandler对象注册到ASP.NET Web API的消息处理管道中。我们采用IIS Express作为宿主,并将采用的端口固定为“3721”。
1: public class WebApiApplication : System.Web.HttpApplication
2: {
3: protected void Application_Start()
4: {
5: GlobalConfiguration.Configuration.MessageHandlers.Add(new HttpMethodOverrideHandler());
6: //其他操作
7: }
8: }
我们创建一个控制台应用作为调用Web API的客户端程序。如下面的代码片断所示,我们定义了一个辅助方法InvokeWebApi根据提供的HttpClient对象和请求采用的HTTP方法进行Web API的调用。在该方法中,我们根据指定的HTTP方法创建了一个指向目标Web API的HttpRequestMessage对象,并将其作为参数调用HttpClient对象的SendAsync方法对目标Web API发起调用。Web API成功调用后会得到最终被执行的目标Action方法的名称,我们将它连同当前请求采用的HTTP方法和“X-HTTP-Method-Override”报头值打印在控制台上。
1: class Program
2: {
3: static void Main(string[] args)
4: {
5: HttpClient httpClient1 = new HttpClient();
6: HttpClient httpClient2 = new HttpClient();
7: HttpClient httpClient3 = new HttpClient();
8: HttpClient httpClient4 = new HttpClient();
9:
10: httpClient3.DefaultRequestHeaders.Add("X-HTTP-Method-Override", "PUT");
11: httpClient4.DefaultRequestHeaders.Add("X-HTTP-Method-Override", "DELETE");
12:
13: Console.WriteLine("{0,-7}{1,-24}{2,-6}", "Method", "X-HTTP-Method-Override", "Action");
14: InvokeWebApi(httpClient1, HttpMethod.Get);
15: InvokeWebApi(httpClient2, HttpMethod.Post);
16: InvokeWebApi(httpClient3, HttpMethod.Post);
17: InvokeWebApi(httpClient4, HttpMethod.Post);
18:
19: Console.Read();
20: }
21:
22: async static void InvokeWebApi(HttpClient httpClient, HttpMethod method)
23: {
24: string requestUri = "http://localhost:3721/api/demo";
25: HttpRequestMessage request = new HttpRequestMessage(method, requestUri);
26: HttpResponseMessage response = await httpClient.SendAsync(request);
27: IEnumerable<string> methodsOverride;
28: httpClient.DefaultRequestHeaders.TryGetValues("X-HTTP-Method-Override", out methodsOverride);
29: string actionName = response.Content.ReadAsStringAsync().Result;
30: string methodOverride = methodsOverride == null ? "N/A" : methodsOverride.First();
31: Console.WriteLine("{0,-7}{1,-24}{2,-6}", method, methodOverride, actionName.Trim('"'));
32: }
33: }
在Main方法中,我们创建了4个HttpClient对象(httpClient1、httpClient2、httpClient3和httpClient4),并将“X-HTTP-Method-Override”报头添加到httpClient3和httpClient4的默认报头集合中,指定的HTTP方法分别是“PUT”和“DELETE”。我们将这4个HttpClient对象作为参数调用辅助方法InvokeWebApi对目标Web API发起4次调用,除了第1次(由于InvokeWebApi是一个异步方法,代码中的第一次调用并不意味着它首先被执行,更不能确保针对它的Web API调用率先完成)采用GET请求之外,其余请求均采用POST方法。
在启动Web API宿主程序后运行客户端控制台应用,我们会得到如下所示的输出结果。我们可以清楚地看到在请求不具有“X-HTTP-Method-Override”报头的情况下,执行的Action方法取决于请求采用的HTTP方法。反之,如果请求通过“X-HTTP-Method-Override”报头携带了相应的HTTP方法,它将用于目标Action方法的选择。这一切均是HttpMethodOverrideHandler这个自定义HttpMessageHandler的功劳。
1: Method X-HTTP-Method-Override Action
2: POST PUT Put
3: GET N/A Get
4: POST N/A Post
5: POST DELETE Delete
如果调用ASP.NET Web API不能发送PUT/DELETE请求怎么办?的更多相关文章
- 如果调用.net core Web API不能发送PUT/DELETE请求怎么办?
通过阅读大佬的文章 http://www.cnblogs.com/artech/p/x-http-method-override.html想到的 通过注册中间件来解决这个问题 public void ...
- MVC项目实践,在三层架构下实现SportsStore-09,ASP.NET MVC调用ASP.NET Web API的查询服务
ASP.NET Web API和WCF都体现了REST软件架构风格.在REST中,把一切数据视为资源,所以也是一种面向资源的架构风格.所有的资源都可以通过URI来唯一标识,通过对资源的HTTP操作(G ...
- 通过HttpClient 调用ASP.NET Web API
在前面两篇文章中我们介绍了ASP.NET Web API的基本知识和原理,并且通过简单的实例了解了它的基本(CRUD)操作.我们是通过JQuery和Ajax对Web API进行数据操作.这一篇我们来介 ...
- 如何通过js跨域调用ASP.NET Web API (请问如何实现在javascript中通过http get的方式跨域调用ASP.NET Web API?)
客户端js无需任何专门设置,使用通常的ajax调用即可: $.ajax({ url: '跨域URL', type: 'get', dataType: 'json', success: function ...
- How ASP.NET Web API 2.0 Works?[持续更新中…]
一.概述 RESTful Web API [Web标准篇]RESTful Web API [设计篇] 在一个空ASP.NET Web项目上创建一个ASP.NET Web API 2.0应用 二.路由 ...
- ASP.NET Web API标准的“管道式”设计
ASP.NET Web API的核心框架是一个消息处理管道,这个管道是一组HttpMessageHandler的有序组合.这是一个双工管道,请求消息从一端流入并依次经过所有HttpMessageHan ...
- Self Host模式下的ASP. NET Web API是如何进行请求的监听与处理的?
构成ASP.NET Web API核心框架的消息处理管道既不关心请求消息来源于何处,也不需要考虑响应消息归于何方.当我们采用Web Host模式将一个ASP.NET应用作为目标Web API的宿主时, ...
- 使用ASP.NET web API创建REST服务(二)
Creating a REST service using ASP.NET Web API A service that is created based upon the architecture ...
- 使用ASP.NET web API创建REST服务(三)
本文档来源于:http://www.cnblogs.com/madyina/p/3390773.html Creating a REST service using ASP.NET Web API A ...
随机推荐
- HTTPS和HTTP的区别(转)
HTTPS和HTTP的区别 超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信 息.HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器 ...
- 【Hibernate框架】关联映射(一对多,多对一)
根据我们的总结计划,上篇文章我们总结了有关于一对一映射相关知识,接下来,我们进行下一个阶段,一对多.多对一映射相关知识. 场景设定: 国家规定,一个人只能在一个公司上班,一个公司可以拥有很多员工.我们 ...
- jquery轮播图详解,40行代码即可简单解决。
我在两个月以前没有接触过html,css,jquery,javascript.今天我却在这里分享一篇技术贴,可能在技术大牛面前我的文章漏洞百出,也请斧正. 可以看出来,无论是div+css布局还是jq ...
- Java设置session超时(失效)的三种方式
1. 在web容器中设置(此处以tomcat为例) 在tomcat-6.0\conf\web.xml中设置,以下是tomcat 6.0中的默认配置: <!-- ================= ...
- iOS 删除、重新排序xcdatamodel
找到Xcode项目文件.xcodeproj,查看包内容. 里面有project.pbxproj,用文本编辑器打开. 找到类似如下内容段: /* Begin XCVersionGroup section ...
- JavaScript中严格模式"use strict";需注意的几个雷区:
1.with语句会抛错误 2.未声明的变量被赋值会报错 3.arguments在严格模式下变为静态,传入的参数与arguments无关系 4.delete会报错 5.对象的重复属性名会报错 6.禁止八 ...
- C#与C/C++的交互zz
C#与C++交互,总体来说可以有两种方法: 利用C++/CLI作为代理中间层 利用PInvoke实现直接调用 第一种方法:实现起来比较简单直观,并且可以实现C#调用C++所写的类,但是问题是MONO构 ...
- maven构建简单的web项目
把jdk给换掉 项目修改好了以后写个页面测试一下,结果正常 下面应该添加依赖让web项目一步步丰满起来. 0-添加依赖 1-建一个servlet 2-web.xml中添加servlet声明 3-重新运 ...
- SqlServer windowss身份登陆和sa身份登陆
今天重新装了系统,但是计算机名变了,于是修改了计算机名,然后装了SQLSEVER,安装完成后登录,发现无论用WINDOWS身份还是SQLSERVER身份都登录不了 1.先说说sqlserver身份登录 ...
- #研发解决方案#iDB-数据库自动化运维平台
郑昀 创建于2015/12/2 最后更新于2015/12/2 关键词:数据库,MySQL,自动化运维,AutoDDL,刷库,帐号授权,审核,回滚 提纲: 数据库自动化运维什么?别人家是怎么玩的? 我们 ...