WebApi,听说过吧?呵呵。

感觉比WebService,WCF要强。尤其是那个啥WCF,啥鬼东西,真难懂。真难搞。真难用。

说比WebService要强,是因为不用在本地先生成个代理。而且XML也显得过于庞大。

用ASP.NET 编写 WebApi 的话,跟MVC差不多。生成的项目也有控制器,视图之类。只不过,其控制器继承的是ApiController。

还有一个不同的是,是不用写action的,只有controller。当然,你硬是要写也可以。但根据RESTful原则,WebApi提供的API方法名称应该纯粹是名词,而没有动词,系统根据请求方式来判断请求者意图,并执行相应操作。什么意思呢?

比如一个API 地址为

http://192.168.0.1/api/book/108

相应的方法为

    public class BookController : ApiController
{
public string Get(string id)
{//读取book信息
return "Get " + id;
}
public string Post([FromBody]object obj)
{//新增book
return "Post";
}
public string Put(int id,[FromBody]object obj)
{//修改book
return "Put " + id;
}
public string Delete(string id)
{//删除book
return "Delete " + id;
}
}

当请求方式为GET时,执行的是方法Get(),Post时,执行的是方法Post()。API地址就一个:

http://192.168.0.1/api/book/108

108是ID值。

而不必写成下面那么傻:

http://192.168.0.1/api/GetBook/108
http://192.168.0.1/api/DeleteBook/108

当然,RESTful原则是这么推荐,但现实往往比较骨感。因为许多网络环境并不支持PUT和DELETE的请求方式,只支持GET和POST。怪不得我调试的时候,GET和POST都可以,到了PUT和DELETE,都报405错误:方法不被允许。错误代码为4开头,说明是浏览器不支持。

幸而看了蒋金楠博客。解决方案如下:

//我们定义了如下一个HttpMethodOverrideHandler类型,它继承自DelegatingHandler。我们在重写的SendAsync方法中实现了对“X-HTTP-Method-Override”报头的提取和对HTTP方法的重写,最后调用基类的同名方法将处理后的请求传递给后续的HttpMessageHandler。
public class HttpMethodOverrideHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
IEnumerable<string> methodOverrideHeader;
if (request.Headers.TryGetValues("X-HTTP-Method-Override", out methodOverrideHeader))
{
request.Method = new HttpMethod(methodOverrideHeader.First());
}
return base.SendAsync(request, cancellationToken);
}
}

在api项目的global.asax.cs里调用这个类:

    public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes); //调用基类的同名方法将处理后的请求传递给后续的HttpMessageHandler。
GlobalConfiguration.Configuration.MessageHandlers.Add(new HttpMethodOverrideHandler());
}
}

这样,请求过来时,读取这些额外设置的报头,系统就能知道请求者的意图了。

前端调用方式如下:

<script type="text/javascript">
(function(){
$.ajax({
type: 'POST',//明地里用支持的HTTP请求方式
url: 'http://192.168.0.1/api/GetBook/108',
data: '{"name":"王小波文集"}',
contentType: "application/json; charset=utf-8",
dataType: 'json',
beforeSend: function (xhr) {
//暗地里写入额外的报头信息
xhr.setRequestHeader('X-HTTP-Method-Override', 'PUT');
},
success: function (results) {
alert(results);
},
error: function (ex) {
alert("错误:" + ex.statusText);
}
})
})();
</script>

服务器端请求也可以,看俺的单元测试代码:

 [TestClass()]
public class InterfaceControllerTests
{
string _baseurl = "http://192.168.0.1/api/GetBook/108";
public InterfaceControllerTests()
{ } [TestMethod()]
public void GetTest()
{
string url = _baseurl + "/1";
string re; using (WebClient webClient = new WebClient())
{
webClient.Encoding = Encoding.GetEncoding("utf-8");
webClient.Headers.Add("Content-Type", "application/x-www-form-urlencoded");//采取POST方式必须加的header,如果改为GET方式的话就去掉这句话即可
re = webClient.DownloadString(url);
} Assert.AreEqual("\"Get 1\"", re);
} [TestMethod()]
public void PostTest()
{
string url = _baseurl;
string postString = @"{""id"":108}";//这里即为传递的参数,可以用工具抓包分析,也可以自己分析,主要是form里面每一个name都要加进来
byte[] postData = Encoding.UTF8.GetBytes(postString);//编码,尤其是汉字,事先要看下抓取网页的编码方式
string re; using (WebClient webClient = new WebClient())
{
webClient.Encoding = Encoding.GetEncoding("utf-8");
webClient.Headers.Add("Content-Type", "application/json");//采取POST方式必须加的header,如果改为GET方式的话就去掉这句话即可
byte[] responseData = webClient.UploadData(url, "POST", postData);//得到返回字符流
re = Encoding.UTF8.GetString(responseData);//解码
} Assert.AreNotEqual(-1, re.IndexOf("Post"));
} [TestMethod()]
public void PutTest()
{
string url = _baseurl + "/109";
string postString = @"{""id"":109}";
byte[] postData = Encoding.UTF8.GetBytes(postString);
string re; using (WebClient webClient = new WebClient())
{
webClient.Encoding = Encoding.GetEncoding("utf-8");
webClient.Headers.Add("Content-Type", "application/json");
webClient.Headers.Add("X-HTTP-Method-Override", "PUT");
byte[] responseData = webClient.UploadData(url, "POST", postData);
re = Encoding.UTF8.GetString(responseData);
} Assert.AreNotEqual(-1, re.IndexOf("Put"));
} [TestMethod()]
public void DeleteTest()
{
string url = _baseurl + "/1";
string re; using (WebClient webClient = new WebClient())
{
webClient.Encoding = Encoding.GetEncoding("utf-8");
webClient.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
webClient.Headers.Add("X-HTTP-Method-Override", "DELETE");
re = webClient.DownloadString(url);
} Assert.AreNotEqual(-1, re.IndexOf("Delete"));
}
}

