ASP.NET Web API 2 的返回结果
原文地址:
httpresponsemessage
httpresponsemessage是asp.net web api 的标准返回值可以直接将转换为 http 响应消息,那为什么我们不推荐使用httpresponsemessage,主要是因为用起来比较麻烦,当然httpresponsemessage提供大量控制的响应消息用来操作设置的缓存控制标头。为什么说httpresponsemessage是asp.net web api 的标准返回值,最后再讲,先看看如何使用httpresponsemessage作为返回值。
public httpresponsemessage get() { httpresponsemessage response = request.createresponse(httpstatuscode.accepted, "value"); //设置内容和编码 response.content = new stringcontent("link sucess", encoding.bigendianunicode); response.headers.cachecontrol = new cachecontrolheadervalue() { maxage = timespan.fromminutes(10),//设置缓存 }; return response; }
http 响应:
http/1.1 202 accepted cache-control: max-age=1200 content-length: 22 content-type: text/plain; charset=utf-16 server: microsoft-iis/10.0 x-aspnet-version: 4.0.30319 x-sourcefiles: =?utf-8?b?rtpcz2l0shvixfdlykfqsvn0dwr5qxbwbgljyxrpb25cv2viqvbju3r1zhlbchbsawnhdglvblxhcglcumv0dxjuvmfsdwu=?= x-powered-by: asp.net
httpresponsemessage作为返回值使用的太少,我除了下载文件外基本没用到过,
public httpresponsemessage downloadfile(string filename) { string filepath = httpcontext.current.server.mappath("/") + "files\\" + filename; filestream stream = new filestream(filepath, filemode.open); httpresponsemessage response = new httpresponsemessage(httpstatuscode.ok); response.content = new streamcontent(stream); response.content.headers.contenttype = new mediatypeheadervalue("application/octet-stream"); response.content.headers.contentdisposition = new contentdispositionheadervalue("attachment") { filename = httputility.urlencode(filename) }; response.headers.add("access-control-expose-headers", "filename"); response.headers.add("filename", httputility.urlencode(filename)); return response; }
ihttpactionresult
ihttpactionresult web api 2 中引入了接口。 从根本上来说,用于将其他类型的值转换为httpresponsemessage类型值的工厂。果控制器操作返回ihttpactionresult,web api 调用executeasync方法创建httpresponsemessage。 然后它会将转换httpresponsemessage到 http 响应消息。我个人比较用的多。使用ihttpactionresult:
- 测试时更加简单方便。
- 在单独的类创建 http 响应的常见逻辑,响应的内容为httpresponsemessage。
- 通过隐藏构造响应的低级细节,使控制器操作的意图更加清晰。
下面是一个和返回值为void一样功能的voiresult,该类实现了ihttpactionresult仅返回状态代码 204 (无内容) 的空 http 响应。
/// <summary> /// 一个无响应内容的响应信息 /// </summary> public class voidresult : ihttpactionresult { httprequestmessage request; public voidresult(httprequestmessage httprequest) { this.request = httprequest; } public voidresult(apicontroller controller) { this.request = controller.request; } public task<httpresponsemessage> executeasync(cancellationtoken cancellationtoken) { return task.fromresult<httpresponsemessage>(new httpresponsemessage(httpstatuscode.nocontent) { requestmessage = request }); } }
调用代码:
public ihttpactionresult get() { return new voidresult(request); }
http 响应:
http/1.1 204 no content cache-control: no-cache pragma: no-cache expires: -1 server: microsoft-iis/10.0 x-aspnet-version: 4.0.30319 x-sourcefiles: =?utf-8?b?rtpcz2l0shvixfdlykfqsvn0dwr5qxbwbgljyxrpb25cv2viqvbju3r1zhlbchbsawnhdglvblxhcglcumv0dxjuvmfsdwu=?= x-powered-by: asp.net
该示例说明了通过ihttpactionresult来构造响应的具体细节,使控制器操作的意图更加清晰和复用。
ihttpactionresult包含一个方法executeasync,以便以异步方式创建httpresponsemessage实例。
public interface ihttpactionresult { task<httpresponsemessage> executeasync(cancellationtoken cancellationtoken); }
如果控制器操作返回ihttpactionresult,web api 调用executeasync方法创建httpresponsemessage。 然后它会将转换httpresponsemessage到 http 响应消息。一般情况下我们只需要使用apicontroller类内置的方法即可,方法内生成的instance定义在system.web.http.results下。
方法 | 实例的类名 | 响应信息 | 响应内容 |
---|---|---|---|
ok() | okresult | 200 (正常) | 无 |
ok |
oknegotiatedcontentresult | 200 (正常 | 序列化的结果 |
json |
jsonresult | 200 | json序列化的结果 |
json |
jsonresult | 200 | json序列化的结果 |
notfound() | notfoundresult | 404 | |
redirect(..) | redirectresult | 跳转 | |
redirecttoroute(...) | redirecttorouteresult | 跳转 | |
responsemessage(httpresponsemessage response) | responsemessageresult | [别用浪费资源] | |
statuscode(httpstatuscode status) | statuscoderesult | 输入的状态码 | 无 |
unauthorized(params authenticationheadervalue[] challenges) | unauthorizedresult | 401 | 未授权的信息明细 |
void
如果web api action返回类型为void,web api 仅返回状态代码 204 (无内容) 的空 http 响应。
[httpget] public void test() { //连接测试 }
http 响应:
http/1.1 204 no content cache-control: no-cache pragma: no-cache expires: -1 server: microsoft-iis/8.0 x-aspnet-version: 4.0.30319 x-sourcefiles: =?utf-8?b?rtpclk5fvcbnvkmgiefdrsbhzg1pblxxzwjcyxbpxef1dghvcml6yxrpb24=?= x-powered-by: asp.net
某些其他类型
对于所有其他返回类型,web api 使用媒体格式化程序要序列化的返回值。 web api 将序列化的值写入到响应正文。 响应状态代码为 200 (正常)。似乎所有类型都可以作为返回值,其实不然。再说这一问题前线看看什么样的实例能作为返回值。
- 值类型但是其值为null,可空的值不在其范围内例如(int不可以返回null, nullable
也就是int?是可以返回为null的) - 类型不是泛型并且也不是nullable<>类型的null实例不能做为返回值。
- 不能被赋值给新实例的实例不能作为返回值
某些其他类型返回值的控制器最终回传的是什么格式的数据:回执的数据格式决定在于请求的accept参数的第一个格式(不包括txt,如果是/则返回json)或者是在global.asax里的设置或被调用的设置。
produce[] produces = new produce[] { new produce{id=1,name="自动化测试3",price=11.2}, new produce{id=2,name="自动化测试2",price=12.2 }, new produce{id=3,name="自动化测试2",price=13.2 } }; [httpget] public produce[] test() { return produces; }
http 响应:
http/1.1 200 ok cache-control: no-cache pragma: no-cache content-type: application/json; charset=utf-8 expires: -1 server: microsoft-iis/10.0 x-aspnet-version: 4.0.30319 x-sourcefiles: =?utf-8?b?rtpclk5fvcbnvkmgiefdrsbhzg1pblxxzwjcyxbpxef1dghvcml6yxrpb24=?= x-powered-by: asp.net
数据内容为:
[{"id":1,"name":"自动化测试3","price":11.2},{"id":2,"name":"自动化测试2","price":12.2},{"id":3,"name":"自动化测试2","price":13.2}]
既然那么多的数据类型都可以作为返回值,那么执行web api是怎么处理返回值的呢?我们通过查看源码可以直到,最终是由apicontrolleractioninvoker.invokeactionasynccore 来执行action的。在invokeactionasynccore可中将返回值作为以下几类处理
- ihttpactionresult:该类型直接调用executeasync方法来获取一个httpresponsemessage实例,将该实例返回;
- httpresponsemessage:将实例设置requestmessage后直接返回
- void: 返回一个新的httpresponsemessage实例,设置其httpstatuscode为nocontent
- 不在上述类型中的类型:返回一个新的httpresponsemessage实例,设置其httpstatuscode为nocontent,content为objectcontent<t >。
总结归纳
- web api2 的最终返回值的类型为httpresponsemessage,其他的返回值类型会经过一系列的处理形成一个httpresponsemessage实例。
- 除了返回jsonresult实例返回的数据格式是json外,其他的返回格式按请求或者设置而定。
推荐阅读
-
ASP.NET第一次访问慢的解决方法(MVC,Web Api)
-
ASP.NET Web API 2 的返回结果
-
或许是你应该了解的一些 ASP.NET Core Web API 使用小技巧
-
js正则表达式之$1$2$3$4$5$6$7$8$9属性,返回子匹配的结果
-
【Web API系列教程】2.2 — ASP.NET Web API中的路由和动作选择机制
-
ASP.NET Web API 2系列(二):灵活多样的路由配置
-
Struts2(二)— Result结果配置、Servlet的API的访问、模型驱动、属性驱动
-
使用RAP2和Mock.JS实现Web API接口的数据模拟和测试
-
使用ASP.NET Web API和Web API Client Gen使Angular 2应用程序的开发更加高效
-
ASP.NET Web API中的Controller