閱讀211 返回首頁    go 技術社區[雲棲]


ASP.NET Web API自身對CORS的支持:從實例開始

在《通過擴展讓ASP.NET Web API支持W3C的CORS規範》中我們通過自定義的HttpMessageHandler為ASP.NET Web API賦予了跨域資源共享的能力,具體來講,這個自定義的CorsMessageHandler的自由主要體現在如下兩個方麵:其一,為簡單跨域請求的響應和繼預檢請求後的真實跨域資源請求的響應添加CORS報頭;其二,對從瀏覽器發送的預檢請求予以響應。實際上ASP.NET Web API本身就提供了針對CORS的支持,就其實現原理來看,與我們的實現沒有本質的區別。接下來我們通過實例演示如何利用ASP.NET Web API自身的支持來實現“跨域資源共享”。

10083557-f2f728995d054084bf60e0e05339642

如圖右圖所示,我們利用Visual Studio在同一個解決方案中創建了兩個Web應用。從項目名稱可以看出,WebApi和MvcApp分別為ASP.NET Web API和MVC應用,後者是Web API的調用者。我們直接采用默認的IIS Express作為兩個應用的宿主,並且固定了端口號:WebApi和MvcApp的端口號分別為“3721”和“9527”,所以指向兩個應用的URI肯定不可能是同源的。

10083600-b82ac5e75dec43429e929c6d4ba459e

ASP.NET Web API對CORS提供的原生支持實現在一個名為“Microsoft ASP.NET Web API 2 Cross-Origin Support”的NuGet包中。我們依然沿用上麵這個通過跨域Ajax請求獲取聯係人列表的這個例子,我們右鍵選種WebApi項目並在上下文菜單中選擇“管理NuGet包(Manage NuGet Package)”,在彈出的如左圖所示的對話框中,我們輸入“CORS”作為查詢條件後會看到這個NuGet包頭。

當我們安裝這個包之後,現有的packages目錄下會添加兩個名稱分別為“Microsoft.AspNet.Cors.5.0.0”和“Microsoft.AspNet.WebApi.Cors.5.0.0”,針對保存其中的兩個程序集(System.Web.Cors.dll和System.Web.Http.Cors.dll)的引用被自動添加到WebApi項目中。

ASP.NET針對CORS的實現就實現在程序集System.Web.Cors.dll中,另一個程序集System.Web.Http.Cors.dll自然就是針對ASP.NET Web API的。在默認情況下,針對CORS的支持是關閉的,我們需要在Global.asax中按照如下的方式調用當前HttpConfiguration的擴展方法EnableCors顯示開啟針對CORS的支持。

   1: public class WebApiApplication : System.Web.HttpApplication
   2: {
   3:     protected void Application_Start()
   4:     {
   5:         GlobalConfiguration.Configuration.EnableCors();
   6:         //其他操作
   7:     }
   8: }

和在《通過擴展讓ASP.NET Web API支持W3C的CORS規範》實現CORS的實例一樣,ASP.NET Web API自身也是借助於應用在HttpController類型或者定義其中的Action方法的特性來定義CORS授權策略的,這個特性類型為System.Web.Http.Cors.EnableCorsAttribute,它定義在程序集System.Web.Http.Cors.dll中。我們隻需要按照如下的方式將EnableCorsAttribute特性應用到定義在ContactsController中的Action方法GetAllContacts上即可。

   1: 
   2: public class ContactsController : ApiController
   3: {
   4:     public IHttpActionResult GetAllContacts()
   5:     {
   6:         Contact[] contacts = new Contact[]
   7:         {
   8:             new Contact{ Name="張三", PhoneNo="123", EmailAddress="zhangsan@gmail.com"},
   9:             new Contact{ Name="李四", PhoneNo="456", EmailAddress="lisi@gmail.com"},
  10:             new Contact{ Name="王五", PhoneNo="789",EmailAddress="wangwu@gmail.com"},
  11:         };
  12:         return Json<IEnumerable<Contact>>(contacts);
  13:     }
  14: }
  15:  
  16: public class Contact
  17: {
  18:     public string Name { get; set; }
  19:     public string PhoneNo { get; set; }
  20:     public string EmailAddress { get; set; }
  21: }

