Asp.Net核心模型绑定,如何将空字段绑定为空字符串?

Ron*_*n C 5 data-binding asp.net-core

如果提交了类似下面MyField的表单并在表单上留空,则默认情况下,Asp.Net Core模型绑定将null置于模型上的相应属性中,如下所示.

示例表格

 <form asp-controller="SomeController" asp-action="SomeAction">
        <label asp-for="MyField">My Field</label><input asp-for="MyField" type="text" />    
        <button type="submit">Submit</button>
 </form>
Run Code Online (Sandbox Code Playgroud)


示例模型

 public class MyModel{
     public string MyField { get; set; }
 }
Run Code Online (Sandbox Code Playgroud)


示例操作方法

    [HttpPost]
    public IActionResult Post(MyModel m) {
          //m.MyField will be null if the field was left empty
          //but I want it set to a blank string by the model binder
    }
Run Code Online (Sandbox Code Playgroud)

但是,由于MyField实际上是在Http Post体中传输的,我更喜欢模型绑定器将模型上的MyField属性设置为空字符串,而不是将其设置为null.对于MyField未在Http Post机构中传输的情况,我宁愿保留null .如何更改模型绑定器以显示此行为?

Ron*_*n C 8

研究了在Asp.Net核心代码SimpleTypeModelBinder在https://github.com/aspnet/Mvc/blob/rel/1.1.3/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/SimpleTypeModelBinder.cs我能看到ModelMetadata.ConvertEmptyStringToNull默认情况下有一个设置为true,导致空字符串在数据绑定时转换为null.但该属性是只读的,所以一开始我无法弄清楚如何改变它的价值.

@ rsheptolut在这个页面上的帖子https://github.com/aspnet/Mvc/issues/4988让我找到了解决方案.

解:

该值必须在启动时设置.这可以通过这个类来完成:

       public class CustomMetadataProvider : IMetadataDetailsProvider, IDisplayMetadataProvider {
            public void CreateDisplayMetadata(DisplayMetadataProviderContext context) {

                if (context.Key.MetadataKind == ModelMetadataKind.Property) {

                    context.DisplayMetadata.ConvertEmptyStringToNull = false;
                }
            }
        }
Run Code Online (Sandbox Code Playgroud)

当它ConfigureServices在startup.cs文件的方法中将它挂入到MvcOptions中时就像这样

 services.AddMvc()
        .AddMvcOptions(options => options.ModelMetadataDetailsProviders.Add(new CustomMetadataProvider ())); 
Run Code Online (Sandbox Code Playgroud)

现在网站范围内,回发的空白字段的默认值将是数据绑定器将相应的模型属性设置为空字符串而不是null.是啊!

  • https://github.com/aspnet/Mvc/issues/7630建议每个属性添加属性[DisplayFormat(ConvertEmptyStringToNull = false)]将起作用. (2认同)