1. "HttpResponseMessage" 2. "IHttpActionResult" 3. "void" 4. "某些其他類型" 5. "總結歸納" 原文地址:https://www.cnblogs.com/xgzh/p/11208611.html HttpResponseMessage ...
原文地址:https://www.cnblogs.com/xgzh/p/11208611.html
HttpResponseMessage
HttpResponseMessage是ASP.NET Web API 的標準返回值可以直接將轉換為 HTTP 響應消息,那為什麼我們不推薦使用HttpResponseMessage,主要是因為用起來比較麻煩,當然HttpResponseMessage提供大量控制的響應消息用來操作設置的緩存控制標頭。為什麼說HttpResponseMessage是ASP.NET Web API 的標準返回值,最後再講,先看看如何使用HttpResponseMessage作為返回值。
public HttpResponseMessage Get()
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Accepted, "value");
//設置內容和編碼
response.Content = new StringContent("Link sucess", Encoding.BigEndianUnicode);
response.Headers.CacheControl = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromMinutes(10),//設置緩存
};
return response;
}
HTTP 響應:
HTTP/1.1 202 Accepted
Cache-Control: max-age=1200
Content-Length: 22
Content-Type: text/plain; charset=utf-16
Server: Microsoft-IIS/10.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RTpcZ2l0SHViXFdlYkFQSVN0dWR5QXBwbGljYXRpb25cV2ViQVBJU3R1ZHlBcHBsaWNhdGlvblxhcGlcUmV0dXJuVmFsdWU=?=
X-Powered-By: ASP.NET
HttpResponseMessage作為返回值使用的太少,我除了下載文件外基本沒用到過,
public HttpResponseMessage DownloadFile(string filename)
{
string filePath = HttpContext.Current.Server.MapPath("/") + "Files\\" + filename;
FileStream stream = new FileStream(filePath, FileMode.Open);
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(stream);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = HttpUtility.UrlEncode(fileName)
};
response.Headers.Add("Access-Control-Expose-Headers", "FileName");
response.Headers.Add("FileName", HttpUtility.UrlEncode(fileName));
return response;
}
IHttpActionResult
IHttpActionResult Web API 2 中引入了介面。 從根本上來說,用於將其他類型的值轉換為HttpResponseMessage類型值的工廠。果控制器操作返回IHttpActionResult,Web API 調用ExecuteAsync方法創建HttpResponseMessage。 然後它會將轉換HttpResponseMessage到 HTTP 響應消息。我個人比較用的多。使用IHttpActionResult:
- 測試時更加簡單方便。
- 在單獨的類創建 HTTP 響應的常見邏輯,響應的內容為HttpResponseMessage。
- 通過隱藏構造響應的低級細節,使控制器操作的意圖更加清晰。
下麵是一個和返回值為void一樣功能的VoiResult,該類實現了IHttpActionResult僅返回狀態代碼 204 (無內容) 的空 HTTP 響應。
/// <summary>
/// 一個無響應內容的響應信息
/// </summary>
public class VoidResult : IHttpActionResult
{
HttpRequestMessage request;
public VoidResult(HttpRequestMessage httpRequest)
{
this.request = httpRequest;
}
public VoidResult(ApiController controller)
{
this.request = controller.Request;
}
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
return Task.FromResult<HttpResponseMessage>(new HttpResponseMessage(HttpStatusCode.NoContent) { RequestMessage = request });
}
}
調用代碼:
public IHttpActionResult Get()
{
return new VoidResult(Request);
}
HTTP 響應:
HTTP/1.1 204 No Content
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/10.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RTpcZ2l0SHViXFdlYkFQSVN0dWR5QXBwbGljYXRpb25cV2ViQVBJU3R1ZHlBcHBsaWNhdGlvblxhcGlcUmV0dXJuVmFsdWU=?=
X-Powered-By: ASP.NET
該示例說明瞭通過IHttpActionResult來構造響應的具體細節,使控制器操作的意圖更加清晰和復用。
IHttpActionResult包含一個方法ExecuteAsync,以便以非同步方式創建HttpResponseMessage實例。
public interface IHttpActionResult
{
Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken);
}
如果控制器操作返回IHttpActionResult,Web API 調用ExecuteAsync方法創建HttpResponseMessage。 然後它會將轉換HttpResponseMessage到 HTTP 響應消息。一般情況下我們只需要使用ApiController類內置的方法即可,方法內生成的instance定義在System.Web.Http.Results下。
方法 | 實例的類名 | 響應信息 | 響應內容 |
---|---|---|---|
OK() | OKResult | 200 (正常) | 無 |
Ok |
OkNegotiatedContentResult | 200 (正常 | 序列化的結果 |
Json |
JsonResult | 200 | Json序列化的結果 |
Json |
JsonResult | 200 | Json序列化的結果 |
NotFound() | NotFoundResult | 404 | |
Redirect(..) | RedirectResult | 跳轉 | |
RedirectToRoute(...) | RedirectToRouteResult | 跳轉 | |
ResponseMessage(HttpResponseMessage response) | ResponseMessageResult | [別用浪費資源] | |
StatusCode(HttpStatusCode status) | StatusCodeResult | 輸入的狀態碼 | 無 |
Unauthorized(params AuthenticationHeaderValue[] challenges) | UnauthorizedResult | 401 | 未授權的信息明細 |
void
如果Web API Action返回類型為void,Web API 僅返回狀態代碼 204 (無內容) 的空 HTTP 響應。
[HttpGet]
public void Test()
{
//連接測試
}
HTTP 響應:
HTTP/1.1 204 No Content
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RTpcLk5FVCBNVkMgIEFDRSBhZG1pblxXZWJcYXBpXEF1dGhvcml6YXRpb24=?=
X-Powered-By: ASP.NET
某些其他類型
對於所有其他返回類型,Web API 使用媒體格式化程式要序列化的返回值。 Web API 將序列化的值寫入到響應正文。 響應狀態代碼為 200 (正常)。似乎所有類型都可以作為返回值,其實不然。再說這一問題前線看看什麼樣的實例能作為返回值。
- 值類型但是其值為null,可空的值不在其範圍內例如(int不可以返回null, Nullable
也就是int?是可以返回為null的) - 類型不是泛型並且也不是Nullable<>類型的null實例不能做為返回值。
- 不能被賦值給新實例的實例不能作為返回值
某些其他類型返回值的控制器最終回傳的是什麼格式的數據:回執的數據格式決定在於請求的Accept參數的第一個格式(不包括txt,如果是/則返回Json)或者是在Global.asax里的設置或被調用的設置。
Produce[] produces = new Produce[] {
new Produce{id=1,Name="自動化測試3",Price=11.2},
new Produce{id=2,Name="自動化測試2",Price=12.2 },
new Produce{id=3,Name="自動化測試2",Price=13.2 }
};
[HttpGet]
public Produce[] Test()
{
return produces;
}
HTTP 響應:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/10.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RTpcLk5FVCBNVkMgIEFDRSBhZG1pblxXZWJcYXBpXEF1dGhvcml6YXRpb24=?=
X-Powered-By: ASP.NET
數據內容為:
[{"id":1,"Name":"自動化測試3","Price":11.2},{"id":2,"Name":"自動化測試2","Price":12.2},{"id":3,"Name":"自動化測試2","Price":13.2}]
既然那麼多的數據類型都可以作為返回值,那麼執行Web Api是怎麼處理返回值的呢?我們通過查看源碼可以直到,最終是由ApiControllerActionInvoker.InvokeActionAsyncCore 來執行Action的。在InvokeActionAsyncCore可中將返回值作為以下幾類處理
- IHttpActionResult:該類型直接調用ExecuteAsync方法來獲取一個HttpResponseMessage實例,將該實例返回;
- HttpResponseMessage:將實例設置RequestMessage後直接返回
- void: 返回一個新的HttpResponseMessage實例,設置其HttpStatusCode為NoContent
- 不在上述類型中的類型:返回一個新的HttpResponseMessage實例,設置其HttpStatusCode為NoContent,Content為ObjectContent<T >。
總結歸納
- WEB API2 的最終返回值的類型為HttpResponseMessage,其他的返回值類型會經過一系列的處理形成一個HttpResponseMessage實例。
- 除了返回JsonResult實例返回的數據格式是Json外,其他的返回格式按請求或者設置而定。