4

给定以下模型,

public class A
{
    public string Name { get; set; }
}

public class B
{
    public string Address { get; set; }
    public A InstanceOfA { get; set; }
}

看法,

<%= Html.TextBox("A.Name") %>

和控制器

UpdateModel<B>(b, collection.ToValueProvider());

我的 b 实例将包含 A 的属性,其中 Name 为空字符串。

如果没有为 name 输入值,是否有 UpdateModel 将 A 属性设置为 null ?

澄清一下,这是一个简单的案例,我的真实世界场景包含具有数百个此类属性的数据模型。这些数据模型的定义不在我的掌控之中。因此,我需要一个针对一般情况的解决方案,即如果没有输入任何值,则不要创建属性。

进一步说明:我也需要它在编辑场景中工作,即编辑 A.Name 设置为“foo”的 b 实例以将 A.Name 设置为“”,我希望 A 为空。

4

5 回答 5

5

我刚刚发现了这种行为(由于检查约束而偶然发现),我认为这是一个错误。我想知道现在有多少开发人员无意中将空字符串保存到他们的数据库中而不是 null?:-)

无论如何,我将对此进行更多探索,看看是否有更好的解决方案。

更新:

这是一个解决方案:

using System.ComponentModel;
using System.Web.Mvc;

namespace CustomerWebsite.Mvc
{
  public sealed class EmptyStringToNullModelBinder : DefaultModelBinder
  {
    protected override void SetProperty(ControllerContext controllerContext,
      ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, object value)
    {
      if ((value != null)
          && (value.GetType() == typeof(string)
              && ((string)value).Length == 0))
      {
        value = null;
      }

      base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value);
    }
  }
}

在 Application_Start 中输入:

ModelBinders.Binders.DefaultBinder = new EmptyStringToNullModelBinder();
于 2009-03-12T20:41:46.820 回答
3

这有点相关,我认为它可以帮助那些以某种方式到达此页面的人。我正在使用 ASP.NET MVC 3,在这个版本中,当一个空文本框发布到服务器时,它被绑定为 null 到模型。

我不得不编写相反的模型绑定器——将空字符串更改为空字符串。

我采用了 Andrew Peters 的上述代码(谢谢!)并将其更改为以下代码。

注意事项:

  1. 正如已经提到的 - 这个模型粘合剂做相反的事情。
  2. 我不是检查值的类型,而是通过 propertyDescriptor 检查它,我认为这更好,因为这是它的目的 - 描述值。就我而言,这是必不可少的,因为我无法检查为空的值。通过描述符我可以找到我需要的一切。

这是代码:

public sealed class CustomModelBinder : DefaultModelBinder
{
    protected override void SetProperty(ControllerContext controllerContext,
        ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, object value)
    {
        if (value == null && propertyDescriptor.PropertyType == typeof(string))
            value = string.Empty;

        base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value);
    }
}

我希望这可以帮助别人。

于 2011-11-25T02:25:54.230 回答
2

当该属性在 FormCollection 中时,UpdateModel 会初始化该属性。为了防止 UpdateModel 将某些属性设置为空值,您可以从 FormCollection 中删除值为空的所有项目。为此,您可以向 NameValueCollection 类型添加扩展方法。

于 2009-02-18T05:08:47.740 回答
2

在进行模型绑定时,ASP.NET MVC 2 Preview 1 似乎会为您执行此操作。

IE。自动转换 ?Foo=&Bar=cat 为

model.Foo = null;
model.Bar = "cat":

实际上,我更喜欢在 null 上获得一个空字符串,所以我不确定它是否是最终设计,但似乎确实有变化。

于 2009-08-11T23:37:44.113 回答
0

感谢您的回答,我对其进行了一些更改,以便并非所有字符串属性都被更改,并且不是字符串的属性也可以更改。感谢DefaultValueAttribute.

public class DefaultValueModelBinder: DefaultModelBinder
{
  protected override void SetProperty( ControllerContext controllerContext,
                                       ModelBindingContext bindingContext,
                                       PropertyDescriptor propertyDescriptor, 
                                       object value )
  {
    if( value == null )
    {
      var defaultValue = (DefaultValueAttribute)propertyDescriptor.Attributes[ typeof(DefaultValueAttribute) ];
      if( defaultValue != null )
        value = defaultValue.Value;
    }

    base.SetProperty( controllerContext, bindingContext, propertyDescriptor, value );
  }
}
于 2013-01-29T15:05:31.147 回答