2012-03-19 31 views
2

我使用JsonNetFormatter发现here与ASP.Net MVC 4测试版网站中托管的Web API测试项目,并发现模型绑定似乎工作方式略有不同当我使用默认JsonMediaTypeFormatter。切换到JsonNetFormatter模型绑定后,似乎破坏了在URL中设置的参数。例如,下面的代码工作正常使用默认JsonMediaTypeFormatter,但是当我使用JsonNetFormatter被抛出此错误:在ASP.Net Web API中使用自定义MediaTypeFormatter的模型绑定错误

"The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Net.Http.HttpResponseMessage Put(Int32, WebAPISpike.Website.Api.Model.PutLesson)'...

JsonNetFormatter

public class JsonNetFormatter : MediaTypeFormatter 
{ 
    private JsonSerializerSettings _jsonSerializerSettings; 

    public JsonNetFormatter(JsonSerializerSettings jsonSerializerSettings) 
    { 
     _jsonSerializerSettings = jsonSerializerSettings ?? new JsonSerializerSettings(); 

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

    protected override bool CanReadType(Type type) 
    { 
     if (type == typeof(IKeyValueModel)) 
     { 
      return false; 
     } 

     return true; 
    } 

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

    protected override Task<object> OnReadFromStreamAsync(Type type, Stream stream, HttpContentHeaders contentHeaders, FormatterContext formatterContext) 
    { 
     // Create a serializer 
     JsonSerializer serializer = JsonSerializer.Create(_jsonSerializerSettings); 

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

    protected override Task OnWriteToStreamAsync(Type type, object value, Stream stream, HttpContentHeaders contentHeaders, FormatterContext formatterContext, 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, Encoding)) 
      { 
       using (JsonTextWriter jsonTextWriter = new JsonTextWriter(streamWriter)) 
       { 
        serializer.Serialize(jsonTextWriter, value); 
       } 
      } 
     }); 
    } 
} 

的Web API配置

var serializerSettings = new JsonSerializerSettings(); 
serializerSettings.Converters.Add(new IsoDateTimeConverter()); 

GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.JsonFormatter); 
GlobalConfiguration.Configuration.Formatters.Add(new JsonNetFormatter(serializerSettings)); 

控制器

public class LessonsController : ApiController { 
    public HttpResponseMessage Put(int id, PutLesson updates) { 
     // get lesson by id and update it with new values in from updates 
     return new HttpResponseMessage(HttpStatusCode.OK); 
    } 
} 

型号

public class PutLesson { 
    public string LessonName { get; set; } 
    public string Overview { get; set; } 
} 

我可以解决此问题由id参数移动到我的PutLesson模型,然后将其设置在那里,但当时它不是URI标识资源,它是请求主体。 JsonNetFormatter实施或我的配置中是否有缺失?

回答

1

这是WebAPI测试版中的一个错误(它发生在各种自定义MediaTypeFormatters中,它计划在下一个版本中修复)。此时此问题有两种解决方法。最“干净”似乎是添加一个ActionFilter,它会处理绑定这些参数给你。你可以阅读更多关于它在这里:

你可以找到有也讨论一个链接,包含了第二个解决方法。