存储来自1个ActionResult的js值以在另一个ActionResult中使用

时间:2013-05-10 12:27:08

标签: c# javascript jquery asp.net-mvc asp.net-mvc-3

我有一个Controller,在其中一个ActionResult中,有一个我可以通过以下方式访问的javascript值:

Request.QueryString["frequency"]

但我需要在另一个ActionResult中使用相同的变量。我怎样才能做到这一点?

我知道我无法设置

string frequency = "";

位于Controller的顶部,然后只需设置在第一个ActionResult

2 个答案:

答案 0 :(得分:10)

当你说ActionResult时,我假设你的意思是控制器中返回Actionresult s的Action方法? e.g:

public class HomeController : Controller {
    // GET: /Home/
    public ActionResult Index() {
        var freq = Request.QueryString["frequency"];
        // ** Want to persist freq here **
        HomeIndexViewModel model = FooLogic.BarIndex();
        return View();
    }
    // GET: /Home/Detail
    public ActionResult Detail() {
        var freq = **Want to access freq here**;
        HomeDetailViewModel model = FooLogic.BarDetail(freq);
        return View();
    }
}

正如您的问题引用ActionResult,这可能是任何类型的ActionResult - 如果不知道您正在做什么,这个答案概述了选择状态持久性存储的一般方法。

要问自己的关键问题是:

  • 需要查看此值 - 只是请求生成该值的用户或其他用户,
    • 如果用户特定,他们是否已登录?是否有会话?
  • 他们需要多久才能看到它(仅下一个请求,或者可能是第二天)
  • 他们希望看到它(仅在当前浏览器中,或在另一个会话中)

您对数据持久性的选择很多且各不相同,每个选项都扮演着略微不同的角色,尽管许多角色在其潜在用途中与其他角色重叠(例如SessionTempData)。我在下面列出了其中的许多内容,所有这些都可以根据具体情况解决您的问题。前两个(查看持久数据或TempData)最有可能对您有用,但在没有更多信息的情况下,其他可能实际上是您需要的信息。

过去至少Nine Options for Managing Persistent User State in ASP.NET,其中许多仍然适用于MVC。


ViewDataViewBag

  • 可用于:当前请求中的当前用户,但您可以使用它来存储状态"在生成的html中准备好传递给将来的请求
  • 仅当您的ActionResult实际上是View(而不是重定向或其他ActionResult,如FileStreamResult)时才相关
  • 允许您将数据从当前控制器操作传递到正在生成的当前视图,这意味着您可以将其插入到客户端对象中,这些对象可以在下一个请求中将其发送回来,例如:
    • 隐藏的表格字段;
    • 查询下一个请求的字符串参数;或
    • ajax请求的javascript变量。

