【问题标题】:ASP.NET MVC UpdateModel empty propertyASP.NET MVC UpdateModel 空属性
【发布时间】:2013-01-29 23:05:31
【问题描述】:

给定以下模型,

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 为空。

【问题讨论】:

    标签: asp.net-mvc modelbinders


    【解决方案1】:

    我刚刚发现了这种行为(由于检查约束而偶然发现),我认为这是一个错误。我想知道现在有多少开发人员无意中将空字符串而不是 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();
    

    【讨论】:

      【解决方案2】:

      这有点相关,我认为它可以帮助那些以某种方式到达此页面的人。我正在使用 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);
          }
      }
      

      我希望这对某人有所帮助。

      【讨论】:

        【解决方案3】:

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

        【讨论】:

        • 如果我编辑一个已经设置了 InstanceOfA.Name 的 B 实例怎么办?我假设它将保持原始值。
        • 如果您不从 "Html.TextBox("A.Name")" 中删除文本,它将被发布。如果 B 的实例具有名称为空的 A 实例,则文本框将为空,因此该项目将在发布期间被删除,并且值不会更改为 null。
        【解决方案4】:

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

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

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

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

        【讨论】:

          【解决方案5】:

          谢谢你的回答,我稍微改了一下,不是所有的字符串属性都改了,不是字符串的属性也可以改。感谢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 );
            }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-05-17
            • 1970-01-01
            • 2015-01-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多