ASP.NET Core 1 (RTM) 中的自定义日期时间模型绑定器

Ser*_*eit 6 c# model-binding custom-model-binder asp.net-core-mvc asp.net-core-webapi

我正在编写 ASP.NET Core 1 应用程序,它有一个 Web API 控制器,供应商将在其中发布数据。

这是 Model 类的简化版本,我会将传入数据绑定到该类:

public class Lead
{
    public int SupplierId { get; set; }
    public DateTime Date { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

问题是日期将以德语格式发布,例如30.09.2016. 我不想将应用程序的全球文化设置为,de-DE因为 a) 我不是德国人,并且 b) 应用程序的其余部分将使用 ISO 日期。

我已经准备好编写一个自定义的IModelBinder,因为它在 ASP.NET Core MVC 中显然是强制性的,一个IModelBinderProvider.

这是我的实现IModelBinderProvider

public class GermanDateTimeModelBinderProvider : IModelBinderProvider
{
    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        if (context == null)
            throw new ArgumentNullException(nameof(context));

        if (!context.Metadata.IsComplexType && 
                context.Metadata.ModelType == typeof(DateTime))
            return new GermanDateTimeBinder();

        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是我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());
    });
}
Run Code Online (Sandbox Code Playgroud)

如何让 ASP.NET Core MVC 将我的自定义DateTime绑定器应用于类的Date属性Lead?有没有办法跳过整个IModelBinderProvider业务并只使用一个IModelBinder

Mar*_*usK 2

您是否以 JSON 形式发布您的值?如果是这样,我建议您使用 JSON.NET 注册一个自定义 JsonConverter。在转换器中,您将使用带有不同 DateFormatString 的 JsonSerializer,在本例中为德语日期格式。所有其他 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);
}
Run Code Online (Sandbox Code Playgroud)

  • 感谢您的回答,这确实是一个非常好的方法。然而,我们确实有一个解决方法,使用一个 DTO,其中包含“DateTime”的“string”,然后我们使用 AutoMapper 来解析日期。所以这个问题并不是关于如何解决这个问题,而是如何在 ASp.NET Core 1 中实际实现自定义 ModelBinder* :) (7认同)