2010-02-06 1 views
18

Edit: Добавлено Баунти, потому что я ищет решение MVC3 (если таковой существует), кроме этого:Почему ASP.NET MVC заботится о моих свойствах только для чтения во время привязки данных?

DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = ложь;


У меня есть свойство только для чтения на моей модели '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); 

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

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

Input Validation vs. Model Validation in ASP.NET MVC


В соответствии с просьбой @haacked вот StackTrace:

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

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

[TargetInvocationException: Свойство аксессор 'Foo' на объекте 'Rolling_Razor_MVC.Models.ContactUsModel' бросили следующее исключение: 'бар'] System.ComponentModel.ReflectPropertyDescriptor.GetValue (компонент объекта) + 390 System.Web.Mvc. < > 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. < Подтвердить > d__5.MoveNext() +644 System.Web.Mvc.DefaultModelBinder.OnModelUpdated (ControllerContext controllerContext, ModelBindingContext BindingContext) +92 System.Web.Mvc.DefaultModelBinder.BindComplexElementalModel (ControllerContext controllerContext, ModelBindingContext BindingContext, модель объекта) + 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 [] includeProperties, String [] excludeProperties, IValueProvider valueProvider) +449 System.Web.Mvc.Controller.TryUpdateModel (модель TModel) +73

+0

Что такое точную ошибку, которую вы видите? Было бы также полезно увидеть соответствующий контроллер и просмотреть код. –

+0

Нам нужно больше деталей, но я предполагаю, что IsUsa является ложным, когда мы пытаемся прочитать это свойство, которое вызывает исключение. Не уверен, почему мы будем читать его во время привязки к модели, хотя, если в форме, которая публикуется, есть поле формы с именем «CityStateZip». – Haacked

+0

@brad хорошо точная ошибка: «CityStateZip недействителен для международных адресов!» ;-) Я обновляю вопрос с помощью полной трассировки стека. Чтобы дублировать, просто добавьте это в ЛЮБЮЮ существующую модель, и у вас есть POST к соответствующему методу действия: public string Foo {get {throw new Exception ("bar"); }} –

ответ

16

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

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


редактировать: Ответ от команды MVC (из выше URL):

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

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

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

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

+0

Отметьте ответ на вышеупомянутое сообщение. – Rudy

+1

две вещи, на которые это не обращается, - это тот факт, что моя собственность была прочитана только для того, чтобы ее не нужно было «получить». поэтому это решение слегка прикручивает мой дизайн, но временные решения по-прежнему работают.во-вторых, это все равно взрывается с исключением. Это определенно не хорошо. если модель терпит неудачу, модель не работает, но взорвать не очень хорошо. –

+0

У меня такая же проблема, пожалуйста, прочитайте мой ответ со ссылкой, если хотите. я с нетерпением жду mvc v3, поскольку в v2 слишком много нерешенных/отсутствующих элементов, включая это и возможность возвращать несколько просмотров для обновления различных физических областей веб-страницы, улучшения пользовательской поддержки валидации на стороне сервера и т. д. ... обойти эти проблемы на данный момент, но только так, используя «хаки», и я не чувствую элегантность кодирования, которую я должен ощущать с помощью mvc; (- я не могу дождаться версии 3. –

0

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

0

У меня есть настоящая проблема!

Для получения дополнительной информации о моей проблеме, вы можете посетить ASP.NET MVC 2.0 Unused Model Property being called when posting a product to the server?

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

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

+1

, как правило, свойства предназначены именно для этого - тупые свойства, если у вас слишком много бизнес-логики, тогда да, вам придется внести изменения, но вы, возможно, должны все равно. Позор, они не могли добавить своего рода свойство «не проверять», но, возможно, это придет для MVC3 –

2

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

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

DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false; 

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

0

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

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

1

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

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

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

    ... 
} 
+0

Уверенный, это должен быть принятый ответ: полностью решает проблему у источника. Новые версии MVC имеют разные имена методов: 'GetMetadataForProperty'. VS может автоматически создавать заглушки, если вы наберете' protected override', n просто добавьте инструкции if. – David784