ASP.NET Web API 自定义MediaType实现jsonp跨域调用

  代码来自《ASP.NET Web API 2 框架揭秘》一书。

  直接上代码:

  

 /// <summary>
    /// 自定义jsonp MediaType
    /// </summary>
    public class JsonpMediaTypeFormatter : JsonMediaTypeFormatter
    {
        //callback参数
        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)
        {
            //如果callback不存在,直接调用父类方法
            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 ex)
            {
                TaskCompletionSource<AsyncVoid> source = new TaskCompletionSource<AsyncVoid>();
                source.SetException(ex);
                return source.Task;
            }
        }


        private void WriteToStream(Type type, object value, Stream writeStream, HttpContent content)
        {
            JsonSerializer serializer = JsonSerializer.Create(this.SerializerSettings);
            using (StreamWriter writer = new StreamWriter(writeStream,this.SupportedEncodings.First())) {
                using (JsonTextWriter jsonTextWriter = new JsonTextWriter(writer) { CloseOutput = false }) {
                    //添加callback(json)
                    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(p => p.Key, p => p.Value).TryGetValue("callback", out callback)) {
                return new JsonpMediaTypeFormatter(callback);
            }
            return this;
        }

        [StructLayout(LayoutKind.Sequential, Size = 1)]
        private struct AsyncVoid { }
    }

  然后在Global.asax中将JsonpMediaTypeFormatter加入

  

 protected void Application_Start()
        { 
            //加入jsonpMediaTypeFormatter
            GlobalConfiguration.Configuration.Formatters.Insert(0, new JsonpMediaTypeFormatter());
            AreaRegistration.RegisterAllAreas();
         
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }

  Demo演示:

  我在localhost:55950 用jquery 调用api(http://localhost:55599/api/search?key=%E7%83%A7%E7%81%AB&from=0&size=10)

  

  得到结果如图:

  

  成功调用。不过书上说,这种方法仅限于get方法。

  OK,笔记完成,记录下来以防以后 用到可以参考参考。

posted @ 2016-07-14 16:48  丶Pz  阅读(1169)  评论(0编辑  收藏  举报