先後端分離之CORS和WebApi

目前的項目是前端mv*+api的方式進行開發的,之前都是沒有跨域的方案,先後端人員在同一個解決方案裏邊進行開發,前端人員要用IIS或VS來開發和調試Api,這樣就很不方便,迫切須要跨域訪問Api.javascript

評選了不少解決方案最終選擇,CORS+WebApicss

cors科普:http://www.ruanyifeng.com/blog/2016/04/cors.htmlhtml

cors網站:http://enable-cors.org/前端

mvc源碼:https://github.com/ASP-NET-MVC/aspnetwebstack/blob/master/src/System.Web.Http.Cors/CorsMessageHandler.csjava

快速入門能夠看一些教程,本身要擴展源碼是一條捷徑.jquery

示例代碼:https://github.com/gutun/aspnet/tree/master/corsgit

1.新建WebApi項目實現CORS跨域github

1.1 新建一個新的項目CrossDomainweb

1.2. 安裝 Microsoft.AspNet.WebApi.Corsajax

Install-Package Microsoft.AspNet.WebApi.Cors

1.3. 配置App_Start目錄下的 WebApiConfig文件

Config中要啓用 CORS的支持我選擇默認的MediaType爲json方式。

1.4 新增UserController,在裏邊新增兩個方法,get用來ping,表明url是通的,post模擬真正的數據提交,咱們全部的api訪問走post, request的入參和出參能夠定義通用的實體。這裏模擬post提交數據解析成UserInfo的實例。

2.JQuery Ajax跨域

<!DOCTYPE html>
<html lang="en">
    <head>
        <title></title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
    </head>
    <body>
    <script>
        $.ajax({
            url:'http://localhost:64542/api/user',
            type:'POST',
            data:{"Id":"1","Name":"張三"},
            dataType:'json',
            //Content-Type:只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain
            //contentType: 'application/json; charset=utf-8',
            cache: false,
            crossDomain: true,
            success:function(data){
                alert(data);
            }
        });
    </script>
    </body>
</html>

使用Nodejs本地服務器訪問WebApi項目,成功的訪問到了api/User,狀態是200.

3.IE8,IE9支持CORS.

CORS在瀏覽器的支持狀況,IE8和IE9是部分兼容,86%的瀏覽器是支持的,佔了大部分,爲了支持IE8和IE9我找到了一個補丁jquery.transport.xdr.min.js 用來彌補在IE8和IE9下的不足。

https://github.com/gfdev/javascript-jquery-transport-xdr.js

<!DOCTYPE html>
<html lang="en">
    <head>
        <title></title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
        <script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
        <!--[if (IE 8)|(IE 9)]>
        <script src="http://cdn.rawgit.com/gfdev/javascript-jquery-transport-xdr/master/dist/jquery.transport.xdr.min.js"></script>
        <![endif]-->
    </head>
    <body>
    <script>
        //http://www.ruanyifeng.com/blog/2016/04/cors.html
        $.ajax({
            url:'http://localhost:64542/api/user',
            type:'POST',
            data:{"Id":"1","Name":"張三"},
            dataType:'json',
            //Content-Type:只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain
            //contentType: 'application/json; charset=utf-8',
            cache: false,
            crossDomain: true,
            success:function(data){
                alert(data);
            }
        });
    </script>
    </body>
</html>

喜出往外,跑起來後遇到了,415錯誤,未識別的Content-Type,這是由於在IE8和IE9下,Content-Type爲空形成的。

 

http://stackoverflow.com/questions/18964258/asp-web-api-post-request-with-cors-and-ie9-xdomainrequest-objec

新增DefaultContentTypeMessageHandler用來處理Request 

using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Cors;
using System.Web.Http.Cors;

namespace CrossDomain
{
    public class DefaultContentTypeMessageHandler : DelegatingHandler
    {
        protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            CorsRequestContext corsRequestContext = request.GetCorsRequestContext();
            if (corsRequestContext != null) //判斷是不是跨域的請求
            {
                if (request.Method == HttpMethod.Post && request.Content.Headers.ContentType == null) //ConentType爲空,使用默認值
                    request.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded");
            }

            var response = await base.SendAsync(request, cancellationToken);

            return response;
        }

    }
}

再次更改WebApiConfig文件,在MessageHandlers管道中追加剛寫的DefaultContentTypeMessageHandler,這樣ContentType爲空的跨域請求會使用默認的ContentType.

using System.Web.Http;
using System.Web.Http.Cors;

namespace CrossDomain
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            //新增CORS支持
            var corsAttr = new EnableCorsAttribute("*", "*", "*");
            config.EnableCors(corsAttr);
            //默認使用json格式,移除xml格式
            config.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
            //處理Content-Type
            config.MessageHandlers.Add(new DefaultContentTypeMessageHandler());

            // Web API configuration and services

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
}

在chrome,IE8,IE9,IE10+上測試沒有問題。

相關文章
相關標籤/搜索