在ASP.NET MVC中重定向时如何传递复杂对象?

10

你好,

我有一个看起来像这样的操作:

[AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Register(AdRegister adRegister, IEnumerable<HttpPostedFileBase> files)

AdRegister是一个复杂的类,我需要将其传递给Register操作中进一步的重定向方法,代码如下:

return this.RedirectToAction("Validate", adRegister);

验证操作的代码如下:

public ActionResult Validate(AdRegister adRegister)

我知道可以传递简单的参数,但在这种情况下,它是一个复杂的对象。这个示例不起作用,adRegister的属性将为空。

这是否可能?如果是,该如何实现?

最好的问候

更多信息:注册操作将获取adRegister并对其执行某些操作,然后将其发送到验证操作。验证操作将向用户返回验证页面。当用户点击授权按钮时,adRgister将从表单中填充,然后发送到vValidate post中进行保存。我已经考虑过将adRegister暂时放置在缓存或数据库中,但如果我能简单地将其传递到下一个操作中,那将更好。

3个回答

18

一种可能的方法是将简单的属性通过查询字符串传递:

return RedirectToAction(
    "Validate", 
    new { 
        foo = adRegister.Foo, 
        bar = adRegister.Bar, 
        ... and so on for all the properties you want to send
    }
);

另一种可能性是将其存储在TempData中(对于重定向的生命周期)或Session中(对于ASP.NET会话的生命周期):

TempData["adRegister"] = adRegister;
return RedirectToAction("Validate");

然后从TempData中检索它:

public ActionResult Validate()
{
    adRegister = TempData["adRegister"] as AdRegister;
    ...
}

另一个可能性(也是我推荐的)是在您的数据存储库中将此对象持久化在POST方法中:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Register(AdRegister adRegister, IEnumerable<HttpPostedFileBase> files)
{
    ...
    string id = Repository.Save(adRegister);
    return RedirectToAction("Validate", new { id = adRegister.Id });
}

然后在重定向后从数据存储中获取它:

public ActionResult Validate(string id)
{
    AdRegister adRegister = Repository.Get(id);
    ...
}

好的,那么直接将复杂对象发送到操作是不可能的。TempData的问题可能在于用户刷新页面。也许最好的方法是将其存储在数据库中,然后使用一组间隔运行清理(如果用户到达第二阶段然后中止,数据仍将保留在数据库中)。 - Banshee
@SnowJim,是的,你说得对,关于用户刷新页面的问题。这就是为什么我不建议你使用它。最好的方法是将其存储在数据库或会话中。 - Darin Dimitrov
@Darin Dimitrov,是的,Session可能是可行的方法,我将不必清理数据库。唯一的问题是如果最终用户提交按钮很慢,但我想我可以将会话超时设置为60分钟。那就可以了。这也将占用更多的服务器内存,但完全不涉及数据库。假设我决定将其保存在数据库中,目标表将经常受到攻击,是否最好创建该表的副本并将临时数据放置在那里? - Banshee
@SnowJim,如果只是临时数据,那么使用会话可能更合适。但如果这些数据稍后可能被重复使用,最好将其永久存储在数据库中。当然,您也可以使用临时表,但如果您决定采用这种方法,您可能可以配置您的会话提供程序以使用SQL服务器,以便它不会存储在内存中,并且它将自动转到数据库中。这样,您就不会消耗服务器上的内存,并且不必关心持久性=>它是透明的。 - Darin Dimitrov
@Darin Dimitrov,感谢您的所有帮助!在这种情况下,用户将会:1. 填写表单并点击提交;2. 系统获取用户想要发布的广告;3. 触发验证操作并将广告数据发送回用户;4.a 最终用户授权广告并将其保存在数据库中;4.b 返回注册表单并自动填充已知数据。这就是复杂对象的生命周期。 - Banshee

1

一个想法可能是创建一个会话变量并传递一个引用该会话变量的密钥,如果需要在几个视图之间使用该对象?


是的,那可能行得通,唯一的问题是如果用户提交页面花费了很长时间,会话可能已经被删除。那么最好将其存储在数据库中。但是再次提醒,会话超时时间可以设置为60分钟,这应该足够了。 - Banshee
如果这个工作流程是特定的,需要很长时间并且需要保持会话实时进行,通过定期的ajax调用来保持会话实时进行比设置会话超时更好。 - Mark Redman

1

ASP.NET MVC的TempData对这个非常完美。

话虽如此,TempData或Session是一个选择,但也有一些缺点,比如违反了一些规则,而且经常会变得模糊或难以调试。更好的做法可能是将临时值“存储”在持久存储中,比如用户的个人资料或您自己的数据库中,然后通过验证方法传递一个键,该键可以从存储中加载数据。这还打开了恢复被放弃的购物车等可能性。


我有一个可以设置定时器的缓存。我可以将对象存储在此缓存中,然后每次用户提交更新时将超时时间设置为60分钟或类似时间。这意味着我不必手动清理数据库,如果用户进行一些奇怪的操作(如刷新等),我仍然可以恢复数据。 - Banshee
要小心了——在大多数情况下,ASP.NET缓存比Session存储更容易受到侵犯。当内存不足时,它是首先受到攻击的东西。我会使用Session而不是Cache来存储用户数据。 - Wyatt Barnett

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接