我正在尝试将对象从一个控制器操作传递到另一个控制器操作。我经过的对象或多或少看起来像这样:
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。
之前有没有人见过这种行为?
干杯,
彼得
答案 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());
}