【问题标题】:Web Service is not wrapping JSON in JSONP callback?Web 服务没有在 JSONP 回调中包装 JSON?
【发布时间】:2014-05-11 04:55:35
【问题描述】:

我正在尝试让我的 .net MVC Web api 返回 JSONP。我有一个对 JsonpMediaTypeFormatter 的引用,基于它实现了一个 JsonFormatter,在我的 Application_Start() 函数中注册了它......以及使用“&callback=?”的客户端 json 调用jsonp 回调包装仍然没有返回......我错过了什么吗?

我尝试在格式化程序类中设置断点,它似乎从未被调用过?

代码位:

格式化程序:

    /// <summary>
/// Handles JsonP requests when requests are fired with text/javascript
/// </summary>
public class JsonpFormatter : JsonMediaTypeFormatter
{

    public JsonpFormatter()
    {
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/javascript"));

        JsonpParameterName = "callback";
    }

    /// <summary>
    ///  Name of the query string parameter to look for
    ///  the jsonp function name
    /// </summary>
    public string JsonpParameterName { get; set; }

    /// <summary>
    /// Captured name of the Jsonp function that the JSON call
    /// is wrapped in. Set in GetPerRequestFormatter Instance
    /// </summary>
    private string JsonpCallbackFunction;


    public override bool CanWriteType(Type type)
    {
        return true;
    }

    /// <summary>
    /// Override this method to capture the Request object
    /// </summary>
    /// <param name="type"></param>
    /// <param name="request"></param>
    /// <param name="mediaType"></param>
    /// <returns></returns>
    public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, System.Net.Http.HttpRequestMessage request, MediaTypeHeaderValue mediaType)
    {
        var formatter = new JsonpFormatter()
        {
            JsonpCallbackFunction = GetJsonCallbackFunction(request)
        };

        // this doesn't work unfortunately
        //formatter.SerializerSettings = GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings;

        // You have to reapply any JSON.NET default serializer Customizations here    
        formatter.SerializerSettings.Converters.Add(new StringEnumConverter());
        formatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;

        return formatter;
    }


    public override Task WriteToStreamAsync(Type type, object value,
                                    Stream stream,
                                    HttpContent content,
                                    TransportContext transportContext)
    {
        if (string.IsNullOrEmpty(JsonpCallbackFunction))
            return base.WriteToStreamAsync(type, value, stream, content, transportContext);

        StreamWriter writer = null;

        // write the pre-amble
        try
        {
            writer = new StreamWriter(stream);
            writer.Write(JsonpCallbackFunction + "(");
            writer.Flush();
        }
        catch (Exception ex)
        {
            try
            {
                if (writer != null)
                    writer.Dispose();
            }
            catch { }

            var tcs = new TaskCompletionSource<object>();
            tcs.SetException(ex);
            return tcs.Task;
        }

        return base.WriteToStreamAsync(type, value, stream, content, transportContext)
                   .ContinueWith(innerTask =>
                   {
                       if (innerTask.Status == TaskStatus.RanToCompletion)
                       {
                           writer.Write(")");
                           writer.Flush();
                       }

                   }, TaskContinuationOptions.ExecuteSynchronously)
                    .ContinueWith(innerTask =>
                    {
                        writer.Dispose();
                        return innerTask;

                    }, TaskContinuationOptions.ExecuteSynchronously)
                    .Unwrap();
    }

    /// <summary>
    /// Retrieves the Jsonp Callback function
    /// from the query string
    /// </summary>
    /// <returns></returns>
    private string GetJsonCallbackFunction(HttpRequestMessage request)
    {
        if (request.Method != HttpMethod.Get)
            return null;

        var query = HttpUtility.ParseQueryString(request.RequestUri.Query);
        var queryVal = query[this.JsonpParameterName];

        if (string.IsNullOrEmpty(queryVal))
            return null;

        return queryVal;
    }
}

注册:

protected void Application_Start()
    {
        InitializeDatabase();
        MapModels();

        GlobalConfiguration.Configuration.Formatters.Insert(0, new JsonpFormatter());
        GlobalConfiguration.Configure(WebApiConfig.Register);
    }

【问题讨论】:

  • 你要返回什么?
  • @JonathanM 它返回一个错误“[回调函数]没有被调用。”响应文本是未包装的纯 JSON 对象。

标签: jquery ajax asp.net-web-api callback jsonp


【解决方案1】:

尝试使用 nugget 包 WebApiContrib.Formatting.Jsonp JSONP 格式化程序,在 Application_Start 中像这样注册它

GlobalConfiguration.Configuration.AddJsonpFormatter();

我刚刚为我正在做的某件事创建了一个 MCV4 项目,并且需要同样的东西,添加了一个 api 控制器并可以对其进行 JSONP 调用。项目地址在这里:

https://github.com/WebApiContrib/WebApiContrib.Formatting.Jsonp

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-13
    • 2015-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-22
    • 2012-06-25
    • 2011-09-27
    相关资源
    最近更新 更多