这方面的一个示例是将您的freq变量传递给Index方法(例如,使用ViewBag.Frequency = freq;,然后将其与@Html.ActionLink一起使用。例如:< / p>

@Html.ActionLink("Click for the Next Action", "Detail", "Home", 
  new { frequency = ViewBag.Frequency }, null)

您的详细信息操作将变为:

    public ActionResult Detail(int frequency) { ...

例如,通过使用var freq = @Html.Raw(Viewbag.Frequency);设置javascript变量,类似的方法可以让您使用hidden form fields中的值或javascript中的值来表示未来的AJAX请求。

注意:有一种思想流派(我认为这是一个很好的学校)你不应该使用这些,而应该创建一个强类型的类(例如高于HomeIndexViewModel的每个视图的模型允许您更好地测试您的控制器操作和视图。

ViewData / ViewBag的优点:

  • 它会在您的服务器上维护无状态,这样您就不必担心工作进程被回收,下一个请求会转到Web场中的其他服务器等。
  • 可能是&#34;后退按钮证明&#34;作为你的状态&#34;位于已呈现的页面

缺点:

  • 仅用于呈现html的有用操作
  • 并非所有数据都应该是后退按钮证明,某些数据应该不断发展,因此存储为服务器端状态(例如,页面点击次数)

TempData

  • 可用于:当前用户,在此内容和下一个请求中
  • 默认情况下(在MVC 4中),这是由SessionStateTempDataProvider实现的(请参阅documentation
  • 当你的ActionResult重定向到另一个Action时,它真的意味着使用,这样你就知道你存储的数据的确切范围和生命周期。

表面上看,它的设计完全符合您的要求,但也有考虑因素。

  • 它依赖于会话状态,因此仅当您已正确配置会话状态时,才适用于Web场和Web园方案。
  • 根据您的设置,会话状态也可能不会在工作进程回收之间持续存在。
  • 您还必须担心&#34;后退按钮&#34;或F5方案,因为第二次可能无法获得数据。

Session

  • 可用于:当前用户,在他们当前的会话中。范围还取决于您如何配置会话状态(例如,在应用程序域本地,或者在Web场中备份和可用的数据库)

这与TempData具有相同的注意事项,但您选择何时从Session中删除值。它实际上是用于与当前会话相关的一般信息(例如,如果用户关闭并重新打开浏览器,或者稍后在他们的移动电话上访问该网站,则用户不希望看到的简单购物车)。 / p>


Cache

  • 可用于:所有用户,但仅限于当前应用程序域内(因此请注意工作进程回收,Web场,Web园等)。

您可以通过Controller的HttpContext属性访问它。 E.g:

HttpContext.Cache["Frequency"] = freq;

缓存

  • 可用于:当前用户,但仅限于用于原始请求的浏览器

Cookie经常被忽略为状态持久性 - 但它们对某些类型的数据非常有用。请记住,如果用户希望看到与用户身份相关联的数据,那么如果他们在另一台计算机上登录,使用隐身/私人浏览器会话等,则cookie无法提供帮助。


数据库

  • 可用于:所有用户,或只是当前用户,您可以选择任意长或短的时间 -

数据库是状态持久性的父亲。您的应用程序代码应被视为易失性,并能够处理重新启动,Web场方案等。如果要存储数据,请使用数据库。通过&#34;数据库&#34;我的意思是任何形式的数据持久性介质,从SQL Server到Redis,Azure文件存储,Azure表存储,Amazon S3等。


其他选项

还有其他选择,但它们并不常见。例如,您可以实现自己的缓存(example here),或使用...

静态或单例类

  • 可用于:所有用户,对该服务器上该工作进程的所有请求
  • 数据将仅在单个工作进程中保留(因此这对Web场和Web园区有影响),并且只有在asp工作进程重新启动之前
  • 线程安全仍然是一个问题,但至少你可以在该类中封装线程安全逻辑
  • 由于耦合到工作进程的生命周期和单个服务器
  • ,因此很少有用

什么不使用

控制器类字段(实例)

  • 可用于:当前用户,仅限当前请求 (免责声明:我相信在所有版本的MVC中为每个请求创建一个新的Controller,但如果不是这样,那么你永远不会用这些来存储状态)

从理论上讲,你永远不会使用这些(除非这是一个10分钟的同事演示应用程序):

  • 由于类的实例字段仅在类的持续时间内持续存在(因此是当前请求的持续时间),如果要存储请求的状态(数据),则应使用Action方法中的变量来更好地传达意图/管理对象/值的范围。
  • 因此,如果您在控制器中使用实例字段,则可能正在共享您从Action调用的控制器方法的数据。
  • 这意味着您可能正在使用控制器来制定业务逻辑。
  • 当前的最佳实践要求控制器应该是调用业务逻辑(包括任何一代视图模型)的动作集合(瘦,不胖,控制器)。
  • Ergo:控制器类实例字段表示您应该重构代码

控制器上需要实例字段的时间是为所有操作提供公共服务,例如IoC接口,但这些服务不会在请求中或跨请求存储状态。


控制器类字段(静态)

  • 可用于:所有用户,对该服务器上该工作进程的所有请求
  • 不是一个好主意 - 所有线程上的所有用户都可以使用静态字段,因此您必须担心线程安全。如果您想在所有用户之间共享数据,可以使用更好的状态商店,例如Cache

答案 1 :(得分:3)

HTTP是无状态的,每个请求都有自己的状态和Controller实例。

您可以使用使用TempData的{​​{1}},但在阅读后删除该值。