我正在使用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>
)
答案 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仅对您当前的请求有效,因此通常是比直接使用会话对象更好的选择,因为您的数据已被删除且在下一个请求中不可用。使用会话对象可能会遇到多个请求重叠问题。