Подтвердить что ты не робот

Почему ASP.NET MVC заботится о моих свойствах только для чтения во время привязки данных?

Изменить: добавлена ​​баунти, потому что я ищу решение MVC3 (если оно существует), кроме этого:

DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;


У меня есть свойство только для чтения на моей модели "Адрес" 'CityStateZip'.

Это просто удобный способ получить город, штат, почтовый индекс из американского адреса. Он выдает исключение, если страна не является США (вызывающий должен сначала проверить).

    public string CityStateZip
    {
        get
        {
            if (IsUSA == false)
            {
                throw new ApplicationException("CityStateZip not valid for international addresses!");
            }

            return (City + ", " + StateCd + " " + ZipOrPostal).Trim().Trim(new char[] {','});
        }
    }

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

Теперь, хотя с выпуском RC2 в январе 2010 года он дает мне ошибку во время привязки данных, потому что связующее устройство по умолчанию, похоже, хочет проверить это значение (хотя оно только для чтения).

Это строка "base.OnModelUpdated", которая вызывает эту ошибку.

public class AddressModelBinder : DefaultModelBinder
{
    protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        base.OnModelUpdated(controllerContext, bindingContext);

Последние изменения в modbinder, видимо, вызвали это изменение в поведении - но я еще не совсем уверен, что это за последствия - или это ошибка? Я передаю это команде MVC, но любопытно, есть ли у кого-либо другие предложения, тем временем, как я могу предотвратить привязку этого свойства.

В этой статье стоит прочитать об изменениях - но не упоминает свойства readonly вообще (не то, что я ожидал бы от нее). Проблема (если таковая есть) может быть шире этой ситуации - я просто не уверен в каких-либо повторениях - если есть!

Проверка ввода и проверка модели в ASP.NET MVC


В соответствии с запросом @haacked здесь stacktrace:

Я получаю это, просто добавив следующую строку в ЛЮБОЙ модель и сделав сообщение соответствующему методу действия. В этом случае я добавил его к моей самой простой возможной модели.

