所以,我已经阅读了大量关于向 WebAPI 添加 JSONP 支持的文章。我已经尝试过所有这些。
然后,我花时间阅读了我一直在使用的常规 Json 格式化程序......嘿,它也支持 Jsonp。
这是课程:
public class JsonNetFormatter : MediaTypeFormatter
{
private readonly JsonSerializerSettings _jsonSerializerSettings;
private string _callbackQueryParameter;
public JsonNetFormatter(JsonSerializerSettings jsonSerializerSettings)
{
_jsonSerializerSettings = jsonSerializerSettings ?? new JsonSerializerSettings();
// Fill out the mediatype and encoding we support
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
SupportedEncodings.Add(new UTF8Encoding(false, true));
//we also support jsonp.
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/javascript"));
}
private Encoding Encoding
{
get { return SupportedEncodings[0]; }
}
public string CallbackQueryParameter
{
get { return _callbackQueryParameter ?? "callback"; }
set { _callbackQueryParameter = value; }
}
public override bool CanReadType(Type type)
{
return true;
}
public override bool CanWriteType(Type type)
{
return true;
}
public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type,
HttpRequestMessage request,
MediaTypeHeaderValue mediaType)
{
var formatter = new JsonNetFormatter(_jsonSerializerSettings)
{
JsonpCallbackFunction = GetJsonCallbackFunction(request)
};
return formatter;
}
private string GetJsonCallbackFunction(HttpRequestMessage request)
{
if (request.Method != HttpMethod.Get)
return null;
var query = HttpUtility.ParseQueryString(request.RequestUri.Query);
var queryVal = query[CallbackQueryParameter];
if (string.IsNullOrEmpty(queryVal))
return null;
return queryVal;
}
private string JsonpCallbackFunction { get; set; }
public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
// Create a serializer
JsonSerializer serializer = JsonSerializer.Create(_jsonSerializerSettings);
// Create task reading the content
return Task.Factory.StartNew(() =>
{
using (var streamReader = new StreamReader(readStream, SupportedEncodings[0]))
{
using (var jsonTextReader = new JsonTextReader(streamReader))
{
return serializer.Deserialize(jsonTextReader, type);
}
}
});
}
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
{
var isJsonp = JsonpCallbackFunction != null;
// Create a serializer
JsonSerializer serializer = JsonSerializer.Create(_jsonSerializerSettings);
// Create task writing the serialized content
return Task.Factory.StartNew(() =>
{
using (var jsonTextWriter = new JsonTextWriter(new StreamWriter(writeStream, Encoding)) { CloseOutput = false })
{
if (isJsonp)
{
jsonTextWriter.WriteRaw(JsonpCallbackFunction + "(");
jsonTextWriter.Flush();
}
serializer.Serialize(jsonTextWriter, value);
jsonTextWriter.Flush();
if (isJsonp)
{
jsonTextWriter.WriteRaw(")");
jsonTextWriter.Flush();
}
}
});
}
}
然后,在你的 global.asax.cs 中添加这个小美:
private static void AddJsonFormatterAndSetDefault()
{
var serializerSettings = new JsonSerializerSettings();
serializerSettings.Converters.Add(new IsoDateTimeConverter());
var jsonFormatter = new JsonNetFormatter(serializerSettings);
jsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
GlobalConfiguration.Configuration.Formatters.Insert(0, jsonFormatter);
}
并从 Application_Start 调用它
这对我来说可以同时支持 json 和 jsonp。