在 ASP.NET MVC5 上设置值后,静态 属性 在每个请求中始终为 null
Static property always null in every request after set value on ASP.NET MVC5
我有一个 static class 和 static 属性
public static class Test
{
public static string Tests { get; set; }
}
现在的问题是,我在控制器中有一个动作
public ActionResult SomeActionInController(){
`` ``
// this place always execute in every request
if (null == Test.Tests)
Test.Tests = "some value";
`` ``
}
但我会在每个请求中得到 null,而不是本地调试,仅在服务器上。
我看到很多人说:静态 属性 值将保留在整个应用程序域中,但为什么现在会发生这种情况?有什么办法可以解决吗?谢谢。
我的服务器使用 IIS 8.5 和 Windows Server 2012 R2
更新1
静态class.
中没有静态构造函数
如果我向 Action 发送请求,每次都会发生 null,因为我可以看到它使用 log4net.
我已经禁用了Idle time out和free time out,都设置为0。所以不存在回收问题。
这是我的 Global.asax:
public class MvcApplication : System.Web.HttpApplication
{
private readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(MvcApplication));
protected void Application_Start()
{
Elmah.Mvc.Bootstrap.Initialize();
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
// Setting log4net
log4net.Config.XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo(Server.MapPath("~/log4net.config")));
// Only keep Razor
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new RazorViewEngine());
System.Threading.Tasks.Task.Factory.StartNew(new Action(() =>
{
try
{
System.Threading.Thread.Sleep(1000 * 100 * 1);
// Send a fake request for warm up the website, when after it recycle
WebClient webClient = new WebClient();
using (Stream stream = webClient.OpenRead(ConfigurationManager.AppSettings["InitialPath"]))
{
if (stream.CanRead)
{
log.Debug("Success warm up when recycle");
}
else
{
log.Debug("warm up failed");
}
}
}
catch (WebException ex)
{
log.Debug(ex);
}
catch (Exception ex)
{
log.Error(ex);
}
}));
}
/// <summary>
/// Setting Page Language
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Application_AcquireRequestState(object sender, EventArgs e)
{
if (HttpContext.Current != null && HttpContext.Current.Session != null)
{
if (AdminLanguage == 1)
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("xx-xx");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("xx-xx");
}
else
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("xx-xx");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("xx-xx");
}
}
}
/// <summary>
/// Cache setting
/// </summary>
/// <param name="context"></param>
/// <param name="arg"></param>
/// <returns></returns>
public override string GetVaryByCustomString(HttpContext context, string arg)
{
// cache from DevTrends.MvcDonutCaching
if (arg == "NavStatic")
{
return "NavStatic=" + HttpContext.Current.Session.SessionID;
}
return base.GetVaryByCustomString(context, arg);
}
}
更新 2
我每次都会设置,因为我用的就是这段代码,所以不用担心。
if (string.IsNullOrEmpty(Test.Tests))
{
log.Debug("Test: null, this time it will be setting");
Test.Tests = "Test";
}
else
{
log.Debug("Test: " + Test.Tests);
}
而在服务器上,log4net会在每次请求(访问动作)时输出它:
Test: null, this time it will be setting
Test: null, this time it will be setting
Test: null, this time it will be setting
更新3
为了一些朋友的建议我把一些代码放在Application_Start()
Test.Tests = "Test";
所以现在,每次请求它都会成功获取值。
但是我在行动中将我的代码更改为:
if (string.IsNullOrEmpty(Test.Tests))
{
log.Debug("Test: null, this time it will be setting");
Test.Tests = "Test";
}
else
{
log.Debug("Test: " + Test.Tests);
Test.Tests = "Test3";
log.Debug("Now the Test new Value = " + Test.Tests);
}
现在 log4net 的每个请求都会像这样输出:
Test: Test
Now the Test new Value = Test3
Test: Test
Now the Test new Value = Test3
Test: Test
Now the Test new Value = Test3
但这不是我想要的。我希望静态 属性 可以在整个应用程序域中读取和修改,而不仅仅是 1 次。
听起来你想要在 ASP.NET MVC 中使用一个全局变量。幸好你的问题已经解决了with this Stack Overflow question.
静力学并不神奇。如果您不设置它们,它们将没有任何价值。
在您的控制器操作中,您正在检查它是否已设置(提示:如果您尚未设置,则未设置):
if (null == Test.Tests)
{
Test.Tests = "some value";
}
那你要在哪里设置Test.Tests
?如果您希望为每个控制器操作设置它,您需要确保在该控制器操作 运行 时设置它。 global.asax.cs:
的 Application_Start
方法是个不错的地方
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
Tests.Test = "This is set";
}
}
public static class Tests
{
public static string Test { get; set; }
}
每次请求都会实例化控制器; Application_Start
方法在每次应用程序池回收时调用一次(或每次应用程序实例化时调用一次)。
您的 Tests.Test
为空的原因是您从未设置它的值。
与George Stocker and Dave Becker讨论后,不断调试。最后找到问题的根源是:因为我将log4net日志文件创建到网站“Bin”文件夹。然后当每个请求进来时,log4net 写入日志,IIS 检测到有一些文件被更改,然后 Application_End() 将执行。都不见了。
非常感谢这两位朋友。
如果您有同样的问题,请不要每次都将任何文件放入或创建到“Bin”文件夹,或尝试写入它。除非你想要应用程序 destroyed 你可以这样做:-)
我有一个 static class 和 static 属性
public static class Test
{
public static string Tests { get; set; }
}
现在的问题是,我在控制器中有一个动作
public ActionResult SomeActionInController(){
`` ``
// this place always execute in every request
if (null == Test.Tests)
Test.Tests = "some value";
`` ``
}
但我会在每个请求中得到 null,而不是本地调试,仅在服务器上。
我看到很多人说:静态 属性 值将保留在整个应用程序域中,但为什么现在会发生这种情况?有什么办法可以解决吗?谢谢。
我的服务器使用 IIS 8.5 和 Windows Server 2012 R2
更新1
静态class.
中没有静态构造函数如果我向 Action 发送请求,每次都会发生 null,因为我可以看到它使用 log4net.
我已经禁用了Idle time out和free time out,都设置为0。所以不存在回收问题。
这是我的 Global.asax:
public class MvcApplication : System.Web.HttpApplication
{
private readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(MvcApplication));
protected void Application_Start()
{
Elmah.Mvc.Bootstrap.Initialize();
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
// Setting log4net
log4net.Config.XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo(Server.MapPath("~/log4net.config")));
// Only keep Razor
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new RazorViewEngine());
System.Threading.Tasks.Task.Factory.StartNew(new Action(() =>
{
try
{
System.Threading.Thread.Sleep(1000 * 100 * 1);
// Send a fake request for warm up the website, when after it recycle
WebClient webClient = new WebClient();
using (Stream stream = webClient.OpenRead(ConfigurationManager.AppSettings["InitialPath"]))
{
if (stream.CanRead)
{
log.Debug("Success warm up when recycle");
}
else
{
log.Debug("warm up failed");
}
}
}
catch (WebException ex)
{
log.Debug(ex);
}
catch (Exception ex)
{
log.Error(ex);
}
}));
}
/// <summary>
/// Setting Page Language
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Application_AcquireRequestState(object sender, EventArgs e)
{
if (HttpContext.Current != null && HttpContext.Current.Session != null)
{
if (AdminLanguage == 1)
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("xx-xx");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("xx-xx");
}
else
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("xx-xx");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("xx-xx");
}
}
}
/// <summary>
/// Cache setting
/// </summary>
/// <param name="context"></param>
/// <param name="arg"></param>
/// <returns></returns>
public override string GetVaryByCustomString(HttpContext context, string arg)
{
// cache from DevTrends.MvcDonutCaching
if (arg == "NavStatic")
{
return "NavStatic=" + HttpContext.Current.Session.SessionID;
}
return base.GetVaryByCustomString(context, arg);
}
}
更新 2
我每次都会设置,因为我用的就是这段代码,所以不用担心。
if (string.IsNullOrEmpty(Test.Tests))
{
log.Debug("Test: null, this time it will be setting");
Test.Tests = "Test";
}
else
{
log.Debug("Test: " + Test.Tests);
}
而在服务器上,log4net会在每次请求(访问动作)时输出它:
Test: null, this time it will be setting
Test: null, this time it will be setting
Test: null, this time it will be setting
更新3
为了一些朋友的建议我把一些代码放在Application_Start()
Test.Tests = "Test";
所以现在,每次请求它都会成功获取值。 但是我在行动中将我的代码更改为:
if (string.IsNullOrEmpty(Test.Tests))
{
log.Debug("Test: null, this time it will be setting");
Test.Tests = "Test";
}
else
{
log.Debug("Test: " + Test.Tests);
Test.Tests = "Test3";
log.Debug("Now the Test new Value = " + Test.Tests);
}
现在 log4net 的每个请求都会像这样输出:
Test: Test
Now the Test new Value = Test3
Test: Test
Now the Test new Value = Test3
Test: Test
Now the Test new Value = Test3
但这不是我想要的。我希望静态 属性 可以在整个应用程序域中读取和修改,而不仅仅是 1 次。
听起来你想要在 ASP.NET MVC 中使用一个全局变量。幸好你的问题已经解决了with this Stack Overflow question.
静力学并不神奇。如果您不设置它们,它们将没有任何价值。
在您的控制器操作中,您正在检查它是否已设置(提示:如果您尚未设置,则未设置):
if (null == Test.Tests)
{
Test.Tests = "some value";
}
那你要在哪里设置Test.Tests
?如果您希望为每个控制器操作设置它,您需要确保在该控制器操作 运行 时设置它。 global.asax.cs:
Application_Start
方法是个不错的地方
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
Tests.Test = "This is set";
}
}
public static class Tests
{
public static string Test { get; set; }
}
每次请求都会实例化控制器; Application_Start
方法在每次应用程序池回收时调用一次(或每次应用程序实例化时调用一次)。
您的 Tests.Test
为空的原因是您从未设置它的值。
与George Stocker and Dave Becker讨论后,不断调试。最后找到问题的根源是:因为我将log4net日志文件创建到网站“Bin”文件夹。然后当每个请求进来时,log4net 写入日志,IIS 检测到有一些文件被更改,然后 Application_End() 将执行。都不见了。
非常感谢这两位朋友。
如果您有同样的问题,请不要每次都将任何文件放入或创建到“Bin”文件夹,或尝试写入它。除非你想要应用程序 destroyed 你可以这样做:-)