8

Desde que actualicé de MVC 2 a MVC 3 RC, el uso de TryUpdateModel causa una NullReferenceException. Este problema solo ocurre cuando ejecuto mi método de acción como parte de una prueba unitaria. Ejecutarlo en el servidor real funciona como se esperaba.TryUpdateModel lanza NullReferenceException en prueba de unidad ASP.NET MVC 3

Así es un seguimiento de pila de la excepción:

System.NullReferenceException: Objeto referencia no establecida en una instancia de un objeto . en System.Web.Mvc.JsonValueProviderFactory.GetValueProvider (ControllerContext controllerContext) en System.Web.Mvc.ValueProviderFactoryCollection. <> c_ DisplayClassc.b _7 (ValueProviderFactory fábrica) en System.Linq.Enumerable.WhereSelectEnumerableIterator 2.MoveNext() at System.Linq.Enumerable.WhereSelectEnumerableIterator 2.MoveNext() en System.Collections.Generic.List colección) en System.Linq. Enumerable.ToList [TSource] (IEnumerable`1 fuente) a System.Web.Mvc.ValueProviderFactoryCollection.GetValueProvider (ControllerContext ControllerContext) en System.Web.Mvc.Controller.TryUpdateModel [TModel] (TModel modelo, prefijo cadena)
... mi propio código f rom aquí en ....

En caso de que las cosas, mi controlador tiene la siguiente firma:

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

Mi conjetura es que esto tiene que ver con la nueva forma DI trabaja en MVC3, pero No puedo entender lo que estoy haciendo mal. Quizás hay algo en términos de configuración de DI que se requiere en MVC 3, pero no fue requerido en MVC 2?

Respuesta

2

En caso de que alguien más tiene el mismo problema y encuentra este mensaje:

He resuelto el problema de forma genérica basada en la respuesta de Ivan Kortym, con el siguiente fragmento de código en mi regulador del constructor de la clase base (gracias!):

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

No es una buena idea, porque está agregando código para facilitar las pruebas en el código de producción. También se ejecuta en cada solicitud, y es completamente innecesario. –

+3

¿Por qué no simplemente utiliza la línea "ValueProvider = ..." en la configuración de su controlador en las pruebas de su unidad. – JoelFan

1

Es probable que se trate de un cambio en la implementación de System.Web.Mvc.JsonValueProviderFactory.GetValueProvider que está golpeando un valor en ControllerContext que es nulo.

Es posible que deba burlarse de un valor adicional en ControllerContext.

Al menos ahí es donde miro primero.

EDITAR

Sí, parece que está haciendo un cheque nulo en 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); 
} 

Desde el StackTrace podemos ver que TryUpdateModel[TModel](TModel model, String prefix). Con el reflector, está accediendo a la propiedad ControllerBaseValueProvider. Esto a su vez llama al ValueProviderFactoryCollection.GetValueProvider(ControllerContext controllerContext) con la propiedad actual de Controladores ControllerContext.

Usted sólo debe ser capaz de crear un nuevo ControllerContext instancia y establezca la propiedad del controlador en consecuencia ...

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

    controller.ControllerContext = controllerContext; 

    controller.Edit(...);  
} 

Algunos de burla adicional puede ser necesario para conseguir que funcione totalmente sin embargo.Algo de información sobre cómo ControllerContext totalmente fingida: Mocking Asp.net-mvc Controller Context

+0

Supongo que casi tanto, pero ¿qué valor exactamente tengo que simular? ¿Y cómo puedo hacer esto? Este parece ser un escenario bastante común ... –

+0

Un escenario común para el código nuevo no es tan común. ;) ¿Por qué no incluye sus simulacros actuales y luego podríamos señalar posibles adiciones? ¿Te estás burlando del encabezado? – jfar

+0

Sí, no parece que la fuente MVC3 esté disponible todavía ... eso podría hacer que todo sea un poco más desafiante. Cargaré Reflector y veré qué puedo encontrar. – bmancini

15

Usted debe agregar este código:

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

Tengo el mismo problema y este código me ayuda.

Cuestiones relacionadas