Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC UpdateModel empty property

Given the following Model,

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

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

View,

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

and Controller

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

my b instance will contain a property of A with an empty string for Name.

Is there anyway to have UpdateModel set the A property to null if no value has been entered for name?

To clarify, this is a simple case, my real world scenario contains data models with hundreds of properties of this ilk. The definition of these data models is out of my hands. Therefore I need a solution for the general case, ie don't create a property if no values have been entered.

Further clarification: i need this to work in edit scenarios aswell, i.e. an instance of b with A.Name set to "foo" is edited to set A.Name to "", i want A to be null.

like image 306
Neil Avatar asked Dec 17 '22 09:12

Neil


1 Answers

I just discovered this behavior (by accident thanks to a check constraint) and I think it is a mistake. I wonder how many devs are now inadvertently saving empty strings into their db instead of null? :-)

Anyway, I'm going to explore this a bit more and see if there is a better solution.

Update:

Here is a solution:

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);
    }
  }
}

And in Application_Start put this:

ModelBinders.Binders.DefaultBinder = new EmptyStringToNullModelBinder();
like image 143
Andrew Peters Avatar answered Dec 19 '22 22:12

Andrew Peters