C# 将JSON对象传递给MVC控制器时,string.empty转换为null
我正在将一个对象从客户端传递到服务器。在此过程中,表示为string.empty的对象属性将转换为null。我想知道当对象类型支持string.empty时如何防止这种情况C# 将JSON对象传递给MVC控制器时,string.empty转换为null,c#,javascript,jquery,asp.net-mvc,C#,Javascript,Jquery,Asp.net Mvc,我正在将一个对象从客户端传递到服务器。在此过程中,表示为string.empty的对象属性将转换为null。我想知道当对象类型支持string.empty时如何防止这种情况 console.log("DataToPost:", dataToPost); $.ajax({ type: "POST", contentType: 'application/json' url: "../../csweb/Orders/SaveOrderDetails/", data:
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);
}
});
我的模型包括可为空的DateTime对象。我无法强制服务器上的所有null都为string.empty
我使用的是AutoMapper,因此我不希望必须单独检查服务器上的属性。问题是,当字符串为空时,AutoMapper会将nullables变为null。另一个问题得到了我认为可以满足您需要的回答:当使用
$发布数据时。ajax
,null
不是数据
选项属性的可能值。如果使用http调试器查看请求,您将看到它已转换为空字符串
因此,我猜您的MVC控制器正在应用相反的转换
我在ajax应用程序中解决这个问题的方法是,我不使用
$.ajax()
的data
选项,而是用JSON序列化所有内容,并将其放在数据选项的单个字段“data”中。这样你就不会有空值的问题了。当然,您必须在服务器端进行反序列化。这是一个MVC特性,它将空字符串绑定到null
s
此逻辑由DefaultModelBinder
使用的属性控制
您可以使用DisplayFormat
属性设置convertEmptyStringToFull
public class OrderDetailsModel
{
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Comment { get; set; }
//...
}
但是,如果不想注释所有特性,可以创建自定义模型绑定器,将其设置为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);
}
}
您可以在行动中使用:
public ActionResult SaveOrderDetails([ModelBinder(typeof(EmptyStringModelBinder))]
OrderDetailsModel orderDetailsModel)
{
}
或者,您可以在Global.asax中将其全局设置为默认ModelBinder:
ModelBinders.Binders.DefaultBinder = new EmptyStringModelBinder();
您可以阅读有关此功能的更多信息。接受的答案对我使用MVC4不起作用。但是,下面的解决方法确实有效,我认为它会帮助其他人
public class CustomModelBinder : DefaultModelBinder
{
public bool ConvertEmptyStringToNull { get; set; }
public CustomModelBinder ()
{
}
public CustomModelBinder (bool convertEmptyStringToNull)
{
this.ConvertEmptyStringToNull = convertEmptyStringToNull;
}
protected override bool OnModelUpdating(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
// this little bit is required to override the ConvertEmptyStringToNull functionality that we do not want!
foreach (string propertyKey in bindingContext.PropertyMetadata.Keys)
{
if(bindingContext.PropertyMetadata[propertyKey] != null)
bindingContext.PropertyMetadata[propertyKey].ConvertEmptyStringToNull = this.ConvertEmptyStringToNull;
}
return base.OnModelUpdating(controllerContext, bindingContext);
}
}
这将解决MVC4+下的问题。bindingContext.ModelMetadata.ConvertEmptyStringToFull似乎被完全忽略,这是因为每个绑定属性的PropertyMetadata对象中都存在该设置。PropertyMetadata是在BindProperty()中重新创建的,因此如果在方法调用之前设置它,它将被覆盖,除非它作为绑定对象的属性存在(例如[DisplayFormat(ConvertEmptyStringToFull=false)]。没有人希望在每个属性上都这样做,因为这很愚蠢。与其像一些答案所建议的那样创建修改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;
}
}
尝试对数据进行字符串化:
data:JSON.stringify(dataToPost),
并且您还应该将contentType指定为:contentType:“application/JSON”
@nemesv感谢您的建议。应用JSON.stringify(dataToPost)并指定内容类型后,数据仍然显示为null。感谢您的回复。如果您查看我的第二个屏幕截图,您将看到我的监视窗口悬停在传递到SaveOrderDetails的参数上。AutoMapper还没有投入使用,但也许AutoMapper可以解决这个问题。我要玩一玩。这显然是这个问题的正确答案。非常感谢。更新:工程作为广告,太!如果如前所述仅为单个参数设置ModelBinderAttribute属性,则上述解决方案不起作用。似乎在绑定单个模型属性时使用了标准的DefaultModelBinder,这使得它们仍然为空。我对此的修复方法是将以下代码添加到重写的BindModel()方法的开头:Binders=newmodelbinderdictionary(){DefaultBinder=this}代码>确认:上面的示例无法在中应用属性action@Anders谢谢你的修复。我已经用信息更新了我的帖子。使用System.ComponentModel.DataAnnotations;我在阵列方面也面临类似的问题。当涉及到mvc操作的参数时,像“{foo:[]}”这样的Json字符串会导致foo=null。有没有办法调整默认mvc json反序列化程序的反序列化,使其将给定的json字符串转换为实际的空数组(也称为NOTNULL)?在mvc 5.2.3中,ModelMetadataProviders.Current
默认返回CachedDataAnnotationsModelMetadataProvider
的实例。CachedDataAnnotationsModelMetadataProvider
密封CreateMetaData方法,因此您不能像这里建议的那样覆盖它。我猜缓存提供程序的性能更好,所以我不确定这个答案是否是个好主意,因为它不使用缓存提供程序(而且无论如何也不能)。
ModelMetadataProviders.Current = new EmptyStringDataAnnotationsModelMetadataProvider();