1

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

Request.QueryString["frequency"]

但我需要在另一个ActionResult. 我怎样才能做到这一点?

我知道我无法设置

string frequency = "";

在控制器的顶部,然后设置在 1st 中ActionResult

4

2 回答 2

10

当您说 时ActionResult,我假设您的意思是控制器中返回Actionresults 的 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)。我在下面列出了其中的许多,根据具体情况,所有这些都可以解决您的问题。前两个(View-persisted data 或 TempData)最有可能对您有用,但在没有更多信息的情况下,其他信息实际上可能是您需要的。

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


ViewDataViewBag

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

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

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

然后,您的 Detail 操作变为:

    public ActionResult Detail(int frequency) { ...

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

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

ViewData/的优点ViewBag

  • 它在您的服务器上保持无状态,因此您不必担心工作进程被回收,下一个请求会发送到您网络场中的不同服务器等。
  • 它可能是“后退按钮证明”,因为您的“状态”位于已呈现的页面中

缺点:

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

临时数据

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

从表面上看,这旨在完全按照您的意愿行事,但有一些注意事项。

  • 它依赖于会话状态,因此只有在您正确配置了会话状态时才适用于网络农场和网络花园场景。
  • 根据您的设置,会话状态也可能不会在工作进程回收之间持续存在。
  • 您还必须担心在“后退按钮”或 F5 场景中会发生什么,因为数据可能第二次不可用。

会议

  • 适用于:当前用户,在他们的当前会话中。范围还取决于您如何配置会话状态(例如,位于应用程序域的本地,或数据库支持并在整个网络场中可用)

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


缓存

  • 适用于:所有用户,但仅在当前应用程序域内(所以要注意工作进程回收、网络农场、网络花园等)

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

HttpContext.Cache["Frequency"] = freq;

饼干

  • 适用于:当前用户,但仅来自他们用于原始请求的浏览器

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


数据库

  • 适用于:所有用户,或仅当前用户,无论您喜欢多长时间,您都可以选择。

数据库是状态持久性之父。您的应用程序代码应该被视为易变的,并且能够处理重启、网络农场场景等。如果您想存储数据,请使用数据库。“数据库”是指任何形式的数据持久性介质,从 SQL Server 到 Redis、Azure 文件存储、Azure 表存储、Amazon S3 等。


其他选项

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

静态或单例类

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

什么不能用

控制器类字段(实例)

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

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

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

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


控制器类字段(静态)

  • 适用于:所有用户,对该服务器上该工作进程的所有请求
  • 不是一个好主意 - 静态字段将可供所有线程上的所有用户使用,因此您必须担心线程安全。如果您想在所有用户之间共享数据,可以使用开箱即用的更好的状态存储,例如Cache
于 2013-05-10T14:49:58.743 回答
3

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

您可以使用TempDatawhich useSession但在阅读后删除该值。

于 2013-05-10T12:31:03.680 回答