参考文章:

如果调用ASP.NET Web API不能发送PUT/DELETE请求怎么办?

ASP.NET for WebApi的更多相关文章

  1. ASP.NET 5 WebApi 返回 HttpResponseMessage

    首先,ASP.NET 5 没有了 MVC 和 WebApi 的区分,都属于 ASP.NET 5,从 Controller 的继承就可以看出,原来 ASP.NET WebApi 2 ValuesCont ...

  2. 让Asp.net mvc WebAPI 支持OData协议进行分页查询操作

    这是我在用Asp.net mvc WebAPI 支持 OData协议 做分页查询服务时的 个人拙笔. 代码已经开发到oschina上.有兴趣的朋友可以看看,欢迎大家指出不足之处. 看过了园子里的几篇关 ...

  3. asp.net core webapi之跨域(Cors)访问

    这里说的跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被当作 ...

  4. ASP.NET Core WebAPI 开发-新建WebAPI项目

    ASP.NET Core WebAPI 开发-新建WebAPI项目, ASP.NET Core 1.0 RC2 即将发布,我们现在来学习一下 ASP.NET Core WebAPI开发. 网上已经有泄 ...

  5. Asp.net Core WebApi 使用Swagger做帮助文档,并且自定义Swagger的UI

    WebApi写好之后,在线帮助文档以及能够在线调试的工具是专业化的表现,而Swagger毫无疑问是做Docs的最佳工具,自动生成每个Controller的接口说明,自动将参数解析成json,并且能够在 ...

  6. Asp.Net Core WebApi学习笔记(四)-- Middleware

    Asp.Net Core WebApi学习笔记(四)-- Middleware 本文记录了Asp.Net管道模型和Asp.Net Core的Middleware模型的对比,并在上一篇的基础上增加Mid ...

  7. Asp.net core WebApi 使用Swagger生成帮助页

    最近我们团队一直进行.net core的转型,web开发向着前后端分离的技术架构演进,我们后台主要是采用了asp.net core webapi来进行开发,开始每次调试以及与前端人员的沟通上都存在这效 ...

  8. ASP.Net Core WebApi几种版本控制对比

    版本控制的好处: (1)助于及时推出功能, 而不会破坏现有系统. (2)它还可以帮助为选定的客户提供额外的功能. API 版本控制可以采用不同的方式进行控制,方法如下: (1)在 URL 中追加版本或 ...

  9. .net异步性能测试(包括ASP.NET MVC WebAPI异步方法)

    很久没有写博客了,今年做的产品公司这两天刚刚开了发布会,稍微清闲下来,想想我们做的产品还有没有性能优化空间,于是想到了.Net的异步可以优化性能,但到底能够提升多大的比例呢?恰好有一个朋友正在做各种语 ...

  10. ASP.NET Core WebApi 返回统一格式参数(Json 中 Null 替换为空字符串)

    相关博文:ASP.NET Core WebApi 返回统一格式参数 业务场景: 统一返回格式参数中,如果包含 Null 值,调用方会不太好处理,需要替换为空字符串,示例: { "respon ...

随机推荐

  1. Nginx配置ThinkPHP和Laravel虚拟主机

    ThinkPHP server { listen 443 ssl; server_name abc.com; root /var/www/abc; ssl on; ssl_certificate /e ...

  2. linux网络原理

    1.ipconfig命令使用 显示所有正在启动的网卡的详细信息或设定系统中网卡的IP地址. 某一块网卡信息 打开或者关闭某一块网卡 2.ifup和ifdown ifup和ifdown分别是加载网卡信息 ...

  3. C第12章-----堆

    #include <stdio.h> #include <stdlib.h> //声明Person结构 //struct Person{ //    float heightI ...

  4. LeetCode01--寻找两个有序数组的中位数

    ''' 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 nu ...

  5. DEV Express中NavBarCointrol的使用

    尚未对内容进行删减,内容有偏差和冗余,谨慎阅读. 发现在后面,写在前面: 13,之前在Default模式下,之所以很多Appearance属性都起不到作用,是因为Control的LookAndFeel ...

  6. Python+selenium常用方法(Webdriver API)

    小编整理了目前学习的Python+selenium常用的一些方法函数,以后有新增再随时更新. 加载浏览器驱动: webdriver.Firefox() 打开页面:get() 关闭浏览器:quit() ...

  7. bzoj 1787 Meet 紧急集合

    Meet 紧急集合 这个题是在脖子oj(清北某奆佬给起的名字)八中oj(大视野在线评测)上的. 给出bzoj链接. 这个题还是求最近公共祖先的问题. 而该题不同于别的题,它是需要求三个点的最近公共祖先 ...

  8. 按Esc按钮关闭layer弹窗

    //按Esc关闭弹出框 $(document).ready(function () { }).keydown( function (e) { if (e.which === 27) {  layer. ...

  9. NYOJ-183赚钱啦,bellman//spfa水过,,题还是蛮变态的赶脚~~

    赚钱啦 时间限制:1000 ms  |  内存限制:65535 KB 难度:5 描述 某国家里有N个城市,分别编号为0~N-1,一个精明的商人准备从0号城市旅行到N-1号城市,在旅行的过程中,从一个城 ...

  10. .NET 调用java webservice保存datetime类型数据为空的解决办法

    问题描述:       用C#.NET调用Java开发的WebService时,先在客户端封装的带有int属性的对象,当将该对象传到服务器端时,服务器端可以得到 string类型的属性值,却不能得到i ...