 public string Foo { get { throw new Exception("bar"); } }

[TargetInvocationException: свойство accessor 'Foo' на объекте 'Rolling_Razor_MVC.Models.ContactUsModel' выбрасывает следующее исключение: 'bar']   System.ComponentModel.ReflectPropertyDescriptor.GetValue(компонент объекта) +390    System.Web.Mvc. < gt; c__DisplayClassb. <GetPropertyValueAccessor> b__a() +18    System.Web.Mvc.ModelMetadata.get_Model() +22    System.Web.Mvc.ModelMetadata.get_RealModelType() +29    System.Web.Mvc. <GetValidatorsImpl> d__0.MoveNext() +38    System.Linq. <SelectManyIterator> d__14`2.MoveNext() +273    System.Web.Mvc. <Validate> d__5.MoveNext() +644    System.Web.Mvc.DefaultModelBinder.OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext) +92    System.Web.Mvc.DefaultModelBinder.BindComplexElementalModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Object model) +60    System.Web.Mvc.DefaultModelBinder.BindComplexModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +1048    System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +280    System.Web.Mvc.Controller.TryUpdateModel(модель TModel, префикс String, String [] includeProperties, String [] excludeProperties, IValueProvider valueProvider) +449    System.Web.Mvc.Controller.TryUpdateModel(модель TModel) +73

4b9b3361

Ответ 1

Я считаю, что испытываю подобную проблему. Я разместил детали:

http://forums.asp.net/t/1523362.aspx


edit: ответ от команды MVC (сверху URL):

Мы исследовали это и пришли к выводу, что система проверки ведет себя так, как ожидалось. Поскольку проверка модели включает попытку выполнить проверку по всем свойствам, а так как свойства типа null-null имеют неявный атрибут [Обязательный], мы проверяем это свойство и вызываем его получателя в процессе. Мы понимаем, что это разрывное изменение от V1 продукта, но необходимо, чтобы новая система проверки модели работала правильно.

У вас есть несколько возможностей обойти это. Любой из них должен работать:

  • Измените свойство Date на метод вместо свойства; таким образом, он будет игнорироваться инфраструктурой MVC.
  • Измените тип свойства на DateTime? вместо DateTime. Это удаляет неявное [Обязательное] из этого свойства.
  • Очистить флаг staticAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes. Это устраняет неявное [Обязательное] из всех свойств типа значения, не допускающего нулевое значение, для всей области приложения. Мы рассматриваем возможность добавления в V3 продукта атрибута, который будет сигнализировать нам "не связывать его, не проверять его, просто притворяйтесь, что это свойство не существует".

Еще раз спасибо за отчет!

Ответ 2

По-прежнему имеет ту же проблему с MVC3.

Я думаю, что лучший способ - это просто в global.asax(из ответа SevenCentral):

 DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;

Это будет отключено для всех из них

Ответ 3

Это ищет для меня весь мир, как ошибка. Я полностью не могу понять, почему ModelBinder должен проверять мои свойства только для чтения (могут быть некоторые технические подробности, но я определенно не понимаю и не желаю тратить время на попытки).

Я добавил следующий поставщик метаданных Model в мое решение, чтобы обойти проблему

protected override CachedDataAnnotationsModelMetadata CreateMetadataPrototype(IEnumerable<Attribute> attributes, Type containerType, Type modelType, string propertyName)
{
    var metadata = base.CreateMetadataPrototype(attributes, containerType, modelType, propertyName);

    if (metadata.IsReadOnly)
    {
        metadata.IsRequired = false;
    }

    return metadata;
}

protected override CachedDataAnnotationsModelMetadata CreateMetadataFromPrototype(CachedDataAnnotationsModelMetadata prototype, Func<object> modelAccessor)
{
    var metadata = base.CreateMetadataFromPrototype(prototype, modelAccessor);

    if (prototype.IsReadOnly)
    {
        metadata.IsRequired = false;
    }

    return metadata;
}

Вам также необходимо добавить следующее в Global.asax.cs

protected void Application_Start()
{
    ModelMetadataProviders.Current = new RESModelMetadataProvider();
    ModelBinders.Binders.Add(typeof(SmartDate), new SmartDateModelBinder());

    ...
}

Ответ 4

Конечно, я мог бы преобразовать CityStateZip в GetCityStateZip(), но потом я не могу связать его с чем-то вроде silverlight так же легко. Это может работать для временного исправления для всех, кто сталкивается с этой проблемой.

Ответ 5

У ЭТОЙ ТОЧНОЙ ПРОБЛЕМЫ!!

Для получения дополнительной информации о моей проблеме вы можете посетить ASP.NET MVC 2.0 Неиспользуемое свойство модели, которое вызывается при публикации продукта на сервер?

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

Между тем, у меня просто есть простая проверка "если", которая устраняет проблему.

Ответ 6

У меня была аналогичная проблема, поле, которое я не ожидал, чтобы быть проверенным, получал ошибку, когда форма была отправлена ​​обратно контроллеру. После некоторого googling я наткнулся на http://codeblog.shawson.co.uk/mvc-strongly-typed-view-returns-a-null-model-on-post-back/, где было указано, что конфликты имен могут вызвать проблемы.

Хотя я и не думал, что мой класс переменной post-back имеет конфликтующие имена свойств, переименование свойства, получившего ошибку, решило мою проблему.

Ответ 7

Та же проблема все еще существует в MVC 5.2.3, и это даже не код проверки, вызывающий проблему. DefaultModelBinder вызывает геттеры вне своего кода проверки, даже если они являются свойствами только для чтения, и даже если данные запроса не передаются в контроллер, соответствующий этим свойствам.

Смотрите более подробное объяснение и мое полное решение здесь: fooobar.com/info/15076399/....

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