Сделайте так, чтобы веб-API IModelBinder применялся ко всем экземплярам типа
Я использую пользовательский IModelBinder, чтобы попытаться преобразовать строки в NodaTime LocalDates. мой LocalDateBinder
выглядит так:
public class LocalDateBinder : IModelBinder
{
private readonly LocalDatePattern _localDatePattern = LocalDatePattern.IsoPattern;
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
if (bindingContext.ModelType != typeof(LocalDate))
return false;
var val = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (val == null)
return false;
var rawValue = val.RawValue as string;
var result = _localDatePattern.Parse(rawValue);
if (result.Success)
bindingContext.Model = result.Value;
return result.Success;
}
}
В моем WebApiConfig я регистрирую эту модель, используя SimpleModelBinderProvider
а-ля
var provider = new SimpleModelBinderProvider(typeof(LocalDate), new LocalDateBinder());
config.Services.Insert(typeof(ModelBinderProvider), 0, provider);
Это прекрасно работает, когда у меня есть действие, которое принимает параметр типа LocalDate, но если у меня есть более сложное действие, которое использует LocalDate внутри другой модели, оно никогда не запускается. Например:
[HttpGet]
[Route("validateDates")]
public async Task<IHttpActionResult> ValidateDates(string userName, [FromUri] LocalDate beginDate, [FromUri] LocalDate endDate)
{
//works fine
}
[HttpPost]
[Route("")]
public async Task<IHttpActionResult> Create(CreateRequest createRequest)
{
//doesn't bind LocalDate properties inside createRequest (other properties are bound correctly)
//i.e., createRequest.StartDate isn't bound
}
Я полагаю, что это как-то связано с тем, как я регистрирую подшивку модели в Web API, но я не знаю, что мне нужно исправить - нужен ли мне пользовательский провайдер подшивки?
1 ответ
Ваш CreateRequest
является сложным типом, для которого не определен преобразователь типов связывателя модели. В этом случае Web Api попытается использовать форматтер медиа-типа. Поскольку вы используете JSON, он попытается использовать форматтер JSON по умолчанию, который в стандартной конфигурации представляет собой Newtonsoft Json.Net. Json.Net не знает, как обрабатывать типы Noda Time из коробки.
Чтобы Json.Net мог обрабатывать типы Noda Time, вы должны установить https://www.nuget.org/packages/NodaTime.Serialization.JsonNet/ и добавить что-то подобное в свой код запуска...
public void Config(IAppBuilder app)
{
var config = new HttpConfiguration();
config.Formatters.JsonFormatter.SerializerSettings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
app.UseWebApi(config);
}
После этого ваш второй пример будет работать как положено, и ModelState.IsValid
будет false
если ввод был не в правильном формате Noda Time.
См. http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api для получения дополнительной информации о привязке параметров в Web API.