2009-08-29 2 views
8

Я пытаюсь передать объект из одного действия контроллера в другое. Объект, который я передаю вокруг выглядит более или менее, как это:RedirectToAction (..) с сложным глубоким объектом не работает

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

Мой контроллер выглядит следующим образом:

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(); 
    } 
} 

Метод результат не удается с нулевым указателем исключением, так как список номера телефонов внезапно null после вызова действия Result с помощью метода RedirectToAction().

Кто-нибудь видел этот тип поведения раньше?

Приветствия,

Питер

ответ

5

Я согласен с @Dennis - если вы не хотите, чтобы Url изменился, вам придется подумать о чем-то другом. Причина в том, что RedirectToAction не сериализует данные, он просто выполняет итерации по свойствам объекта объектов маршрута, строя строку запроса, причем ключи являются именами свойств, а значения представляют собой строковое представление значений свойств. Если вы хотите изменить Url, то использование TempData, вероятно, самый простой способ сделать это, хотя вы также можете сохранить элемент в базе данных, передать идентификатор методу Result и восстановить его оттуда.

+0

Hi T, В итоге я использовал трюк TempDaata для переноса объектов из одного действия в другое. Спасибо, что выяснили, как работает RedirectToAction. Для меня это была путаница. – 2009-08-31 14:31:49

7

вам действительно нужно перенаправить к другому действию ли? RedirectToAction вызывает новый HTTP-запрос, поэтому TempData работает. Не могли бы вы просто вызвать действие Result прямо так?

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

    return Result(person); 

} 

Редактировать Если ваше приложение не делает больше, чем то, что вы показали в этом вопросе, это не выглядит, как вам действительно нужно действие Index. Вы можете перенести код, который создает нового человека, в частный метод CreatePerson. В вашем действии Result, если person имеет значение null, затем вызовите метод CreatePerson. Действие Index может быть полностью устранено, но это потребует изменения ваших маршрутов. Или просто позвольте return RedirectToAction("Result", "Dialog"); быть единственной строкой кода в вашем действии Index.

На самом деле, после разделения MVC проблем, что метод CreatePerson, вероятно, должен быть методом внутри вашего кода модели. Контроллер не должен содержать логику создания нового Person. Это действительно принадлежит модели.

+0

Привет Деннис, Спасибо за ответ. Вы совершенно правы в создании объектов Person. Спасибо! – 2009-08-31 14:29:48

2

Хотя это старый вопрос, я нашел great answer to it в том, что, по моему мнению, является дублирующим вопросом. Ключом является конструктор RouteValueDictionary.

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

Поскольку у вас есть коллекции, это делает его немного Tricker, but this other answer covers this very nicely.

0

Для всех это действительно необходимо вызвать какое-либо действие и вернуть представление с другого контроллера со сложным объектом и не хотеть (или не может) передать объект в TempData.Я использую в мое приложение очень некрасиво, но рабочий раствор:

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()); 
} 

Вдохновленный ответ здесь: https://stackoverflow.com/a/4360019/1341409

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