Я использую JsonNetFormatter
найденный здесь с бета-проектом Web API, размещенным на бета-сайте ASP.Net MVC 4, и обнаружил, что привязка модели работает немного иначе, чем при использованиипо умолчанию 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 Config
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
или в моей конфигурации?