jsonp媒体类型格式化程序c#问题
Posted
技术标签:
【中文标题】jsonp媒体类型格式化程序c#问题【英文标题】:jsonp media type formatter c# issue 【发布时间】:2013-07-09 22:12:56 【问题描述】:可能是一个愚蠢的问题,但我正在尝试将 jsonp 支持添加到我的 webapi 应用程序中。我将此行添加到我的 webapiconfig.cs,但它失败了,因为 jsonpmediatypeformatter 构造函数需要 2 个参数:
public static void Register(HttpConfiguration configuration)
configuration.Routes.MapHttpRoute("API Default", "api/v1/controller/id",
new id = RouteParameter.Optional );
var appXmlType = configuration.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
configuration.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
**configuration.Formatters.Insert(0, new JsonpMediaTypeFormatter();**
其中第一个似乎是 mediatypeformatter 类型,这对我来说没有多大意义。我试过了:
configuration.Formatters.Insert(0, new JsonpMediaTypeFormatter(new JsonMediaTypeFormatter(),"jsonp"));
它确实将响应正确地包装在一个名为 jsonp 的函数中,但也破坏了标准的 json 响应。
有什么想法吗?
【问题讨论】:
我认为由于 WebAPI 的默认序列化程序是 JSON.NET,因此需要将 mediatypeformatter 组合到一个子类中才能使 json 和 jsonp 工作(我使用的是 WebapiContrib.Formatting.Jsonp nuget包裹)。我在这里找到了一个似乎可以解决问题的解决方案:west-wind.com/weblog/posts/2012/Apr/02/… 【参考方案1】:我也花了很长时间才让它工作。此代码基于 https://gist.github.com/ninnemana/3715076 - 这对我不起作用,因为 HttpContext.Current
使用 .NET 框架的 4.5 版本返回 null。
这是课程:
public class JsonpMediaTypeFormatter : JsonMediaTypeFormatter
private string _callbackQueryParamter;
private HttpRequestMessage HttpRequest;
public JsonpMediaTypeFormatter()
SupportedMediaTypes.Add(DefaultMediaType);
SupportedMediaTypes.Add(new MediaTypeWithQualityHeaderValue("text/javascript"));
MediaTypeMappings.Add(new UriPathExtensionMapping("jsonp", DefaultMediaType));
public string CallbackQueryParameter
get return _callbackQueryParamter ?? "callback";
set _callbackQueryParamter = value;
public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type,
HttpRequestMessage request, MediaTypeHeaderValue mediaType)
HttpRequest = request;
return base.GetPerRequestFormatterInstance(type, request, mediaType);
public override System.Threading.Tasks.Task WriteToStreamAsync(Type type, object value, System.IO.Stream writeStream, System.Net.Http.HttpContent content, System.Net.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();
);
return base.WriteToStreamAsync(type, value, writeStream, content, transportContext);
private bool IsJsonpRequest(out string callback)
var query = HttpUtility.ParseQueryString(HttpRequest.RequestUri.Query);
callback = query[CallbackQueryParameter];
return !string.IsNullOrEmpty(callback);
这需要添加到您的启动中:
public class Startup
// This code configures Web API. The Startup class is specified as a type
// parameter in the WebApp.Start method.
public void Configuration(IAppBuilder appBuilder)
// Configure Web API for self-host.
HttpConfiguration config = new HttpConfiguration();
// Remove the XML formatter (only want JSON) see http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization
config.Formatters.Remove(config.Formatters.XmlFormatter);
// add jsonp formatter as the one with the highest prio
config.Formatters.Insert(0, new JsonpMediaTypeFormatter());
// routes
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/controller/arg1/arg2",
defaults: new arg1 = RouteParameter.Optional, arg2 = RouteParameter.Optional
);
appBuilder.UseWebApi(config);
【讨论】:
【参考方案2】:所以,我已经阅读了大量关于向 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。
【讨论】:
以上是关于jsonp媒体类型格式化程序c#问题的主要内容,如果未能解决你的问题,请参考以下文章
如何在 ServiceStack 中实现 JSONP 格式化程序
将奏鸣曲媒体与奏鸣曲格式化程序ckeditor集成的图像限制文件大小