TryUpdateModel создает исключение NullReferenceException в модульном тесте ASP.NET MVC 3 - PullRequest
8 голосов
/ 12 ноября 2010

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

Вот трассировка стека исключения:

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

На случай, если это имеет значениемой контроллер имеет следующую подпись:

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

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

Ответы [ 3 ]

15 голосов
/ 16 декабря 2010

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

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

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

2 голосов
/ 27 января 2011

На случай, если кто-то еще столкнется с такой же проблемой и найдет этот пост:

Я решил проблему в общем на основе ответа Ивана Кортима (спасибо!) Со следующим фрагментом кода в конструкторе базового класса контроллера:

if (Request!=null && Request.Form != null && Request.Form.HasKeys() && ValueProvider == null)
{
    ValueProvider = new FormCollection(Request.Form).ToValueProvider();
}
1 голос
/ 12 ноября 2010

Вероятно, это изменение в реализации System.Web.Mvc.JsonValueProviderFactory.GetValueProvider, которое достигает значения в ControllerContext, которое является нулевым.

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

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

РЕДАКТИРОВАТЬ

Да, похоже, что он делает нулевую проверку на 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);
}

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

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

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

    controller.ControllerContext = controllerContext;

    controller.Edit(...);       
}

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

...