【问题标题】:MVC binding form data problemMVC绑定表单数据问题
【发布时间】:2011-02-04 19:46:25
【问题描述】:

我正在使用一个匹配表单中所有字段的对象。然后我使用默认绑定在我的操作中填充对象,如下所示;

public ActionResult GetDivisionData(DivisionObj FormData)

My DivisionObj 在构造函数中将它的所有值初始化为 string.empty。

问题在于,当绑定器从已发布的表单数据填充模型时,任何未发布的数据在对象中都设置为 null,即使我将对象初始化为包含空字符串。

有没有办法改变这一点,使未发布的数据成为一个空字符串。

【问题讨论】:

  • 您需要在控制器操作中将属性设置为空字符串,在业务逻辑或数据访问层中处理它。我建议这是您的 BL 的功能。

标签: asp.net-mvc


【解决方案1】:

您始终可以使用[Bind(Exclude="PropertyName1,PropertyName2,PropertyName3")] 将某些属性排除在绑定之外:

public ActionResult GetDivisionData([Bind(Exclude="PropertyName1,PropertyName2,PropertyName3")]DivisionObj FormData)

如果你真的必须在 String 属性中有 String.Empty,你可以使用这个 binder:

public class EmptyStringModelBinder : DefaultModelBinder
{
    protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor)
    {
        base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
        if (propertyDescriptor.PropertyType == typeof(String))
            propertyDescriptor.SetValue(bindingContext.Model,propertyDescriptor.GetValue(bindingContext.Model) ?? String.Empty);
    }
}

您还必须在 global.asax 中运行它:

ModelBinders.Binders.DefaultBinder = new EmptyStringModelBinder();

【讨论】:

  • 这样更有活力。我的用户可能会错误地填写表格。关键是如果字段留空,我需要我的对象包含 string.empty。
【解决方案2】:

我只能确认我看到的结果与您相同。您的选择是:

一种方法是像 LukLed 解释的那样排除属性。但这会导致代码重复,并且每次 DivisionObj(或您希望装饰的任何其他模型类)作为操作参数出现时,您都必须在每个控制器操作上执行此操作。所以有点麻烦……

我目前正在处理各种自定义属性的多个问题,一些需要在构造函数中实例化,一些需要仅在运行时知道的值,还有一些在某些方面也很特殊。

我已经确定对我来说最好使用自定义模型绑定器并在那里完成大部分工作。

【讨论】:

  • 所以你的意思是,如果在 post 数据中没有找到匹配的值,即使对象被初始化为 string.empty,默认模型绑定器也会使对象值为 null?
  • 我尝试了它,因为当我回答您的问题时,我手头有一些代码,并且它确实按照您的体验方式工作。但我不是 100% 确定它是否总是这样工作。您可以自己下载 ASP.NET MVC 源代码并查看 DefaultValueProvider 和 DefaultModelBinder 实现,并亲自了解它们是如何实现的。
【解决方案3】:

这是 DefaultModelBinder 的默认行为,更具体地说是 DataAnnotations 框架。 ConvertEmptyStringToNull 默认设置为 true。您可以创建自己的模型绑定器并替换默认模型绑定器。

public class EmptyStringModelBaseBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        bindingContext.ModelMetadata.ConvertEmptyStringToNull = false;

        return base.BindModel(controllerContext, bindingContext);
    }
}

然后在全球...

ModelBinders.Binders.DefaultBinder = new EmptyStringModelBaseBinder();

虽然我希望他们有一个静态的方式来为默认的模型绑定器设置这个。也许在 v3 中:)

或者,您也可以使用[DisplayFormat(ConvertEmptyStringToNull=false)] 属性在每个属性的基础上进行设置。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2011-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-17
相关资源
最近更新 更多