How do you keep the value of global variables betw

2020-03-01 05:42发布

问题:

I am developing an ASP.NET MVC 3 web application using Razor and C#.

I just discovered that I have some problems with global variables, probably because I am relatively new to MVC.

I have a controller with some global variables and action methods. I declared a global variable in order to allow the action methods to manipulate it and reflect the manipulations to all the action methods. I have the following situation:

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);
    }
}

The Print() action method is called with an Html.ActionLink() from the MyView View.

The surprising thing is that the value of _MyGlobalVariable is not kept! So the value of _MyGlobalVariable before the instruction _MyGlobalVariable += "Print" is equal to null.

Am I making some mistake? How can I keep the value of global variables between calls to Views?

Thanks

Francesco

PS: in my specific case the global variable is a Dictionary<K,V> but I guess it does not change the logic.

PPS: I know you can use ViewModels instead of global variables to pass data between action methods but in my case is much less code if I use a Dictionary<K,V> which usually I don't wrap in ViewModels (I use POCOs or Lists<T>)

回答1:

Each request gets a fresh controller instance.
Since your "variable" is an instance field, it doesn't persist.

You can fix that by making it static, or by using application state.

However, don't.
You should never use mutable global state in a web application.

In particular, if you get two request at the same time, your field will get messed up.

Depending on what you're trying to do, you may want to use Session state or cookies.



回答2:

First of all, there are no such thing as global variables in C#. What you're looking for is a static variable, which can be accessed through a class itself. Since a new controller instance is created on each request, the value of your variable is lost.

You will need to declare your variable as such:

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

And access it as such:

MyControllerClass._MyGlobalVariable

Also, this variable will only be accessable from methods of the myController class, as you have it declared private.

In addition to this, you will probably want to lock down the variable whenever using it, as you will end up running into race conditions eventually.

note: I wouldn't suggest doing it this way



回答3:

As everyone said global variables here won't work. Even if they were a good idea then they would not work in a web farm scenario as the value would be only on one machine.

Your Index controller action could look something like this....

    public ActionResult Index()
{

    myModel myStronglyTypedModel = new myModel();

    myStronglyTypedModel.SomeStateIWantToKeep = "Hello";

    return View(myStronglyTypedModel);
}

Then in your print would do this

public ActionResult Print(myModel myStronglyTypedModel)

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

And your view could could start with

@ModelType myModel

and so your view would be strongly typed.

I am a vb guy so someone feel free to correct my c#. I suspect the @ModelType directive in vb is @model in c# but haven't checked.

Cheers



回答4:

You can use TempData Dictionary to save one step calling controller. TempData send your data to just one next session if you want to remain your data to all session you should initialize that TempData in every method controller you want.

    public ActionResult Index()
    {

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

in MyGlobalVariableInitializer, you initialize MyGlobalVariable for the first time.

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


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


回答5:

You should probably use ViewData for this OR use the HttpContext. ViewData will only be valid for your current request so is generally a better alternative than directly using the session object since your data is removed and not available on the next request. Using the session object can suffer from multi request overlap issues.