如何在MVC3中的不同Action方法调用之间保留全局变量的值?

时间:2011-05-09 15:51:21

标签: c# asp.net-mvc-3 global-variables

我正在使用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);
    }
}

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

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

我犯了一些错误吗?如何在对Views的调用之间保留全局变量的值?

由于

弗朗西斯

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

PPS:我知道你可以使用ViewModel而不是全局变量来在动作方法之间传递数据,但在我的情况下,如果我使用Dictionary<K,V>通常我不会在ViewModels中包装,那么代码要少得多(我使用) POCOs Lists<T>

5 个答案:

答案 0 :(得分:31)

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

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

然而, 您永远不应该在Web应用程序中使用可变全局状态。

特别是,如果您同时收到两个请求,您的字段将会搞砸。

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

答案 1 :(得分:4)

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

您需要声明您的变量:

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

并按原样访问:

MyControllerClass._MyGlobalVariable

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

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

注意:我不建议这样做

答案 2 :(得分:2)

正如大家所说,这里的全局变量不起作用。即使它们是个好主意,它们也不会在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但是没有检查过。

干杯

答案 3 :(得分:2)

您可以使用TempData Dictionary保存一步调用控制器。如果要将数据保留到所有会话中,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");
    }

答案 4 :(得分:1)

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