一个Web API 控制器方法可以返回以下类型的值
1.void
2.HttpResponseMessage
3.IHttpActionResult
4.其它一些类型
根据action不同的返回类型,Web API 使用不同的处理方法去创建一个http响应信息。
Action返回类型 |
Web API 如何生成响应消息 |
void |
返回空 204(No Content) |
HttpResponseMessage |
直接转换成HTTP响应消息 |
IHttpActionResult |
调用ExecuteAsync方法去创建一个HttpResponseMessage 对象,让后将这个对象转换成Http响应消息 |
其他类型 |
将序列化的值写到响应消息的内容中,返回200(OK) |
下面对每一种返回类型做详细说明
void
如果action返回void类型,Web API返回一个空HTTP响应消息,状态码为:204(No Content)
例如:
public class ValuesController : ApiController { public void Post() { } }
执行此Action时,响应消息为:
HTTP/1.1 204 No Content Server: Microsoft-IIS/8.0 Date: Mon, 27 Jan 2014 02:13:26 GMT
HttpResponseMessage
如果action返回一个HttpResponseMessage类型值,Web API直接将该对象转换成HTTP响应消息,使用HttpResponseMessage对象的属性值去填充响应消息。
返回HttpResponseMessage类型的方式给了我们更多的控制响应消息的能力,例如下面的控制器 action实现了设置响应消息头Cache-Control 的值
public class ValuesController : ApiController { public HttpResponseMessage Get() { HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, "value"); response.Content = new StringContent("hello", Encoding.Unicode); response.Headers.CacheControl = new CacheControlHeaderValue() { MaxAge = TimeSpan.FromMinutes(20) }; return response; } }
响应消息:
HTTP/1.1 200 OK Cache-Control: max-age=1200 Content-Length: 10 Content-Type: text/plain; charset=utf-16 Server: Microsoft-IIS/8.0 Date: Mon, 27 Jan 2014 08:53:35 GMT hello
如果你传递一个model 对象(domain model)给CreateResponse方法,Web API将使用媒体格式(media formatter)序列化对象并将序列化后的内容写入到响应主体内容中。
public HttpResponseMessage Get() { // Get a list of products from a database. IEnumerable<Product> products = GetProductsFromDB(); // Write the list to the response body. HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, products); return response; }
如上,Web API 将使用请求消息的头部 Accept 指定的格式选择响应消息内容的格式,(内容协商的实现)
IHttpActionResult
IHttpActionResult 接口在Web API2中引入,本质上,它是一个HttpResponseMessage工厂(比如使用NotFound()可以返回404响应,Ok(products)可以返回一个 200响应并返回内容,这两个方法返回的类型均实现了IHttpActionResult接口)。
使用IHttpActionResult 接口有以下几个优势:
--简化控制器的单元测试
--将创建HTTP响应的主要逻辑分离到不同的类中
--通过隐藏创建响应消息的底层细节,使控制器动作的意图更加清晰。
IHttpActionResult 只包含一个方法,ExecuteAsync,这个方法能够异步的创建一个HttpResponseMessage对象。
public interface IHttpActionResult { Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken); }
如果一个控制器方法返回一个IHttpActionResult类型对象,Web API调用ExecuteAsync方法去创建一个HttpResponseMessage对象,然后将这个对象转换成HTTP响应消息。
可以自己实现IHttpActionResult接口,实现自定义转换方法,比如返回一个纯文本类型响应消息
public class TextResult : IHttpActionResult { string _value; HttpRequestMessage _request; public TextResult(string value, HttpRequestMessage request) { _value = value; _request = request; } public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) { var response = new HttpResponseMessage() { Content = new StringContent(_value), RequestMessage = _request }; return Task.FromResult(response); } }
控制器的方法这样写:
public class ValuesController : ApiController { public IHttpActionResult Get() { return new TextResult("hello", Request); } }
这时响应消息为:
HTTP/1.1 200 OK Content-Length: 5 Content-Type: text/plain; charset=utf-8 Server: Microsoft-IIS/8.0 Date: Mon, 27 Jan 2014 08:53:35 GMT hello
通常,你应该将IHttpActionResult接口的实现类定义在System.Web.Http.Results命名空间下,The ApiContoller class defines helper methods that return these built-in action results.(APIController 类定义了返回(这些内建的action返回类型)帮助信息的方法。
在下面的例子中:如果找不到请求的id所对应的产品,控制器则调用APIController.NotFound 去创建一个404(Not Found)响应消息,否则控制器调用APIController.OK,创建一个200(OK)包含产品类容信息的响应消息。
public IHttpActionResult Get (int id) { Product product = _repository.Get (id); if (product == null) { return NotFound(); // Returns a NotFoundResult } return Ok(product); // Returns an OkNegotiatedContentResult }
其他的返回类型
对应其他的action返回类型,Web API使用媒体格式(media formatter)序列化返回值,Web API将序列化的值写入肖响应消息的主体中,响应状态代码为200(OK)
public class ProductsController : ApiController { public IEnumerable<Product> Get() { return GetAllProductsFromDB(); } }
上面Action返回一个列表类型,如果请求消息中没有指定 Accept头部信息(要求响应消息内容的类型),则会将列表对象序列化成json(默认)返回给浏览器。
返回其他类型的方式,一个缺点就是不能直接返回一个响应错误代码,比如404,当然,可以通过抛出一个HttpResponseException异常来返回响应错误代码,更多信息可查看(Exception Handling in ASP.NET Web API.)
Web API 使用请求消息中 Accept 头部值指定的格式来决定响应消息返回的内容格式(即内容协商方式)
比如:使用Chrome的postman插件
指定请求头部 Accept 值 为:application/xml 则返回xml类型数据。
指定请求头部 Accept 值 为:application/json 则返回json类型数据。