You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在.NET Core中设置ConvertEmptyStringToNull默认值为false

ASP.NET Core 全局设置空字符串不自动转Null实现方案

原有实现失效原因

你之前编写的自定义元数据提供器存在两个核心问题:

  • 仅重写了GetMetadataForType方法,该方法仅返回类型本身的元数据,模型绑定、表单解析实际依赖的属性级元数据由CreatePropertyDetails方法生成,完全没有走到你设置ConvertEmptyStringToNull = false的逻辑。
  • 重写逻辑中手动创建了DisplayMetadataProviderContext,跳过了基类读取属性上标注的[DisplayFormat]等特性的流程,导致手动给字段加特性也会失效。

正确实现步骤

1. 编写自定义模型元数据提供器

重写创建类型元数据、属性元数据的两个核心方法,在基类生成的元数据基础上修改默认值,不覆盖显式标注的特性配置:

public class EmptyStringAllowedModelMetadataProvider : DefaultModelMetadataProvider
{
    public EmptyStringAllowedModelMetadataProvider(ICompositeMetadataDetailsProvider detailsProvider) : base(detailsProvider)
    {
    }

    public EmptyStringAllowedModelMetadataProvider(ICompositeMetadataDetailsProvider detailsProvider, IOptions<MvcOptions> optionsAccessor) : base(detailsProvider, optionsAccessor)
    {
    }

    protected override ModelMetadata CreateTypeDetails(ModelMetadataIdentity key)
    {
        var metadata = base.CreateTypeDetails(key);
        // 为string类型本身设置默认值
        if (metadata.ModelType == typeof(string))
        {
            metadata.DisplayMetadata.ConvertEmptyStringToNull = false;
        }
        return metadata;
    }

    protected override ModelMetadata CreatePropertyDetails(ModelMetadataIdentity key)
    {
        var metadata = base.CreatePropertyDetails(key);
        // 仅针对string类型属性修改默认值
        if (metadata.ModelType == typeof(string))
        {
            // 检查属性是否显式标注了DisplayFormatAttribute,有则保留特性配置,无则使用默认值false
            var hasExplicitDisplayFormat = metadata.Attributes.PropertyAttributes
                .Any(attr => attr is DisplayFormatAttribute);
            if (!hasExplicitDisplayFormat)
            {
                metadata.DisplayMetadata.ConvertEmptyStringToNull = false;
            }
        }
        return metadata;
    }
}

2. 注册自定义提供器替换默认实现

在Program.cs中(.NET 6+ 顶级语句模板),注册完MVC相关服务后,替换容器中默认的IModelMetadataProvider实例:

var builder = WebApplication.CreateBuilder(args);

// 原有服务注册,根据项目实际场景选择对应方法:AddRazorPages/AddControllers/AddControllersWithViews
builder.Services.AddControllersWithViews();

// 替换默认模型元数据提供器
builder.Services.AddSingleton<IModelMetadataProvider>(sp =>
{
    var compositeDetailsProvider = sp.GetRequiredService<ICompositeMetadataDetailsProvider>();
    var mvcOptions = sp.GetRequiredService<IOptions<MvcOptions>>();
    return new EmptyStringAllowedModelMetadataProvider(compositeDetailsProvider, mvcOptions);
});

var app = builder.Build();
// 后续中间件配置保持原有逻辑即可

如果是使用Startup.cs的旧版.NET Core 3.1/.NET 5项目,在ConfigureServices方法中添加上述注册逻辑即可。

补充说明

  • 该实现仅修改全局默认行为,如果你需要给特定字段开启空字符串转null,只需要在对应字段上显式标注[DisplayFormat(ConvertEmptyStringToNull = true)],显式配置优先级高于全局默认。
  • 该方案兼容ASP.NET Core 3.1到.NET 8的所有版本,不需要修改现有模型类的代码,所有string类型的字段、参数都会默认保留空字符串,不会自动转换为null。

内容的提问来源于stack exchange,提问作者TeamDman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 20:18:29