天天看點

【Web API系列教程】1.2 — Web API 2中的Action Results

前言

本節的主題是ASP.NET Web API如何将控制器動作的傳回值轉換成HTTP的響應消息。

Web API控制器動作可以傳回下列的任何值:

1, void

2, HttpResponseMessage

3, IHttpActionResult

4, Some other type

取決于傳回的以上哪一種,Web API使用不同的機制來建立HTTP響應。

Return type How Web API creates the response
void Return empty 204 (No Content)
HttpResponseMessage Convert directly to an HTTP response message.
IHttpActionResult Call ExecuteAsync to create an HttpResponseMessage, then convert to an HTTP response message.
Other type Write the serialized return value into the response body; return 200 (OK).

本節的剩餘部分将較長的描述每種傳回值。

如果傳回類型是type,Web API就會用狀态碼204(No Content)傳回一個空HTTP響應。

示例控制器:

public class ValuesController : ApiController
{
    public void Post()
    {
    }
}
           

HTTP相應:

HTTP/1.1 204 No Content
Server: Microsoft-IIS/8.0
Date: Mon, 27 Jan 2014 02:13:26 GMT
           

如果一個動作傳回HttpResponseMessage,Web API就通過HttpResponseMessage的屬性構造成消息進而直接将傳回值轉換成HTTP響應。

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
           

如果傳遞一個域模型給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;
}
           

IHttpActionResult接口在Web API 2中被引進。本質上,它定義了一個HttpResponseMessage工廠。以下是使用IHttpActionResult接口的好處:

1, 簡單你的控制器的單元測試

2, 為建立HTTP相應将公共邏輯移動到單獨的類

3, 通過隐藏建構相應的底層細節,使控制器動作更清晰

IHttpActionResult包含一個單獨的方法ExecuteAsync,它會異步地建立一個HttpResponseMessage執行個體:

public interface IHttpActionResult
{
    Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken);
} 
           

如果一個控制器動作傳回IHttpActionResult,Web API會調用ExecuteAsync方法來建立HttpResponseMessage。然後将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
           

更通常的情況是,你會使用System.Web.Http.Results命名空間下定義的IHttpActionResult實作。

在接下來的示例中,如果請求沒有比對到任何已存在的産品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
}
           

Other Return Types

對于其他所有傳回類型,Web API使用媒體格式(media formatter)來序列化傳回值。Web API将序列化值寫入到響應體中。響應狀态碼是200(OK)。

public class ProductsController : ApiController
{
    public IEnumerable<Product> Get()
    {
        return GetAllProductsFromDB();
    }
}
           

該實作的缺點在于你不能直接傳回一個錯誤碼,比如404。

Web API通過在請求中使用Accept頭來選擇格式。

示例請求:

GET http://localhost/api/products HTTP/1.1
User-Agent: Fiddler
Host: localhost:24127
Accept: application/json
           

示例相應:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/8.0
Date: Mon, 27 Jan 2014 08:53:35 GMT
Content-Length: 56

[{"Id":1,"Name":"Yo-yo","Category":"Toys","Price":6.95}]