本節(jié)的主題是ASP.NET Web API如何將控制器動作的返回值轉(zhuǎn)換成HTTP的響應(yīng)消息。
Web API控制器動作可以返回下列的任何值: 1, void 2, HttpResponseMessage 3, IHttpActionResult 4, Some other type
取決于返回的以上哪一種,Web API使用不同的機(jī)制來創(chuàng)建HTTP響應(yīng)。
| 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). |
本節(jié)的剩余部分將詳細(xì)描述每種返回值。
如果返回類型是type,Web API就會用狀態(tài)碼204(No Content)返回一個空HTTP響應(yīng)。
示例控制器:
public class ValuesController : ApiController
{
public void Post()
{
}
}
HTTP相應(yīng):
HTTP/1.1 204 No Content
Server: Microsoft-IIS/8.0
Date: Mon, 27 Jan 2014 02:13:26 GMT
如果一個動作返回HttpResponseMessage,Web API就通過HttpResponseMessage的屬性構(gòu)造成消息從而直接將返回值轉(zhuǎn)換成HTTP響應(yīng)。
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;
}
}
相應(yīng):
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)將序列化模型寫入到響應(yīng)體中。
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中被引進(jìn)。本質(zhì)上,它定義了一個HttpResponseMessage工廠。以下是使用IHttpActionResult接口的好處: 1, 簡單你的控制器的單元測試 2, 為創(chuàng)建HTTP相應(yīng)將公共邏輯移動到單獨的類 3, 通過隱藏構(gòu)建相應(yīng)的底層細(xì)節(jié),使控制器動作更清晰
IHttpActionResult包含一個單獨的方法ExecuteAsync,它會異步地創(chuàng)建一個HttpResponseMessage實例:
public interface IHttpActionResult
{
Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken);
}
如果一個控制器動作返回IHttpActionResult,Web API會調(diào)用ExecuteAsync方法來創(chuàng)建HttpResponseMessage。然后將HttpResponseMessage轉(zhuǎn)換到HTTP相應(yīng)消息里。
以下是一個IHttpActionResult的簡單執(zhí)行,它創(chuàng)建一個文本相應(yīng):
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);
}
}
相應(yīng):
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實現(xiàn)。
在接下來的示例中,如果請求沒有匹配到任何已存在的產(chǎn)品ID,控制器就會調(diào)用ApiController.NotFound來創(chuàng)建一個404(Not Found)響應(yīng)。否則,控制器會調(diào)用ApiController.OK,它會調(diào)用一個意為包含該產(chǎn)品的200(OK)相應(yīng)。
public IHttpActionResult Get (int id)
{
Product product = _repository.Get (id);
if (product == null)
{
return NotFound(); // Returns a NotFoundResult
}
return Ok(product); // Returns an OkNegotiatedContentResult
}
對于其他所有返回類型,Web API使用媒體格式(media formatter)來序列化返回值。Web API將序列化值寫入到響應(yīng)體中。響應(yīng)狀態(tài)碼是200(OK)。
public class ProductsController : ApiController
{
public IEnumerable<Product> Get()
{
return GetAllProductsFromDB();
}
}
該實現(xiàn)的缺點在于你不能直接返回一個錯誤碼,比如404。
Web API通過在請求中使用Accept頭來選擇格式。
示例請求:
GET http://localhost/api/products HTTP/1.1
User-Agent: Fiddler
Host: localhost:24127
Accept: application/json
示例相應(yīng):
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}]