2009-08-29 25 views
8

Estoy tratando de pasar un objeto de una acción de controlador a otra. El objeto que estoy pasando alrededor se ve más o menos así:RedirectToAction (..) falla el objeto complejo complejo

public class Person 
{ 
    public string Name { get; set; } 
    public List<PhoneNumber> PhoneNumbers {get; set; } 
    public List<Address> Addresses { get; set; } 
} 

Mi controlador se ve así:

public class DialogController : Controller 
{ 
    public ActionResult Index() 
    { 
     // Complex object structure created 
     Person person = new Person(); 
     person.PhoneNumbers = new List(); 
     person.PhoneNumbers.Add("12341324"); 

     return RedirectToAction("Result", "Dialog", person); 

    } 

    public ActionResult Result(Person person) 
    { 
     string number = person.PhoneNumbers[0].ToString(); 
     return View(); 
    } 
} 

El método consecuencia falla con una excepción de puntero nulo ya que la lista es repente PHONENUMBERS null después de invocar la acción Result con el método RedirectToAction().

¿Alguien ha visto este tipo de comportamiento antes?

Saludos,

Peter

Respuesta

5

Estoy de acuerdo con @Dennis: a menos que desee que la URL cambie, tendrá que pensar en otra cosa. La razón es que RedirectToAction no serializa los datos, simplemente itera sobre las propiedades en el objeto de valores de ruta que construye una cadena de consulta con las claves que son los nombres de propiedad y los valores la representación de cadena de los valores de propiedad. Si desea que el Url cambie, entonces usar TempData es probablemente la forma más sencilla de hacerlo, aunque también puede almacenar el elemento en la base de datos, pasar el id al método Result y reconstituirlo desde allí.

+0

Hola T, Terminé usando el truco TempDaata para transferir objetos de una acción a la otra. Gracias por aclarar cómo funciona RedirectToAction. Esa fue la parte realmente confusa para mí. –

7

¿Usted realmente necesita para redirigir a la otra acción? RedirectToAction causa una nueva solicitud http, razón por la cual funciona TempData. ¿No podría simplemente llamar a la acción Result directamente así?

public ActionResult Index() 
{ 
    // Complex object structure created 
    Person person = new Person(); 
    person.PhoneNumbers = new List(); 
    person.PhoneNumbers.Add("12341324"); 

    return Result(person); 

} 

Editar A menos que su aplicación está haciendo más que lo que usted ha mostrado en la pregunta, que no se parece a lo que realmente necesita la acción Índice. Puede mover el código que crea una nueva persona a un método privado CreatePerson. En su acción Result si person es nulo, llame al método CreatePerson. La acción Index podría eliminarse por completo, pero eso requeriría modificar sus rutas. O simplemente deje que return RedirectToAction("Result", "Dialog"); sea la única línea de código en su acción Index.

En realidad, después de la separación de preocupaciones MVC, ese método CreatePerson probablemente debería ser un método dentro de su código de modelo. El controlador no debería contener la lógica de crear un nuevo Person. Eso realmente pertenece al modelo.

+0

Hola Dennis, Gracias por la respuesta. Tienes toda la razón sobre la creación de los objetos Persona. Gracias! –

2

Aunque esta es una pregunta anterior, encontré una great answer to it en lo que creo que es una pregunta duplicada. La clave es RouteValueDictionary constructor.

return RedirectToAction("Result", "Dialog", new RouteValueDictionary(person)) 

Puesto que usted tiene colecciones, que hace que sea un poco Tricker, but this other answer covers this very nicely.

0

Para todos, eso realmente necesita llamar alguna acción y devolver la vista desde otro controlador con objeto complejo y no quiere (o no puede) pasar el objeto en TempData.Yo uso en mi aplicación muy feo, pero la solución de trabajo:

protected ActionResult InternalRedirectToAction(string action, string controller, object model) 
{ 
    var htmlHelper = new HtmlHelper(new ViewContext(
           ControllerContext, 
           new WebFormView(ControllerContext, "HACK"), 
           new ViewDataDictionary(), 
           TempData, //for sharing TempData between Actions 
           new StringWriter()), 
         new ViewPage()); 

    var otherViewHtml = htmlHelper.Action(action, controller, model); 
    return Content(otherViewHtml.ToString()); 
} 

Inspirado en respuesta encuentran aquí: https://stackoverflow.com/a/4360019/1341409