Web API-如何将Controller的返回值转换成HTTP response消息

https://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization

https://code.msdn.microsoft.com/Support-format-in-ASPNET-e3785b2a

1,Web API 框架是一个面向 Http 协议的通信框架。相对于 WCF 而言,Web API 只面向于 Http 协议设计,而且没有 WCF 那么繁琐的配置。

Web API 的开发类似于 ASP.NET MVC 中控制器的开发,但是相对于直接使用 ASP.NET MVC 来返回 Json 对象的方式而言,Web API 封装了数据的序列化、反序列化,接口、实现都更加简单。
简单地说,如果要向浏览器、移动端提供 Json 数据格式的 API,则应该首选 Web API 作为通信框架。,2,Web API 框架目前支持两种数据格式的序列化:Json 及 Xml。在不做任何配置的情况下,如果 Http 请求中,HttpHeader 中 Accept 被指定为 accept: application/xml,则 Web API 会自动把数据使用 xml 进行序列化,否则使用 json 序列化。
如果期望不使用 xml 序列化数据,我们可以通过 GlobalConfiguration.Configuration.Formatters 来进行配置:config.Formatters.Remove(config.Formatters.XmlFormatter)。

一般情况下,我们会使用 Json 序列化。跟 ASP.NET MVC 的 Json 序列化不同的是,Web API 使用了 Newtonsoft.Json 框架来进行序列化。

(例如,JsonMediaTypeFormatter.SerializerSettings 属性就是 Newtonsoft.Json.JsonSerializerSettings 类型,可以直接对序列化进行配置。)
Json 序列化支持对匿名类型进行进行序列化,这大大方便了开发人员,例如,我们可以随意组装数据并直接返回;

Web API 提供了 HttpResponseMessage 类型可作为返回值,使得开发人员可以对 HttpResponse 做一些更详细的设置。而且,如果不期望修改返回值类型而直接返回 HttpResponse 时,可以使用 HttpResponseException 间接返回一个 HttpResponseMessage。

https://www.asp.net/web-api/overview/formats-and-model-binding/content-negotiation

二,Web API-如何将Controller的返回值转换成HTTP response消息

一个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插件

clipboard

指定请求头部 Accept 值 为:application/xml 则返回xml类型数据。

clip_image002

指定请求头部 Accept 值 为:application/json 则返回json类型数据。

posted @ 2016-10-12 14:09  jimcsharp  阅读(947)  评论(0编辑  收藏  举报