Asp.Net Web Api - ModelBinders
Мне нужно использовать какой-нибудь пользовательский механизм связывания, чтобы всегда обрабатывать входящие даты в британском формате, я настроил пользовательский механизм связывания и зарегистрировался следующим образом:
GlobalConfiguration.Configuration.BindParameter(typeof(DateTime), new DateTimeModelBinder());
Кажется, что это работает только для параметров строки запроса, и работает, только если я укажу [ModelBinder] в своем параметре, вот так, есть ли способ заставить все действия использовать мой связыватель модели:
public IList<LeadsLeadRowViewModel> Get([ModelBinder]LeadsIndexViewModel inputModel)
Кроме того, как я могу передать свою опубликованную форму на мой контроллер Api, чтобы использовать мою модель связующего?
4 ответа
Я думаю, вам не нужен модельный переплет. Ваш подход неверен. Правильный подход к датам - использование библиотеки глобализации на стороне клиента, такой как библиотека глобализации, для анализа дат, отформатированных на любом языке, и преобразования их в объекты дат JavaScript. Затем вы можете сериализовать свои структуры данных сценария данных в json с помощью браузера JSON.stringify, и это должно работать. Лучше всегда использовать стандартные форматы для дат и использовать средство форматирования, а не подшивку модели. Доступные средства форматирования также правильно обрабатывают часовые пояса, если вы используете параметр kind ваших объектов DateTime в C#, чтобы указать, будет ли время даты выражаться по местному времени или по времени UTC.
Вы можете зарегистрировать связыватель модели глобально, внедрив ModelBinderProvider и вставив его в список сервисов.
Пример использования в Global.asax:
GlobalConfiguration.Configuration.Services.Insert(typeof(ModelBinderProvider), 0, new Core.Api.ModelBinders.DateTimeModelBinderProvider());
Ниже приведен пример кода, демонстрирующего реализацию ModelBinderProvider и ModelProvider, которые преобразуют аргументы DateTime с учетом культуры (с использованием текущей культуры потоков);
Реализация DateTimeModelBinderProvider:
using System;
using System.Web.Http;
using System.Web.Http.ModelBinding;
...
public class DateTimeModelBinderProvider : ModelBinderProvider
{
readonly DateTimeModelBinder binder = new DateTimeModelBinder();
public override IModelBinder GetBinder(HttpConfiguration configuration, Type modelType)
{
if (DateTimeModelBinder.CanBindType(modelType))
{
return binder;
}
return null;
}
}
Реализация DateTimeModelBinder:
public class DateTimeModelBinder : IModelBinder
{
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
ValidateBindingContext(bindingContext);
if (!bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName) ||
!CanBindType(bindingContext.ModelType))
{
return false;
}
bindingContext.Model = bindingContext.ValueProvider
.GetValue(bindingContext.ModelName)
.ConvertTo(bindingContext.ModelType, Thread.CurrentThread.CurrentCulture);
bindingContext.ValidationNode.ValidateAllProperties = true;
return true;
}
private static void ValidateBindingContext(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException("bindingContext");
}
if (bindingContext.ModelMetadata == null)
{
throw new ArgumentException("ModelMetadata cannot be null", "bindingContext");
}
}
public static bool CanBindType(Type modelType)
{
return modelType == typeof(DateTime) || modelType == typeof(DateTime?);
}
}
Кажется, что атрибут маршрутизации конфликтует с привязкой модели. Если вы используете атрибут маршрутизации, вы можете обернуть global.asax
конфигурация в единый GlobalConfiguration.Config
позвоните, чтобы избежать проблем с инициализацией:
GlobalConfiguration.Configure(config =>
{
config.BindParameter(typeof(DateTime), new DateTimeModelBinder());
config.MapHttpAttributeRoutes();
}
(Это может быть исправлено в следующем ASP.NET 5, если это связано с ошибкой # 1165.)
Для этого вам не нужно настраивать связующее. Хорошо, если вы измените культуру потоков на UK или установите настройки web.config для UK, если это то, что ваш сайт использует все время.
Если нет, вы все равно можете изменить DateTimeFormatInfo для CurrentCulture на британский.
Скотт Хансельман также предлагает хороший пост о модельных папках.
Вы можете поместить это в Global.asax:
ModelBinders.Binders[typeof(DateTime)] = new DateAndTimeModelBinder()