8

Поскольку я обновил с MVC 2 до MVC 3 RC, использование TryUpdateModel вызывает исключение NullReferenceException. Эта проблема возникает только при запуске моего метода действий как части единичного теста. Запуск его на самом сервере работает, как ожидалось.TryUpdateModel throws NullReferenceException в ASP.NET MVC 3 unit test

Вот стека след за исключением:

System.NullReferenceException: Объект ссылка не указывает на экземпляр объекта . на System.Web.Mvc.JsonValueProviderFactory.GetValueProvider (ControllerContext controllerContext) на System.Web.Mvc.ValueProviderFactoryCollection. <> c_ DisplayClassc.b _7 (ValueProviderFactory завод) в System.Linq.Enumerable.WhereSelectEnumerableIterator 2.MoveNext() at System.Linq.Enumerable.WhereSelectEnumerableIterator 2.MoveNext() в System.Collections.Generic.List коллекция) в System.Linq. Enumerable.ToList [TSource] (IEnumerable`1 источник) в System.Web.Mvc.ValueProviderFactoryCollection.GetValueProvider (ControllerContext controllerContext) при System.Web.Mvc.Controller.TryUpdateModel [TModel] (TModel модели, префикс Строка)
... мой собственный код f ром здесь ....

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

[AcceptVerbs(HttpVerbs.Post)] 
public virtual ActionResult Edit(int id, FormCollection collection) 
{ 
} 

Я думаю, что это связано с новым способом DI работает в MVC3, но Я не могу понять, что я делаю неправильно. Возможно, есть что-то с точки зрения установки DI, которая требуется в MVC 3, но не требуется в MVC 2?

ответ

2

В случае, если кто-то имеет такую ​​же проблему и находит этот пост:

Я решил проблему в общем, основываясь на ответ Ивана Kortym, в следующей части кода в моем контроллере конструкторе базового класса (спасибо!):

if (Request!=null && Request.Form != null && Request.Form.HasKeys() && ValueProvider == null) 
{ 
    ValueProvider = new FormCollection(Request.Form).ToValueProvider(); 
} 
+2

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

+3

Почему бы просто не использовать строку «ValueProvider = ...» в настройке вашего контроллера в своих модульных тестах. – JoelFan

1

Это, вероятно, изменение в реализации System.Web.Mvc.JsonValueProviderFactory.GetValueProvider, которое имеет значение в ControllerContext, которое равно null.

Возможно, вам понадобится высмеять дополнительное значение в ControllerContext.

По крайней мере, именно там я бы посмотрел первым.

EDIT

Да, похоже, что делает проверку нулевой на controllerContext.

public override IValueProvider GetValueProvider(ControllerContext controllerContext) 
{ 
    if (controllerContext == null) 
    { 
     throw new ArgumentNullException("controllerContext"); 
    } 
    object deserializedObject = GetDeserializedObject(controllerContext); 
    if (deserializedObject == null) 
    { 
     return null; 
    } 
    Dictionary<string, object> backingStore = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); 
    AddToBackingStore(backingStore, string.Empty, deserializedObject); 
    return new DictionaryValueProvider<object>(backingStore, CultureInfo.CurrentCulture); 
} 

Из StackTrace мы можем видеть, что TryUpdateModel[TModel](TModel model, String prefix). Используя отражатель, он обращается к объекту ControllerBaseValueProvider. Это, в свою очередь, вызывает ValueProviderFactoryCollection.GetValueProvider(ControllerContext controllerContext) с текущими контроллерами ControllerContext.

Вы просто должны быть в состоянии создать новый экземпляр ControllerContext и установите свойство контроллера соответственно ...

[TestMethod] 
public void EditTest 
{ 
    var controller = new Controller();   
    var controllerContext = new ControllerContext(); 

    controller.ControllerContext = controllerContext; 

    controller.Edit(...);  
} 

Некоторые дополнительные насмешливый может потребоваться, чтобы заставить его полностью функционировать, хотя.Некоторая информация о том, как полностью макете ControllerContext: Mocking Asp.net-mvc Controller Context

+0

Я чувствую почти столько же, но какое значение мне нужно издеваться? И как я могу это сделать? Это, по-видимому, довольно распространенный сценарий ... –

+0

Обычный сценарий для нового кода не так уж и важен. ;) Почему бы вам не включить ваши текущие макеты, и тогда мы могли бы указать на вероятные дополнения. Вы издеваетесь над заголовком? – jfar

+0

Да, похоже, что источник MVC3 еще есть ... что может сделать вещи более сложными. Я загружу Reflector и посмотрю, что я могу найти. – bmancini

15

Вы должны добавить этот код:

FormCollection formValues = new FormCollection() 
     { 
      { "Test", "test" }, 
      { "FirstName", "TestName" } 
     }; 
     rootController.ValueProvider = formValues.ToValueProvider(); 

У меня такая же проблема, и этот код помогает мне.

Смежные вопросы