jquery jsonpmediatypeformatter - JSONP with ASP.NET Web API




8 Answers

After asking this question, I finally found what I needed, so I am answering it.

I ran across this JsonpMediaTypeFormatter. Add it into the Application_Start of your global.asax by doing this:

var config = GlobalConfiguration.Configuration;
config.Formatters.Insert(0, new JsonpMediaTypeFormatter());

and you are good to go with an JQuery AJAX call that looks like this:

$.ajax({
    url: 'http://myurl.com',
    type: 'GET',
    dataType: 'jsonp',
    success: function (data) {
        alert(data.MyProperty);
    }
})

It seems to work very well.

core webapicontrib

I am working on creating a new set of services in ASP.MVC MVC 4 using the Web API. So far, it's great. I have created the service and gotten it to work, and now I am trying to consume it using JQuery. I can get back the JSON string using Fiddler, and it seems to be ok, but because the service exists on a separate site, trying to call it with JQuery errors with the "Not Allowed". So, this is clearly a case where I need to use JSONP.

I know that the Web API is new, but I'm hoping someone out there can help me.

How do I make a call to a Web API method using JSONP?




You can use an ActionFilterAttribute like this:

public class JsonCallbackAttribute : ActionFilterAttribute
{
    private const string CallbackQueryParameter = "callback";

    public override void OnActionExecuted(HttpActionExecutedContext context)
    {
        var callback = string.Empty;

        if (IsJsonp(out callback))
        {
            var jsonBuilder = new StringBuilder(callback);

            jsonBuilder.AppendFormat("({0})", context.Response.Content.ReadAsStringAsync().Result);

            context.Response.Content = new StringContent(jsonBuilder.ToString());
        }

        base.OnActionExecuted(context);
    }

    private bool IsJsonp(out string callback)
    {
        callback = HttpContext.Current.Request.QueryString[CallbackQueryParameter];

        return !string.IsNullOrEmpty(callback);
    }
}

Then put it on your action:

[JsonCallback]
public IEnumerable<User> User()
{
    return _user;
}






Updated

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 writeStream, HttpContent content, TransportContext transportContext)
        {
            string callback;

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

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

                    writer.Write(")");
                    writer.Flush();
                });
            }
            else
            {
                return base.WriteToStreamAsync(type, value, writeStream, 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);
        }
    }



johperl, Thomas. The answer given by Peter Moberg above should be correct for the RC version as the JsonMediaTypeFormatter that he inherits from uses the NewtonSoft Json serializer already, and so what he has should work with out any changes.

However, why on earth are people still using out parameters, when you could just do the following

public override Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContentHeaders contentHeaders, TransportContext transportContext)
        {
            var isJsonpRequest = IsJsonpRequest();

            if(isJsonpRequest.Item1)
            {
                return Task.Factory.StartNew(() =>
                {
                    var writer = new StreamWriter(stream);
                    writer.Write(isJsonpRequest.Item2 + "(");
                    writer.Flush();
                    base.WriteToStreamAsync(type, value, stream, contentHeaders, transportContext).Wait();
                    writer.Write(")");
                    writer.Flush();
                });
            }

            return base.WriteToStreamAsync(type, value, stream, contentHeaders, transportContext);
        }

        private Tuple<bool, string> IsJsonpRequest()
        {
            if(HttpContext.Current.Request.HttpMethod != "GET")
                return new Tuple<bool, string>(false, null);

            var callback = HttpContext.Current.Request.QueryString[CallbackQueryParameter];

            return new Tuple<bool, string>(!string.IsNullOrEmpty(callback), callback);
        }



Unfortunately, I don't have enough reputation to comment, so I'll post an answer. @Justin raised the issue of running the WebApiContrib.Formatting.Jsonp formatter alongside the standard JsonFormatter. That issue is resolved in the latest release (actually released some time ago). Also, it should work with the latest Web API release.







We can solve CORS(Cross-origin resource sharing)issue using two ways,

1)Using Jsonp 2)Enabling the Cors

1)Using Jsonp- to use the Jsonp we need to install WebApiContrib.Formatting.Jsonp nuget package and need to add JsonpFormmater in WebApiConfig.cs refer screenshots,

Jquery code

2)Enabling the Cors -

to enable the cors we need to add Microsoft.AspNet.WebApi.Cors nuget package and need to enable cors in WebApiConfig.cs refer screenshot

For more reference, you can refer my sample repo on GitHub using the following link. https://github.com/mahesh353/Ninject.WebAPi/tree/develop




Related

jquery jsonp asp.net-mvc-4 asp.net-web-api