国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

WebApi系列~在WebApi中實(shí)現(xiàn)Cors訪問

2019-11-15 02:31:05
字體:
供稿:網(wǎng)友

WebApi系列~在WebApi中實(shí)現(xiàn)Cors訪問

回到目錄

說在前

Cors是個(gè)比較熱的技術(shù),這在蔣金楠的博客里也有體現(xiàn),Cors簡單來說就是“跨域資源訪問”的意思,這種訪問我們指的是Ajax實(shí)現(xiàn)的異步訪問,形象點(diǎn)說就是,一個(gè)A網(wǎng)站公開一些接口方法,對(duì)于B網(wǎng)站和C網(wǎng)站可以通過發(fā)xmlhttPRequest請(qǐng)求來調(diào)用A網(wǎng)站的方法,對(duì)于xmlhttprequest封裝比較好的插件如jquery的$.ajax,它可以讓開發(fā)者很容易的編寫AJAX異步請(qǐng)求,無論是Get,Post,Put,Delete請(qǐng)求都可以發(fā)送。

Cors并不是什么新的技術(shù),它只是對(duì)HTTP請(qǐng)求頭進(jìn)行了一個(gè)加工,還有我們的Cors架構(gòu)里,對(duì)jsonp也有封裝,讓開發(fā)者在使用jsonp訪問里,編寫的代碼量更少,更直觀,呵呵。(Jsonp和Json沒什么關(guān)系,它是從一個(gè)URI返回一個(gè)Script響應(yīng)塊,所以,JSONP本身是和域名沒關(guān)系的,而傳統(tǒng)上的JSON是走xmlhttprequest的,它在默認(rèn)情況下,是不能跨域訪問的)

做在后

一  下面先說一下,對(duì)jsonp的封裝

1 注冊jsonp類型,在global.asax里application_Start方法中

 GlobalConfiguration.Configuration.Formatters.Insert(0, new EntityFrameworks.Web.Core.JsonpMediaTypeFormatter());

2 編寫JsonpMediaTypeFormatter這個(gè)類型中實(shí)現(xiàn)了對(duì)jsonp請(qǐng)求的響應(yīng),并在響應(yīng)流中添加指定信息,如callback方法名。

 /// <summary>    /// 對(duì)jsonp響應(yīng)流的封裝    /// </summary>    public class JsonpMediaTypeFormatter : JsonMediaTypeFormatter    {        public string Callback { get; private set; }        public JsonpMediaTypeFormatter(string callback = null)        {            this.Callback = callback;        }        public override Task WriteToStreamAsync(            Type type,            object value,            Stream writeStream,            HttpContent content,            TransportContext transportContext)        {            if (string.IsNullOrEmpty(this.Callback))            {                return base.WriteToStreamAsync(type, value, writeStream, content, transportContext);            }            try            {                this.WriteToStream(type, value, writeStream, content);                return Task.FromResult<AsyncVoid>(new AsyncVoid());            }            catch (Exception exception)            {                TaskCompletionSource<AsyncVoid> source = new TaskCompletionSource<AsyncVoid>();                source.SetException(exception);                return source.Task;            }        }        private void WriteToStream(            Type type,            object value,            Stream writeStream,            HttpContent content)        {            JsonSerializer serializer = JsonSerializer.Create(this.SerializerSettings);            using (StreamWriter streamWriter = new StreamWriter(writeStream, this.SupportedEncodings.First()))            using (JsonTextWriter jsonTextWriter = new JsonTextWriter(streamWriter) { CloSEOutput = false })            {                jsonTextWriter.WriteRaw(this.Callback + "(");                serializer.Serialize(jsonTextWriter, value);                jsonTextWriter.WriteRaw(")");            }        }        public override MediaTypeFormatter GetPerRequestFormatterInstance(            Type type,            HttpRequestMessage request,            MediaTypeHeaderValue mediaType)        {            if (request.Method != HttpMethod.Get)            {                return this;            }            string callback;            if (request.GetQueryNameValuePairs().ToDictionary(pair => pair.Key,                 pair => pair.Value).TryGetValue("callback", out callback))            {                return new JsonpMediaTypeFormatter(callback);            }            return this;        }        [StructLayout(LayoutKind.Sequential, Size = 1)]        private struct AsyncVoid        {        }    }

二  對(duì)指定域名實(shí)現(xiàn)友好的跨域資源訪問

1 在global.asax中注冊這個(gè)HttpHandler,使它對(duì)HTTP的處理進(jìn)行二次加工,它可以有同步和異步兩個(gè)版本,本例中實(shí)現(xiàn)異步方式實(shí)現(xiàn)

 //對(duì)指定URI的網(wǎng)站進(jìn)行跨域資源的共享 GlobalConfiguration.Configuration.MessageHandlers.Add(new EntityFrameworks.Web.Core.Handlers.CorsMessageHandler());

