【发布时间】:2012-03-20 17:28:56
【问题描述】:
我将JsonNetFormatter 找到here 与托管在ASP.Net MVC 4 beta 站点中的Web API beta 项目一起使用,并发现模型绑定的工作方式似乎与我使用默认JsonMediaTypeFormatter 时略有不同.切换到 JsonNetFormatter 模型绑定后似乎忽略了 URL 中设置的参数。例如,下面的代码在默认的JsonMediaTypeFormatter 下运行良好,但是当我使用JsonNetFormatter 时会抛出这个错误:
"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 实现或我的配置中是否缺少某些内容?
【问题讨论】:
标签: model-binding asp.net-mvc-4 asp.net-web-api