曾幾什麼時候,微軟基於Web服務技術給出最流行的基於XML且以擴展名爲.asmx結尾的Web Service,此服務在.NET Framework中風靡一時同時也被.NET業界同仁所青睞,幾年後在此基礎上又擴展成爲了WCF,基於SOAP協議,基於WCF標準須要一些配置上的改變。現現在,大勢所趨咱們只須要HTTP協議以及更加優美的JSON格式,這時將不得不出現一個更加輕量級的Web服務技術。固然,Web Service和WCF雖然有其侷限性可是其仍被許多企業所普遍應用,說明一時半會還不會被淘汰,也有其存在的價值。api
此時Web APi出現了,Web APi是一個僅僅只支持HTTP協議並且很是強大的框架而且默認是JSON格式,咱們和須要配置如endpoint、contarcts等繁瑣的配置的Web Service和WCF畫上了句號。Web APi基於ResetFul服務輕量並且強大,下面咱們來看看Web APi是如何的強大以及輕量,它的優勢和特色在哪裏?跨域
咱們首先來看一張圖,以下session
接下來咱們一一解釋上述優勢框架
在WCF中咱們須要endpoints和contracts,可是在Web APi中咱們根本不須要這些設置(超簡單)。ide
不像WCF,在WCF中一個服務對應的是從一個地址到一個物理文件(簡言之:一個地址被映射到一個服務類或者是.svc文件),當物理文件移除位置或者刪除其產生的影響可想而知,可是在Web APi中一個服務地址是一個RESET路由,而且該路由被映射到一個控制器上的方法(很靈活)。性能
Web APi提供了一套高度可擴展的消息處理管道機制,其中如DelegateHandler以及Filer提供了請求和響應的機制。Handler容許咱們在被激活的控制器以及控制器上方法進行自定義錯誤處理,同時它也可以被配置來處理不一樣控制器上的路由。而Filter中包含了相應的類以及方法在控制器上的方法被調用以前和以後來容許咱們運行一些代碼,例如:action filter、exception filter等等,與此同時這些過濾器對應的特性可以修飾控制器上的方法,能夠修飾單個或者全局皆可(高擴展)。學習
給予Web服務開發者一個稍抽象的路由,可是開發者可以看到並易懂這樣的一個實現,咱們可以映射任何一個URL到一個控制上的方法,換言之,這樣的抽象就不會具體對應到哪一個文件或者是哪一個具體的接口,只要URL對應一個有效的控制器方法咱們就只須要在對應的方法進行咱們的實現便可(稍抽象路由)測試
咱們繼續以一張圖來歸納ui
HTTP方法自動映射到控制器上對應的方法,而且經過URL裏所傳遞的參數Web APi也會自動匹配,固然可能手動須要進行簡單的配置,其增刪改查分別對應HTTP方法中的POST、GET、DELETE等。spa
咱們知道在MVC上的控制器返回什麼數據格式,如JSON或者XML須要咱們去顯示指定返回的類型,可是在Web APi上的控制器對應的方法只須要返回原始數據值便可,它會根據調用者的請求自動進行轉換爲JSON或者XML。
路由特性以及路由前綴都是很是明確的路由定義而且與咱們控制器上的HTTP方法相關聯。
對於特定的業務需求咱們須要不一樣的路由來進行約束,好比類型,值的範圍等,Web APi中的路由約束是一個很是棒的特色。
這個跨域特色的支持真是讓咱們大飽眼福,可以徹底進行js跨域請求,知足所需。
在這個特色中,全部未被處理的錯誤機制都會被抓取到,經過訪問的錯誤異常以及異常所在的上下文Web APi可以支持多個異常處理記錄。
從上可知,Web APi的強大以及靈活是WCF以及Web Service所沒法比擬的,在Web服務技術中,Web APi的簡潔以及優雅已經成爲最佳服務技術選擇。固然這也是站在Web Service以及WCF的肩膀上或者是時代的需求所發展出來的,咱們只需明白:腳有多大,就穿多大鞋。
以前這個話題我是不知道的,在【嗨博客】中有羣友問才知道在Web APi中是不支持Session的,說的更加精準一點是默認沒有啓動Session,這裏就統一進行下學習,但願你有所收穫。 在Web APi中的Session不依賴於System.Web,如若要將Web APi運行在ASP.NET運行時,此時咱們須要啓動Session,當咱們只要是在Web APi環境中就啓動APi該如何作?有兩種實現方式,請往下看。
如下皆在Global.asax全局文件中進行。
private const string WebApiPrefix = "APi"; private static string WebApiExecutePath = string.Format("~/{0}", WebApiPrefix);
private bool isWebAPiRequest() { return HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.StartsWith(WebApiExecutePath); }
protected void Application_PostAuthorizeRequest() { if (isWebAPiRequest()) { HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required); } }
protected void Session_Start() { HttpContext.Current.Session.Add("xpy0928", "嗨-博客"); var session_value = HttpContext.Current.Session["xpy0928"]; }
測試以下圖:
以前咱們在Web APi系列中講到過HttpControllerRouteHandler,此類中的GetHttpHandler方法返回HttpControllerHandler的一個實例即HttpHandler,經過此HttpHandler是進入Web APi消息處理管道的入口點,咱們可使用在IHttpHandler上的Session實現IRquiressionstate接口便可。
protected void Application_PostAuthorizeRequest() { HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required); }
public class EnableSession_HttpControllerRouteHandler : HttpControllerRouteHandler { protected override IHttpHandler GetHttpHandler(System.Web.Routing.RequestContext requestContext) { return new EnableSession_ControllerHandler(requestContext.RouteData); } }
public class EnableSession_ControllerHandler : HttpControllerHandler, IRequiresSessionState { public EnableSession_ControllerHandler(RouteData routeData) : base(routeData) { } }
routes.MapHttpRoute( name: "DefaultAPi", routeTemplate: "api/{controller}/{id}", defaults: new { id = UrlParameter.Optional } ).RouteHandler = new EnableSession_HttpControllerRouteHandler();
public static void Register(HttpConfiguration config) { var httpControllerRouteHandler = typeof(HttpControllerRouteHandler).GetField("_instance", BindingFlags.Static | BindingFlags.NonPublic); if (httpControllerRouteHandler != null) { httpControllerRouteHandler.SetValue(null, new Lazy<HttpControllerRouteHandler>(() => new EnableSession_HttpControllerRouteHandler(), true)); } config.MapHttpAttributeRoutes(); }
此時運行將出現以下錯誤:
【注意】解決方案:在Web API中屬性路由引發的HttpConfiguration.EnsureInitialized異常
public void Get() { object context; if (Request.Properties.TryGetValue("MS_HttpContext", out context)) { var httpContext = context as HttpContextBase; if (httpContext != null && httpContext.Session != null) { var lastValue = httpContext.Session["xpy0928"] as int?; httpContext.Session["xpy0928"] = "博客園"; var session_value = httpContext.Session["xpy0928"]; } } }
以上兩種方法皆可在Web APi中啓動Session,你以爲那個簡單就按照對應的來。但咱們須要注意一個問題:在Web APi中,Web APi是不依賴於HttpContext,也就是HttpContext.Current確定是爲null的,咱們要訪問Session或者其餘對象須要使用Request對象中的屬性Properties來獲取你想要的值或者設置值。