为什么 ASP.NET TempData 在修改 Web.config 时不起作用?

Why doesn't ASP.NET TempData work when modifying Web.config?

如果需要,我的 Global.asax.cs 文件中有一个函数可以对 Web.config 文件应用一些更改。文件保存为:

config.Save(ConfigurationSaveMode.Modified);

我最近发现 TempData 不适用于我的应用程序:在下一次请求时它似乎是空的。我的 MCVE:

public ActionResult Foo()
{
  TempData["error"] = "testing error passing";
  return RedirectToAction("Bar");
}

public ActionResult Bar()
{
  throw new Exception(TempData["error"] as string);
}

我将其添加到我的 HomeController,访问 /Home/Foo 将重定向到 /Home/Bar。但是,在上面的 config.Save 行处于活动状态时,我得到:

Server Error in '/' Application.
Exception of type 'System.Exception' was thrown.

但是如果我注释掉那一行,我会得到:

Server Error in '/' Application.
test error passing

正如我最初所期待的那样。

(我有几次得到了相反的结果,但通常是在我评论或取消评论该行后的第一个请求中,所以可能 I should blame caching。)

为什么会发生这种情况,我该如何解决?

基于这个问题:

What happens when I edit web.config?

Imagine each ASP.NET application (as defined in IIS) is a program on the desktop. Saving web.config will do something similar to closing the program and reopening it. - Dan Goldstein

IIS 默认行为会在运行时对 web.config 文件应用任何更改时自动重置整个会话状态并回收现有 AppDomain,因此存储在 TempData 数组中的所有值都将丢失,留下取而代之的是空值。

config.Save 行未注释时,行:

throw new Exception(TempData["error"] as string);

将包含来自 TempData["error"]:

的空值
throw new Exception(null);

由于 as operator returns null 如果对象不存在,它会抛出带有空字符串的新 Exception 实例,导致显示默认异常消息而不是自定义异常消息。

如果 config.Save 行被注释,配置更改不会应用到 web.config 文件,因此现有的 AppDomain 仍然是 运行 和 TempData 值是还在原地。

可以通过以下步骤更改默认行为:

  1. 打开 IIS 管理器。
  2. Select 应用程序池 => [您的应用程序池名称] => 高级设置。
  3. 在回收区,找到 Disable Recycling for Configuration Changes (DisallowRotationOnConfigChange) 部分并将其设置为 True

相关问题:How to prevent an ASP.NET application restarting when the web.config is modified?

TempData 将值存储在会话中,您的默认会话存储似乎是 InProc,它将数据存储在服务器内存中,服务器内存主要 运行ning 在应用程序池的 AppDomain 下

默认情况下,当虚拟目录下的文件发生任何变化时,IIS 会检测到使用文件观察器并回收应用程序池,这将取消分配分配给该 Web 应用程序的所有内存。

为避免这种情况,您可以将会话模式更改为数据库或状态服务器。

但最好完全避免更改 web.config,如果您有任何用户定义的配置或需要在 运行 时更改,则必须存储它在其他地方缓存以避免任何性能影响