如何在 MVC3 中的不同操作方法调用之间保持全局变量的值

本文关键字:之间 调用 全局变量 操作方法 MVC3 | 更新日期: 2023-09-27 17:56:07

我正在使用Razor和C#开发一个 ASP.NET MVC 3 Web应用程序。

我刚刚发现我在全局变量方面有一些问题,可能是因为我对 MVC 比较陌生。

我有一个带有一些全局变量和操作方法的控制器。我声明了一个全局变量,以便允许操作方法操作它并将操作反映到所有操作方法。我有以下情况:

public class myController : Controller
{
    private string _MyGlobalVariable;
    public ActionResult Index()
    {
       _MyGlobalVariable = "Hello";
       //other code
       return View("MyView");
    }
    public ActionResult Print()
    {
       _MyGlobalVariable += "Print";
       return View("PrintView", _MyGlobalVariable);
    }
}
Print()

操作方法是使用 MyView 视图中的 Html.ActionLink() 调用的。

令人惊讶的是,_MyGlobalVariable的价值并没有保留!因此,指令_MyGlobalVariable += "Print"之前的_MyGlobalVariable值等于 null。

我是不是搞错了什么?如何在调用视图之间保留全局变量的值?

谢谢

弗朗切斯科

PS:在我的特定情况下,全局变量是一个Dictionary<K,V>但我想它不会改变逻辑。

PPS:我知道您可以使用 ViewModels 而不是全局变量在操作方法之间传递数据,但就我而言,如果我使用通常不包装在 ViewModels 中的Dictionary<K,V>,代码就会少得多(我使用 POCOLists<T>

如何在 MVC3 中的不同操作方法调用之间保持全局变量的值

每个请求都会获得一个新的控制器实例。
由于您的"变量"是一个实例字段,因此它不会持久化。

可以通过将其设为static 或使用应用程序状态来解决此问题。

但是,不要
切勿在 Web 应用程序中使用可变全局状态。

特别是,如果您同时收到两个请求,您的字段将变得混乱。

根据您要执行的操作,您可能需要使用会话状态或 Cookie。

首先,C# 中没有全局变量这样的东西。你要找的是一个静态变量,可以通过类本身访问它。由于在每个请求上都会创建一个新的控制器实例,因此变量的值将丢失。

您需要这样声明变量:

private static string _MyGlobalVariable = "insert default value here";

并按以下方式访问它:

MyControllerClass._MyGlobalVariable

此外,此变量只能从 myController 类的方法访问,因为您已将其声明为 private。

除此之外,您可能希望在使用变量时锁定变量,因为最终会遇到竞争条件。

注意:我不建议这样做

您可以使用 TempData 字典来保存一步调用控制器。TempData 将数据发送到下一个会话 如果要将数据保留到所有会话,则应在所需的每个方法控制器中初始化该 TempData。

    public ActionResult Index()
    {
        if (TempData["MyGlobalVariable"] == null)
            return RedirectToAction("MyGlobalVariableInitializer");
        else
            TempData["MyGlobalVariable"] =(string)TempData["MyGlobalVariable"]+" world";
     .
     .
     .
     }

在 MyGlobalVariableInitializer 中,首次初始化 MyGlobalVariable。

    public ActionResult CompanySelection()
    {
        return View();
    }

    public ActionResult MyGlobalVariableInitializer()
    {
        TempData["MyGlobalVariable"] = "Hello";
        return RedirectToAction("Index");
    }

正如大家所说,这里的全局变量是行不通的。 即使它们是一个好主意,它们也不会在 Web 场方案中工作,因为值仅在一台计算机上。

索引控制器操作可能如下所示。

    public ActionResult Index()
{
    myModel myStronglyTypedModel = new myModel();
    myStronglyTypedModel.SomeStateIWantToKeep = "Hello";
    return View(myStronglyTypedModel);
}

然后在你的打印中会这样做

public ActionResult Print(myModel myStronglyTypedModel)
{
    myStronglyTypedModel.SomeStateIWantToKeep += "Print";
    return View("PrintView");
}

你的观点可以从

@ModelType myModel

因此,您的视图将被强类型化。

我是一个 vb 人,所以有人可以随时纠正我的 c#。 我怀疑 vb 中的 @ModelType 指令在 c# 中@model但尚未检查。

干杯

您可能应该为此使用 ViewData 或使用 HttpContext。ViewData 仅对您当前的请求有效,因此通常比直接使用会话对象更好,因为您的数据将被删除,并且在下一个请求中不可用。使用会话对象可能会遇到多请求重叠问题。