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

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

 Request.QueryString["frequency"] 

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

我知道我不能设置一个

 string frequency = ""; 

在Controller的顶部,然后只在第一个ActionResult设置。

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

您可以使用使用Session TempData ,但在读取后删除该值。

当你说ActionResult ,我假设你的意思是在控制器中返回Actionresult的Action方法? 例如:

 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)最有可能对您有用,但在没有更多信息的情况下,其他可能实际上是您需要的信息。

在ASP.NET中 ,过去至少有九个用于管理持久用户状态的选项 ,其中许多仍然适用于MVC。


ViewData和ViewBag

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

例如,将freq变量传递给Index方法的View(例如,使用ViewBag.Frequency = freq;然后将其与@Html.ActionLink一起使用。例如:

 @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变量,在javascript中使用未来的AJAX请求var freq = @Html.Raw(Viewbag.Frequency); , 例如。

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

ViewData / ViewBag优点:

  • 它在您的服务器上维护无状态,因此您不必担心工作进程被回收,下一个请求将转到Web场中的其他服务器等。
  • 它可能是“后退按钮certificate”,因为您的“状态”位于已呈现的页面中

缺点:

  • 只有渲染html的有用动作
  • 并非所有数据都应该是后退按钮certificate,一些数据应该不断发展,因此存储为服务器端状态(例如页面命中计数)

TempData的

  • 可用于 :当前用户,在此请求和下一个请求中
  • 默认情况下(在MVC 4中),这是由SessionStateTempDataProvider实现的(参见文档 )
  • 当您的ActionResult重定向到另一个Action时,它实际上是要使用的,这样您就可以知道已存储数据的确切范围和生命周期。

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

  • 它依赖于会话状态,因此仅当您已正确配置会话状态时,才适用于Web场和Web园场景。
  • 根据您的设置,会话状态也可能不会在工作进程回收之间持续存在。
  • 您还必须担心“后退按钮”或F5场景中发生的情况,因为数据可能无法再次使用。

会议

  • 适用于 :当前用户,在当前会话中。 范围还取决于您如何配置会话状态(例如,应用程序域的本地,或Web服务器支持和可用的数据库)

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


高速缓存

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

您可以通过Controller的HttpContext属性访问它。 例如:

 HttpContext.Cache["Frequency"] = freq; 

cookies

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

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


数据库

  • 适用于 :所有用户,或仅限当前用户,您可以选择任意长或短的时间。

数据库是状态持久性的父亲。 您的应用程序代码应被视为易失性,并且能够处理重新启动,Web场方案等。如果要存储数据,请使用数据库。 “数据库”是指任何forms的数据持久性介质,从SQL Server到Redis,Azure文件存储,Azure表存储,Amazon S3等。


其他选择

还有其他选择,但它们通常不常用。 例如,您可以实现自己的缓存( 此处示例 ),或使用…

静态或单例类

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

什么不用

控制器类字段(实例)

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

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

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

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


控制器类字段(静态)

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