2016年8月5日 星期五

asp.net webapi jsonp跨網域取得資料


在asp.net Web API中寫jsonp,是不用更動到原本的API程式的,非常的簡單

View
$.ajax({
    url: 'http://localhost:53322/api/values',
    type: 'get',
    dataType: 'jsonp',
    success: function (e) {
  console.log(e);
    }
});

API Controller

public IEnumerable<string> Get()
{
    return new string[] { "value1", "value2" };
}

上面兩個jquery和web api的範例應該很多人都很熟了

下面是最重要的,必須在Global.asax.cs中,新增一個繼承自JsonMediaTypeFormatter的類別,我命名為JsonpMediaTypeFormatter
protected void Application_Start()
{
 ……
 var config = GlobalConfiguration.Configuration;
 config.Formatters.Insert(0, new JsonpMediaTypeFormatter());
}

public class JsonpMediaTypeFormatter : JsonMediaTypeFormatter
{
    private string callbackQueryParameter;

    public JsonpMediaTypeFormatter()
    {
        SupportedMediaTypes.Add(DefaultMediaType);
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/javascript"));

        MediaTypeMappings.Add(new UriPathExtensionMapping("jsonp", DefaultMediaType));
    }

    public string CallbackQueryParameter
    {
        get { return callbackQueryParameter ?? "callback"; }
        set { callbackQueryParameter = value; }
    }

    public override Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContent content, TransportContext transportContext)
    {
        string callback;

        if (IsJsonpRequest(out callback))
        {
            return Task.Factory.StartNew(() =>
            {
                var writer = new StreamWriter(stream);
                writer.Write(callback + "(");
                writer.Flush();

                base.WriteToStreamAsync(type, value, stream, content, transportContext).Wait();

                writer.Write(")");
                writer.Flush();
            });
        }
        else
        {
            return base.WriteToStreamAsync(type, value, stream, content, transportContext);
        }
    }

    private bool IsJsonpRequest(out string callback)
    {
        callback = null;

        if (HttpContext.Current.Request.HttpMethod != "GET")
            return false;
         callback = HttpContext.Current.Request.QueryString[CallbackQueryParameter];

        return !string.IsNullOrEmpty(callback);
    }
}

JsonpMediaTypeFormatter的作用是將jquery傳到web api的參數(callback),把ValuesController回傳的json資料包裝成一個function後回傳

所以我們就不用在ValuesController裡面處理Callback參數了




沒有留言:

張貼留言