前言
本節的主題是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}]