下面是MessageHandlers原代碼,實(shí)現(xiàn)對(duì)HTTP請(qǐng)求的二次處理

    /// <summary>    /// 跨域資源訪問的HTTP處理程序    /// </summary>    public class CorsMessageHandler : DelegatingHandler    {        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)        {            //得到描述目標(biāo)Action的HttpActionDescriptor            HttpMethod originalMethod = request.Method;            bool isPreflightRequest = request.IsPreflightRequest();            if (isPreflightRequest)            {                string method = request.Headers.GetValues("access-Control-Request-Method").First();                request.Method = new HttpMethod(method);            }            HttpConfiguration configuration = request.GetConfiguration();            HttpControllerDescriptor controllerDescriptor = configuration.Services.GetHttpControllerSelector().SelectController(request);            HttpControllerContext controllerContext = new HttpControllerContext(request.GetConfiguration(), request.GetRouteData(), request)            {                ControllerDescriptor = controllerDescriptor            };            HttpActionDescriptor actionDescriptor = configuration.Services.GetActionSelector().SelectAction(controllerContext);            //根據(jù)HttpActionDescriptor得到應(yīng)用的CorsAttribute特性            CorsAttribute corsAttribute = actionDescriptor.GetCustomAttributes<CorsAttribute>().FirstOrDefault() ??                controllerDescriptor.GetCustomAttributes<CorsAttribute>().FirstOrDefault();            if (null == corsAttribute)            {                return base.SendAsync(request, cancellationToken);            }            //利用CorsAttribute實(shí)施授權(quán)并生成響應(yīng)報(bào)頭            IDictionary<string, string> headers;            request.Method = originalMethod;            bool authorized = corsAttribute.TryEvaluate(request, out headers);            HttpResponseMessage response;            if (isPreflightRequest)            {                if (authorized)                {                    response = new HttpResponseMessage(HttpStatusCode.OK);                }                else                {                    response = request.CreateErrorResponse(HttpStatusCode.BadRequest, corsAttribute.ErrorMessage);                }            }            else            {                response = base.SendAsync(request, cancellationToken).Result;            }            //添加響應(yīng)報(bào)頭            if (headers != null && headers.Any())                foreach (var item in headers)                    response.Headers.Add(item.Key, item.Value);            return Task.FromResult<HttpResponseMessage>(response);        }    }

2 添加Cors特性,以便處理可以跨域訪問的域名,如B網(wǎng)站和C網(wǎng)站

    /// <summary>    /// Cors特性    /// </summary>   [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]       public class CorsAttribute : Attribute    {        public Uri[] AllowOrigins { get; private set; }        public string ErrorMessage { get; private set; }        public CorsAttribute(params string[] allowOrigins)        {            this.AllowOrigins = (allowOrigins ?? new string[0]).Select(origin => new Uri(origin)).ToArray();        }        public bool TryEvaluate(HttpRequestMessage request, out IDictionary<string, string> headers)        {            headers = null;            string origin = null;            try            {                origin = request.Headers.GetValues("Origin").FirstOrDefault();            }            catch (Exception)            {                this.ErrorMessage = "Cross-origin request denied";                return false;            }            Uri originUri = new Uri(origin);            if (this.AllowOrigins.Contains(originUri))            {                headers = this.GenerateResponseHeaders(request);                return true;            }            this.ErrorMessage = "Cross-origin request denied";            return false;        }        private IDictionary<string, string> GenerateResponseHeaders(HttpRequestMessage request)        {            //設(shè)置響應(yīng)頭"Access-Control-Allow-Methods"            string origin = request.Headers.GetValues("Origin").First();            Dictionary<string, string> headers = new Dictionary<string, string>();            headers.Add("Access-Control-Allow-Origin", origin);            if (request.IsPreflightRequest())            {                //設(shè)置響應(yīng)頭"Access-Control-Request-Headers"                //和"Access-Control-Allow-Headers"                headers.Add("Access-Control-Allow-Methods",
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 子洲县| 平果县| 静海县| 普安县| 江山市| 定日县| 乌什县| 苏州市| 城固县| 龙州县| 江都市| 鄂伦春自治旗| 磐石市| 正安县| 牟定县| 兰州市| 四子王旗| 五台县| 黔南| 阿鲁科尔沁旗| 大理市| 金溪县| 仙居县| 静安区| 丹棱县| 铜陵市| 颍上县| 额济纳旗| 本溪市| 上饶县| 丽江市| 宜黄县| 博野县| 彭山县| 西峡县| 于都县| 西昌市| 岳池县| 罗源县| 屯门区| 九江市|