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

sha*_*inz 1 javascript c# asp.net-mvc jquery asp.net-mvc-3

我有一个控制器,在其中一个ActionResults中,返回了一个javascript值,我可以通过以下方式访问:

Request.QueryString["frequency"]
Run Code Online (Sandbox Code Playgroud)

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

我知道我不能设置一个

string frequency = "";
Run Code Online (Sandbox Code Playgroud)

在控制器的顶部,然后只在第一个设置ActionResult.

And*_*own 10

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

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

要问自己的关键问题是:

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

您对数据持久性的选择有很多种,每种都有不同的作用,尽管许多在其潜在用途中与其他人重叠(例如SessionTempData).我在下面列出了很多,根据确切的情况,所有这些都可以解决您的问题.前两个(查看持久数据或TempData)最有可能对您有用,但在没有更多信息的情况下,其他可能实际上是您需要的信息.

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


ViewDataViewBag

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

这方面的一个例子是将您的freq变量传递给Index方法的View(例如,通过使用ViewBag.Frequency = freq;,然后使用它@Html.ActionLink.例如:

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

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

    public ActionResult Detail(int frequency) { ...
Run Code Online (Sandbox Code Playgroud)

类似的方法允许您使用隐藏表单字段中的值,或者通过使用var freq = @Html.Raw(Viewbag.Frequency);例如设置javascript变量的javascript来使用未来的AJAX请求.

注意:有一个思想学派(我认为这是一个很好的学校)你不应该使用它们,而是你应该HomeIndexViewModel为每个视图创建一个强类型类(如上所述),以允许你更好地测试您的Controller操作和视图.

ViewData/的优点ViewBag:

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

缺点:

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

TempData的

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

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

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

会议

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

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


高速缓存

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

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

HttpContext.Cache["Frequency"] = freq;
Run Code Online (Sandbox Code Playgroud)

饼干

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

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


数据库

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

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


其他选择

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

静态或单例类

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

什么不用

控制器类字段(实例)

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

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

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

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


控制器类字段(静态)

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