通过扩展让ASP.NET Web API支持JSONP

我们通过继承JsonMediaTypeFormatter定义了如下一个JsonpMediaTypeFormatter类型。它的只读属性Callback代表JavaScript回调函数名称,改属性在构造函数中指定。在重写的方法WriteToStreamAsync中,对于非JSONP调用(回调函数不存在),我们直接调用基类的同名方法对响应对象实施针对JSON的序列化,否则调用WriteToStream方法将对象序列化后的JSON字符串填充到JavaScript回调函数中。

通过扩展让ASP.NET Web API支持JSONP
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Web;
using Newtonsoft.Json;

namespace MvcApplication2.Attributes
{
    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
        {

        }
    }
}
通过扩展让ASP.NET Web API支持JSONP

我们重写了GetPerRequestFormatterInstance方法,在默认情况下,当ASP.NET Web API采用内容协商机制选择出与当前请求相匹配的MediaTypeFormatter后,会调用此方法来创建真正用于序列化响应结果的MediaTypeFormatter对象。在重写的这个GetPerRequestFormatterInstance方法中,我们尝试从请求的URL中得到携带的JavaScript回调函数名称,即一个名为“callback”的查询字符串。如果回调函数名不存在,则直接返回自身,否则返回据此创建的JsonpMediaTypeFormatter对象。

将JsonpMediaTypeFormatter的应用到ASP.NET Web API中    

现在我们在WebApi应用的Global.asax中利用如下的程序创建这个JsonpMediaTypeFormatter对象并添加当前注册的MediaTypeFormatter列表中。为了让它被优先选择,我们将这个JsonpMediaTypeFormatter对象放在此列表的最前端。

通过扩展让ASP.NET Web API支持JSONP
protected void Application_Start()
        {
            GlobalConfiguration.Configuration.Formatters.Insert(0, new JsonpMediaTypeFormatter());
            
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
通过扩展让ASP.NET Web API支持JSONP

在ASP.NET MVC中调用:

通过扩展让ASP.NET Web API支持JSONP
<script src="~/Scripts/jquery-1.7.1.js"></script>
<script type="text/javascript">
    $(function() {

        $("#btnTest").click(function() {
            $.ajax({
                Type       : "GET",   
                url: "http://localhost:6120/api/values/5",
                dataType   : "jsonp",   
                success: function(data) {
                    alert(data);
                }

            });

        });
    });
</script>
<input type="button" value="click" id="btnTest" />
通过扩展让ASP.NET Web API支持JSONP

通过扩展让ASP.NET Web API支持JSONP,布布扣,bubuko.com

通过扩展让ASP.NET Web API支持JSONP

上一篇:浅谈使用 PHP 进行手机 APP 开发(API 接口开发)


下一篇:photoshop为美女人*作出逼真的陶瓷裂痕