如上麵的代碼片斷所示,我們為應用的EnableCorsAttribute特性指定了三個參數。根據參數名稱和上麵我們針對W3C的CORS規範的介紹,我們應該可以猜得到它們分別代表:授權的源站點,和請求所允許的自定義包頭和HTTP方法。我們將客戶端ASP.NET MVC應用所在的站點“https://localhost:9527”設置為授權的源站點,後兩者則直接設置為“*”表示對此不作任何限製。

接下來們在MvcApp應用中定義如下一個HomeController,默認的Action方法Index會將對應的View呈現出來。

   1: public class HomeController : Controller
   2: {
   3:     public ActionResult Index()
   4:     {
   5:         return View();
   6:     }
   7: }

如下所示的是Action方法Index對應View的定義。我們的目的在於:當頁麵成功加載之後以Ajax請求的形式調用上麵定義的Web API獲取聯係人列表,並將自呈現在頁麵上。如下麵的代碼片斷所示,Ajax調用和返回數據的呈現是通過調用jQuery的getJSON方法完成的。

   1: <html>
   2: <head>
   3:     <title>聯係人列表</title>
   4:     <script type="text/javascript" src="@Url.Content("~/scripts/jquery-1.10.2.js")"></script>
   1:  

   2: </head>

   3: <body>

   4:     <ul id="contacts"></ul>

   5:     <script type="text/javascript">

   6:         $(function ()

   7:         {

   8:             var url = "https://localhost:3721/api/contacts";

   9:             $.getJSON(url, null, function (contacts) {

  10:                 $.each(contacts, function (index, contact)

  11:                 {

  12:                     var html = "<li><ul>";

  13:                     html += "<li>Name: " + contact.Name + "</li>";

  14:                     html += "<li>Phone No:" + contact.PhoneNo + "</li>";

  15:                     html += "<li>Email Address: " + contact.EmailAddress + "</li>";

  16:                     html += "</ul>";

  17:                     $("#contacts").append($(html));

  18:                 });

  19:             });

  20:         });

  21:     
          </script>
   5: </body>
   6: </html>
10083601-2c6710f208e84125b777c15c07b80ef

現在運行我們的ASP.NET MVC程序,依然可以得到如右圖所示的輸出結果。從編程的角度來講,ASP.NET Web API針對CORS的實現僅僅涉及到兩個方麵:

  • 其一,HttpConfiguration的擴展方法EnableCors,它用於開啟ASP.NET Web API針對CORS的支持;
  • 其二,EnableCorsAttribute特性,它為目標HttpController或者Action方法定義CORS授權策略。

但是整個CORS體係不限於此,在它們背後隱藏著一係列的類型,我們將會利用後續的文章對此作全麵講述。

CORS係列文章
[1] 同源策略與JSONP
[2] 利用擴展讓ASP.NET Web API支持JSONP
[3] W3C的CORS規範
[4] 利用擴展讓ASP.NET Web API支持CORS
[5] ASP.NET Web API自身對CORS的支持: 從實例開始
[6] ASP.NET Web API自身對CORS的支持: CORS授權策略的定義和提供
[7] ASP.NET Web API自身對CORS的支持: CORS授權檢驗的實施
[8] ASP.NET Web API自身對CORS的支持: CorsMessageHandler


作者:蔣金楠
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
原文鏈接

最後更新:2017-10-25 15:33:40

  上一篇:go  通過擴展讓ASP.NET Web API支持W3C的CORS規範
  下一篇:go  ASP.NET Web API自身對CORS的支持: EnableCorsAttribute特性背後的故事