2012-03-02 3 views
2

Недавно я обнаружил, что, если я сказал:Модель Binding - Runtime Type

object latestPosts = new MyApp.Models.LatestPosts(); 
TryUpdateModel(latestPosts); 

The latestPosts объект не обновляется. Это связано с проблемой, найденной here. Использование обходного решения решило проблему. Однако, если я переношу lastPosts как свойство (называемое параметрами) существующего типа (например, Widget), он не обновляет модель. Например.

var widget = new Widget(); 
MyTryUpdateModel(widget, "Widget", null, null, ValueProvider); // LatestPosts doesn't update 

Но на следующий же работа:

MyTryUpdateModel(widget.Parameters, "Widget.Parameters", null, null, ValueProvider); 

Edit: Вот класс Widget:

public class Widget {   
    [Required, StringLength(100)] 
    public virtual string Name { get; set; } 

    private object _parameters; 
    public virtual object Parameters { 
     get { 
      // Code removed for brevity 
      if (_parameters == null) 
       _parameters = new MyApp.Models.LatestPosts(); 

      return _parameters; 
     } set { _parameters = value; } 
    } 
} 

А вот класс LatestPosts:

public class LatestPosts { 
    public int NumPosts { get; set; } 
} 

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

Благодаря

+0

Я не могу воспроизвести проблему. Оба работают для меня. Не могли бы вы представить полный пример, позволяющий воспроизвести проблему, включая то, как выглядят ваши классы моделей и что именно отправляется как значения в запросе? –

+0

Привет, Дарин, я, надеюсь, отредактировал вопрос с информацией, которую вам нужно помочь. Спасибо – nfplee

+0

не использовать TryUpdateModel/UpdateModel – Omu

ответ

0

Я explaim и почему оригинальный TryUpdateModel не работает и почему «заплата TryUpdateNode не работает в вашем случае. Я координатор Mvc управление Toolkit, который содержит сложную пользовательскую модель Binder, поэтому мы приобрели глубокие знания Model Binder и проблем, стоящих за ним.

По умолчанию TryUpdateModel: он просто вызывает DefaultModelBinder. Теперь определение типа во время выполнения на основе информации, полученной в процессе привязки модели, является рискованным, потому что такая информация поступает от клиента и может манипулировать злоумышленником, который таким образом может заставить связующее устройство создавать экземпляр типа, который он решил .... очень рискованно ... Он мог бы использовать это, чтобы заставить связующее устройство выполнить нежелательный вредоносный код, который находится в конструкторе типа «поддельный». Таким образом, общий выбор дизайна заключается в том, что ВСЕ ТИПЫ, используемые модельным связующим, ДОЛЖНЫ БЫТЬ ОПРЕДЕЛЕНЫ В ВРЕМЯ КОМПЛЕКСА

MyTryUpdateModel: он просто определяет тип корневой модели, вызывая GetType, а затем использовать эту информацию для вызова стандартного связующего на этот тип. Однако, за исключением этого «запуска» initia, модель Binder работает как обычно ... то есть ... тип свойств корневой модели, НЕ ПОЛУЧЕН С GetType или с информацией о времени исполнения, а просто проверяя тип свойства корневой модели ... что в вашем случае является объектом ... это означает отсутствие информации.

Устройства Defaul для пользовательских моделей инструментов Mvc Controls Toolkit имеют инструменты для определения типа во время выполнения ... но не ВСЕ ТИПЫ ... потому что они подвержены риску заражений ... типов, которые являются подтипами «безопасных» типов .. для типов экземпляров, которые реализуют интерфейс.

+0

Спасибо, я надеялся, что моя первоначальная проблема может быть решена с использованием настраиваемого связующего. У меня уже есть собственное собственное связующее устройство, но было бы здорово добавить к нему эту функциональность. Я быстро просмотрел код в файле ExDefaultBinder.cs, но я не могу точно определить точный бит кода, который обрабатывает это. Я был бы признателен, если бы вы могли показать урезанную версию с кодом, необходимым для этого.Спасибо – nfplee

+0

Не так просто, ExDefaulModelBinder просто добавляет дополнительные точки. Вы можете указать «новое поведение, написав» обработчик преобразования. Большинство элементов управления Mvc Controls Toolkit имеют обработчики Transformation, которые автоматически определяют подклассы. ОДНАКО, вам нужно указать свойство wich для присоединения обработчика преобразования! Обработчики преобразования в основном выполняют задачу построения состояния элемента управления ... но им необходимо прикрепить «элемент управления» или поведение определенного свойства ViewMdel. Если вы хотите изменить поведение по всем свойствам, которые вы не можете использовать, я использую мое собственное связующее устройство. –

+0

Создание связующего custo, которое обнаруживает классы по свойствам ALL, не сложно, но ему нужна информация о том, какой тип подтипа будет создан, если значение не является presnt в модели и ему необходимо его создать. Например, в вашем случае свойство Parameters может быть нулевым, и в этом случае устройство Binder должно быть способно его создать ... но как? ... ExDefaultModelBinder опирается на информацию, записанную в скрытое поле, когда страница отображается ... затем на почте этот скрытый файл проверяется, чтобы прочитать информацию о типе, который нужно создать. Если вы дадите мне больше информации в этот момент, я могу отправить код –