Проблема данных формы привязки MVC - PullRequest
6 голосов
/ 06 апреля 2010

Я использую объект, который соответствует всем полям в моей форме. Затем я использую привязку по умолчанию для заполнения объекта в моем действии, например так:

public ActionResult GetDivisionData(DivisionObj FormData)

Мой DivisionObj инициализирует все свои значения в string.empty в конструкторе.

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

Есть ли способ изменить это так, чтобы неопубликованные данные были пустой строкой.

Ответы [ 3 ]

13 голосов
/ 06 апреля 2010

Это поведение по умолчанию для 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)], чтобы установить его для каждого свойства.

2 голосов
/ 06 апреля 2010

Вы всегда можете использовать [Bind(Exclude="PropertyName1,PropertyName2,PropertyName3")], чтобы исключить некоторые свойства из привязки:

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

Если вам действительно нужно иметь String.Empty в свойствах String, вы можете использовать это связующее:

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();
1 голос
/ 06 апреля 2010

Я могу только подтвердить, что вижу те же результаты, что и вы. Ваши варианты:

Один из способов - исключить свойства, как объяснил LukLed. Но это приведет к дублированию кода, и вам придется делать это при каждом действии контроллера каждый раз, когда DivisionObj (или любой другой класс Model, который вы хотите декорировать) появляется в качестве параметра действия. Так это немного громоздко ...

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

Я решил, что для меня лучше пойти с Custom Model Binder и делать большую часть этого материала там.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...