根據web api 官方參考文獻 總結出一下代碼舉例:
將 HTTP 響應消息的處理委托給另一處理程序(稱為“內部處理程序”)的 HTTP 處理程序的類型。
如何理解這句話的意思?
首先我們應知道Asp.Net Web Api 的http消息響應機制,這里我可以解釋為:消息管道串聯。官方代碼指出:public abstract class DelegatingHandler : System.Net.Http.HttpMessageHandler,
而具體實現“管道串聯”是通過DelegatingHandler這個類型來完成。
通過以上文檔得出疑問
當DelegatingHandler自己負責的消息處理任務完成之后可以委托另一個HttpMessagHandler進行后續的處理。
如果這個被委托的也是一個DelegatingHandler對象,不就可以組成一個委托鏈了嗎?而這個委托鏈不就是由一個個DelegatingHandler組成的消息處理管道嗎?
namespace System.Net.Http { // 摘要: // 被稱為內部處理程序的並將 HTTP 響應消息委托給另一處理程序的 HTTP 處理程序的基類型。 public abstract class DelegatingHandler : HttpMessageHandler { // 摘要: // 創建 System.Net.Http.DelegatingHandler 類的新實例。 protected DelegatingHandler(); // // 摘要: // 創建特定內部處理程序的 System.Net.Http.DelegatingHandler 類的新實例。 // // 參數: // innerHandler: // 負責處理 HTTP 響應消息的內部處理程序。 protected DelegatingHandler(HttpMessageHandler innerHandler); // 摘要: // 獲取或設置處理 HTTP 響應消息的內部處理程序。 // // 返回結果: // 返回 System.Net.Http.HttpMessageHandler。 HTTP 響應消息的內部處理程序。 public HttpMessageHandler InnerHandler { get; set; } // 摘要: // 釋放由 System.Net.Http.DelegatingHandler 使用的非托管資源,並可根據需要釋放托管資源。 // // 參數: // disposing: // 如果為 true,則釋放托管資源和非托管資源;如果為 false,則僅釋放非托管資源。 protected override void Dispose(bool disposing); // // 摘要: // 以異步操作發送 HTTP 請求到內部管理器以發送到服務器。 // // 參數: // request: // 要發送到服務器的 HTTP 請求消息。 // // cancellationToken: // 取消操作的取消標記。 // // 返回結果: // 返回 System.Threading.Tasks.Task<TResult>。 表示異步操作的任務對象。 // // 異常: // System.ArgumentNullException: // request 為 null。 protected internal override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken); } }
我們在此可以總結出,如ASP.NET Web API的消息處理管道均由DelegatingHandler組成(位於管道尾端的HttpMessageHandler除外),我們就可以根據其InnerHandler獲得對被委托的HttpMessageHandler對象的引用,由此便構成消息處理的鏈式結構。組成ASP.NET Web API核心框架的消息處理管道,
理論總結的差不多,那么下面我們就對該消息處理委托類進行消息自定義操作,
public class RequestMessageDelegatingHandler : DelegatingHandler { protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { return base.SendAsync(request, cancellationToken).ContinueWith((responseToCompleteTask) => { //獲取URL參數 NameValueCollection query = HttpUtility.ParseQueryString(request.RequestUri.Query); //獲取Post正文數據,比如json文本 string fRequesContent = request.Content.ReadAsStringAsync().Result; //可以做一些其他安全驗證工作,比如Token驗證,簽名驗證。 //可以在需要時自定義HTTP響應消息 //return SendError("自定義的HTTP響應消息", HttpStatusCode.OK); HttpResponseMessage response = responseToCompleteTask.Result; HttpError error = null; if (response.TryGetContentValue<HttpError>(out error)) { //添加自定義錯誤處理 //error.Message = "請求失敗"; } if (error != null) { //記錄關鍵的異常信息 QWPlatform.SystemLibrary.LogManager.Logger.Instance.Error("[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "]404錯誤:請求數據" + error.Message); //返回錯誤信息 throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.OK) { //封裝處理異常信息,返回指定JSON對象 Content = new StringContent(new ZLSoft.CHSS.Web.Public.Library.BaseClass.AjaxResult(Common.Base.AjaxResultType.失敗, error.Message + "404").CreateResultString()), //Encoding.GetEncoding("UTF-8"), "application/json" ReasonPhrase = "Exception" }); } else { return response; } }, cancellationToken); } }
接下來,我們只需要把當前類注冊到 webapiconfig類當中。
public class WebAPIConfig { public static void Register(HttpConfiguration config) { //跨域配置 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); // config.MapHttpAttributeRoutes(); //注冊路由映射 config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); config.MessageHandlers.Add(new RequestMessageDelegatingHandler());
} }
接下里就可以在 RequestMessageDelegatingHandler 中間寫好消息處理機制哪里進行統一的安全校驗。