2013-07-11 47 views
0

可能是一個愚蠢的問題,但我試圖添加jsonp支持到我的webapi應用程序。我加入這行我webapiconfig.cs,但它的失敗,因爲2個參數預計爲jsonpmediatypeformatter構造:jsonp媒體類型格式化程序問題

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響應。

任何想法?

+0

我想既然爲的WebAPI的默認的序列是JSON.NET,該mediatypeformatter必須組合成一個單獨的子類,讓json和jsonp工作(我使用的是WebapiContrib.Formatting.Jsonp nuget包)。我在這裏找到了一個解決方案,似乎可以做到: http://www.west-wind.com/weblog/posts/2012/Apr/02/Creating-a-JSONP-Formatter-for-ASPNET-Web- API – AesopWaits

回答

1

因此,我已閱讀了大量關於將JSONP支持添加到WebAPI的內容。我嘗試了所有這些。

然後,我花時間閱讀我一直使用的常規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。

2

我花了很長時間纔得到它的工作。此代碼基於https://gist.github.com/ninnemana/3715076 - 這對我不起作用,因爲HttpContext.Current在4.5版本的.NET框架中返回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); 
     } 
    }