JSONP with ASP.NET Web API
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?
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.
以下是适用于WebAPI RC的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);
}
}
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;
}
链接地址: http://www.djcxy.com/p/20554.html