具有复杂深层对象的RedirectToAction(..)失败

时间:2009-08-29 18:09:08

标签: asp.net-mvc

我正在尝试将对象从一个控制器操作传递到另一个控制器操作。我经过的对象或多或少看起来像这样:

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

结果方法因空指针异常而失败,因为在使用RedirectToAction()方法调用Result操作后,PhoneNumbers列表突然为null。

之前有没有人见过这种行为?

干杯,

彼得

4 个答案:

答案 0 :(得分: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);

}

修改除非你的应用所做的比你在问题中所展示的更多,否则看起来你真的不需要索引操作。您可以将创建新人的代码移动到私有CreatePerson方法中。如果Result为空,则在person操作中,然后调用CreatePerson方法。 Index行动可以完全取消,但这需要修改您的路线。或者让return RedirectToAction("Result", "Dialog");成为Index操作中唯一的代码行。

实际上,在关注MVC后,CreatePerson方法可能应该是模型代码中的一种方法。控制器不需要包含创建新Person的逻辑。这真的属于模型。

答案 1 :(得分:5)

我同意@Dennis - 除非您想要更改Url,否则您将不得不考虑其他事情。原因是RedirectToAction不会序列化数据,它只是遍历路由值对象中的属性,构造一个查询字符串,其中键是属性名称,值是属性值的字符串表示形式。如果您想要更改Url,那么使用TempData可能是最简单的方法,尽管您也可以将项目存储在数据库中,将id传递给Result方法,然后从那里重新构建它。

答案 2 :(得分:2)

虽然这是一个老问题,但我发现great answer to it我认为是一个重复的问题。关键是 RouteValueDictionary 构造函数。

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

由于你有集合,它会让它变得有点棘手,but this other answer covers this very nicely

答案 3 :(得分: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