将JSON对象传递给MVC Controller时,string.empty转换为null

Sea*_*son 34 javascript c# asp.net-mvc jquery

我正在将一个对象从客户端传递给服务器.在此过程中,表示为string.empty的对象的属性将转换为null.当对象类型支持string.empty时,我想知道如何防止这种情况.

在此输入图像描述

console.log("DataToPost:", dataToPost);

$.ajax({
    type: "POST",
    contentType: 'application/json'
    url: "../../csweb/Orders/SaveOrderDetails/",
    data: dataToPost,
    success: function (result) {
        console.log(result);
    },
    error: function (e) {
        console.error(e);
    }
});
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

我的模型包含可空的DateTime对象.我不能强制服务器上的所有空值到string.empty.

我正在使用AutoMapper,所以我不想在服务器上单独检查属性.

nem*_*esv 72

这是一个MVC功能,它将空字符串绑定到nulls.

此逻辑由ModelMetadata.ConvertEmptyStringToNull属性控制,该属性由DefaultModelBinder.

您可以ConvertEmptyStringToNull使用DisplayFormat属性进行设置

public class OrderDetailsModel
{
    [DisplayFormat(ConvertEmptyStringToNull = false)]
    public string Comment { get; set; }

    //...
}
Run Code Online (Sandbox Code Playgroud)

但是,如果您不想注释所有属性,则可以创建自定义模型绑定器,并将其设置为false:

public class EmptyStringModelBinder : DefaultModelBinder 
{
    public override object BindModel(ControllerContext controllerContext,
                                     ModelBindingContext bindingContext)
    {
        bindingContext.ModelMetadata.ConvertEmptyStringToNull = false;
        Binders = new ModelBinderDictionary() { DefaultBinder = this };
        return base.BindModel(controllerContext, bindingContext);
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以在操作中使用ModelBinderAttribute:

public ActionResult SaveOrderDetails([ModelBinder(typeof(EmptyStringModelBinder))] 
       OrderDetailsModel orderDetailsModel)
{
}
Run Code Online (Sandbox Code Playgroud)

或者您可以在Global.asax中将其全局设置为Default ModelBinder:

ModelBinders.Binders.DefaultBinder = new EmptyStringModelBinder();
Run Code Online (Sandbox Code Playgroud)

您可以在此处详细了解此功能.

  • 如果我如上所述为单个参数设置ModelBinderAttribute-attribute,则上述解决方案不起作用.看起来在绑定单个模型属性时使用标准DefaultModelBinder,这使得它们无论如何都是null.我对此的修复是将以下代码添加到重写的BindModel()的开头 - 方法:`Binders = new ModelBinderDictionary(){DefaultBinder = this};` (6认同)

Los*_*ter 10

除了创建一个修改ModelMetadata的ModelBinder,而不是建议的一些答案,更清晰的替代方案是提供自定义的ModelMetadataProvider.

public class EmptyStringDataAnnotationsModelMetadataProvider : System.Web.Mvc.DataAnnotationsModelMetadataProvider 
{
    protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
    {
        var modelMetadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
        modelMetadata.ConvertEmptyStringToNull = false;
        return modelMetadata;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在Application_Start()中

ModelMetadataProviders.Current = new EmptyStringDataAnnotationsModelMetadataProvider();
Run Code Online (Sandbox Code Playgroud)