#c# #asp.net-core-mvc #model-binding #custom-model-binder #asp.net-core-webapi
#c# #asp.net-core-mvc #привязка модели #custom-model-binder #asp.net-core-webapi
Вопрос:
Я пишу и ASP.NET Приложение Core 1, в котором есть контроллер веб-API, где поставщик будет размещать данные.
Это упрощенная версия класса модели, к которой я буду привязывать входящие данные:
public class Lead
{
public int SupplierId { get; set; }
public DateTime Date { get; set; }
}
Проблема в том, что даты будут опубликованы, например, с немецким форматированием 30.09.2016
. Я не хочу устанавливать глобальную культуру приложения de-DE
, потому что а) я не немец, и б) остальная часть приложения будет работать с датами ISO.
Я решил написать пользовательское IModelBinder
и, потому что это, по-видимому, обязательно в ASP.NET Ядро MVC, an IModelBinderProvider
.
Вот моя реализация IModelBinderProvider
:
public class GermanDateTimeModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context == null)
throw new ArgumentNullException(nameof(context));
if (!context.Metadata.IsComplexType amp;amp;
context.Metadata.ModelType == typeof(DateTime))
return new GermanDateTimeBinder();
return null;
}
}
Проблема в том, что my IModelBinderProvider
используется только для Lead
класса, т. Е. context.Metadata.ModelType == typeof(Lead)
.
Я бы ожидал, что привязка модели увидит, что мы не имеем дело с a DateTime
, двигаться дальше, а затем возвращаться для каждого свойства Lead
класса.
По-видимому, это не так, и мой обычай IModelBinder
никогда не попадает.
Причина, по которой я говорю, что IModelBinderProvider
это кажется обязательным, заключается в том, что я не нашел способа прямой регистрации IModelBinder
в конвейере MVC; Вместо этого я должен зарегистрировать IModelBinderProvider:
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc(options =>
{
options.ModelBinderProviders.Insert(0, new GermanDateTimeModelBinderProvider());
});
}
Как я могу получить ASP.NET Ядро MVC для применения моего пользовательского DateTime
связующего к Date
свойству Lead
класса?
Может быть, есть способ пропустить весь IModelBinderProvider
бизнес и использовать только an IModelBinder
?
Ответ №1:
Вы публикуете свои значения в формате JSON? Если это так, я бы посоветовал вам зарегистрировать пользовательский JsonConverter с JSON.NET . В конвертере вы будете использовать JsonSerializer с другой DateFormatString, в данном случае с немецким форматом даты. На все остальные JsonSerializer это не влияет.
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services
.AddMvc()
.AddJsonOptions(option =>
{
option.SerializerSettings.Converters.Add(new LeadConverter());
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddDebug();
app.UseMvcWithDefaultRoute();
}
}
public class LeadConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new System.NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var jsonSerializer = new JsonSerializer
{
DateFormatString = "dd.MM.yyyy"
};
return jsonSerializer.Deserialize<Lead>(reader);
}
public override bool CanConvert(Type objectType) => objectType == typeof(Lead);
}
Комментарии:
1. Спасибо за ваш ответ, это действительно очень хороший подход. Однако у нас есть обходной путь с DTO, который имеет
string
insetad ofDateTime
, а затем мы используем AutoMapper для анализа дат. Итак, этот вопрос касается не столько того, как я могу обойти проблему, сколько того, как на самом деле реализовать пользовательский ModelBinder в ASp.NET Ядро 1 🙂