2014-01-07 58 views
11

ASP.NET Web API小組決定使用JSON.NET庫來模型綁定JSON數據。但是,「正常」的MVC控制器仍然使用劣質的JsonDataContractSerializer。這會導致解析日期的問題,並導致我非常頭痛。如何將JSON.NET作爲ASP.NET MVC控制器的模型綁定器?

參考見本:
http://www.devcurry.com/2013/04/json-dates-are-different-in-aspnet-mvc.html

作者選擇解決問題的客戶端上的淘汰賽層。但我更願意通過在MVC控制器中使用與Web API控制器中相同的JSON.NET模型綁定器來解決此問題。

如何將不同的JSON模型綁定器替換爲ASP.NET MVC?具體來說,是JSON.NET庫。如果可能的話,從Web API使用相同的模型綁定器將是理想的。

+1

您是否檢查了相關問題:http://stackoverflow.com/questions/7109967/using-json-net-as-default-json-serializer-in-asp-net-mvc-3-is-it-可能或http://stackoverflow.com/questions/14591750/asp-net-mvc4-setting-the-default-json-serializer?lq=1? – nemesv

+0

哪個版本的mvc? – nawfal

回答

5

我已經這樣做了,而且高度定製的是Json.NET是幹什麼的,由系列化:

替換的global.asax.cs默認格式化,Application_Start

GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.JsonFormatter); 
GlobalConfiguration.Configuration.Formatters.Add(new CustomJsonMediaTypeFormatter()); 

和我CustomJsonMediaTypeFormatter是:

public static class CustomJsonSettings 
{ 
    private static JsonSerializerSettings _settings; 

    public static JsonSerializerSettings Instance 
    { 
     get 
     { 
      if (_settings == null) 
      { 
       var settings = new JsonSerializerSettings(); 

       // Must convert times coming from the client (always in UTC) to local - need both these parts: 
       settings.Converters.Add(new IsoDateTimeConverter { DateTimeStyles = System.Globalization.DateTimeStyles.AssumeUniversal }); // Critical part 1 
       settings.DateTimeZoneHandling = DateTimeZoneHandling.Local; // Critical part 2 

       // Skip circular references 
       settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; 

       // Handle special cases in json (self-referencing loops, etc) 
       settings.ContractResolver = new CustomJsonResolver(); 

       _settings = settings; 
      } 

      return _settings; 
     } 
    } 
} 

public class CustomJsonMediaTypeFormatter : MediaTypeFormatter 
{ 
    public JsonSerializerSettings _jsonSerializerSettings; 

    public CustomJsonMediaTypeFormatter() 
    { 
     _jsonSerializerSettings = CustomJsonSettings.Instance; 

     // Fill out the mediatype and encoding we support 
     SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json")); 
     SupportedEncodings.Add(new UTF8Encoding(false, true)); 
    } 

    public override bool CanReadType(Type type) 
    { 
     return true; 
    } 

    public override bool CanWriteType(Type type) 
    { 
     return true; 
    } 

    public override Task<object> ReadFromStreamAsync(Type type, Stream stream, HttpContent content, IFormatterLogger formatterLogger) 
    { 
     // Create a serializer 
     JsonSerializer serializer = JsonSerializer.Create(_jsonSerializerSettings); 

     // Create task reading the content 
     return Task.Factory.StartNew(() => 
     { 
      using (StreamReader streamReader = new StreamReader(stream, SupportedEncodings.First())) 
      { 
       using (JsonTextReader jsonTextReader = new JsonTextReader(streamReader)) 
       { 
        return serializer.Deserialize(jsonTextReader, type); 
       } 
      } 
     }); 
    } 

    public override Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContent content, TransportContext transportContext) 
    { 
     // Create a serializer 
     JsonSerializer serializer = JsonSerializer.Create(_jsonSerializerSettings); 

     // Create task writing the serialized content 
     return Task.Factory.StartNew(() => 
     { 
      using (StreamWriter streamWriter = new StreamWriter(stream, SupportedEncodings.First())) 
      { 
       using (JsonTextWriter jsonTextWriter = new JsonTextWriter(streamWriter)) 
       { 
        serializer.Serialize(jsonTextWriter, value); 
       } 
      } 
     }); 
    } 
} 

最後,CustomJsonResolver:

public class CustomJsonResolver : DefaultContractResolver 
{ 
    protected override IList<JsonProperty> CreateProperties(Type type, Newtonsoft.Json.MemberSerialization memberSerialization) 
    { 
     var list = base.CreateProperties(type, memberSerialization); 

     // Custom stuff for my app 
     if (type == typeof(Foo)) 
     { 
      RemoveProperty(list, "Bar"); 
      RemoveProperty(list, "Bar2"); 
     } 

     return list; 
    } 

    private void RemoveProperty(IList<JsonProperty> list, string propertyName) 
    { 
     var rmc = list.FirstOrDefault(x => x.PropertyName == propertyName); 

     if (rmc != null) 
     { 
      list.Remove(rmc); 
     } 
    } 
} 
+0

這是,但你可能不需要這一切,例如自定義解析器是特定於我的應用程序 –

+2

這似乎是爲WebApi,而不是MVC5。 –

+0

如果這是一個純粹的MVC5項目,那麼沒有GlobalConfiguration可用。這個問題顯然是針對MVC的 –

0

JsonNetValueProviderFactory proposed here比我嘗試過的其他程序(比如使用格雷格恩尼斯的數組有問題)效果更好。這個鏈接也提出了一個解決方案,從行動中返回Json。

相關問題