ASP.NET MVC UpdateModel пустое свойство - PullRequest
4 голосов
/ 18 февраля 2009

Учитывая следующую модель,

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.

В любом случае UpdateModel устанавливает для свойства A значение null, если для имени не было введено никакого значения?

Чтобы уточнить, это простой случай, мой сценарий реального мира содержит модели данных с сотнями свойств этого рода. Определение этих моделей данных не в моих руках. Поэтому мне нужно решение для общего случая, то есть не создавайте свойство, если значения не были введены.

Дальнейшее уточнение: мне нужно, чтобы это работало и в сценариях редактирования, т.е. экземпляр b с A.Name, установленным в "foo", редактируется, чтобы установить A.Name в "", я хочу, чтобы A было нулевым.

Ответы [ 5 ]

5 голосов
/ 12 марта 2009

Я только что обнаружил это поведение (случайно благодаря проверочному ограничению) и думаю, что это ошибка. Интересно, сколько разработчиков теперь непреднамеренно сохраняют пустые строки в своей базе данных вместо нуля? : -)

В любом случае, я собираюсь исследовать это немного подробнее и посмотреть, есть ли лучшее решение.

Обновление:

Вот решение:

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();
3 голосов
/ 25 ноября 2011

Это как-то связано, и я подумал, что это может помочь тем, кто каким-то образом достиг этой страницы. Я работаю с ASP.NET MVC 3, и в этой версии, когда пустое текстовое поле отправляется на сервер, оно привязано к модели как нулевое.

Мне пришлось написать противоположное связующее для модели, которое заменяет пустые строки на пустые.

Я взял вышеуказанный код Эндрю Питерса (спасибо за это!) И изменил его на следующий.

На что обратить внимание:

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

Надеюсь, это кому-нибудь поможет.

2 голосов
/ 12 августа 2009

Похоже, что ASP.NET MVC 2 Preview 1 сделает это за вас при выполнении привязки модели.

т. конвертировать автоматически? Foo = & Bar = cat в

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

Я на самом деле предпочитаю использовать пустую строку вместо нуля, так что я пока не уверен, является ли ее окончательный дизайн, но, похоже, что-то изменилось.

2 голосов
/ 18 февраля 2009

UpdateModel инициализирует свойство, когда это свойство находится в FormCollection. Для того чтобы UpdateModel не устанавливал некоторые свойства на пустые значения, вы можете удалить все элементы из вашей коллекции FormCollection, где значение пусто. Для этого вы можете добавить метод расширения к типу NameValueCollection.

0 голосов
/ 29 января 2013

Спасибо за ваш ответ, я немного изменил его, чтобы не все свойства строки были изменены, и свойства, которые не являются строками, тоже можно изменить. Благодаря 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 );
  }
}
...