IIS 部署 ASP.NET 站点排查手册:500.19、CS0016 与静态资源 404

分类:web  |  时间:2026-10-11 11:05:16  |  阅读:49
场景背景

一个 ASP.NET WebForms 站点(.NET 4.5 + SQLite/XML 文件存储)要部署到 Windows Server 2012 R2 的 IIS 上。本地 VS 里跑得好好的,一上传到服务器就各种报错:先是 500.19 配置错误,改完又是 CS0016 编译失败,能打开之后静态资源又 404。

这篇文章把这几类最常见的 IIS 部署问题整理成一份排查手册,每个都附上根因和修复命令,都是我在真实服务器上踩出来的。

IIS 管理控制台

问题一:HTTP 错误 500.19 —— 配置节被锁定

现象:访问站点直接返回 HTTP Error 500.19 - Internal Server Error,错误信息里带 Config Error: This configuration section cannot be used at this path。

根因:IIS 默认在 applicationHost.config 里锁定了很多配置节,web.config 里一旦出现被锁定的节就整站崩。

排查:

powershell
# 找到被锁定的节(错误信息里 Config Section 就是)
# 常见被锁的节:handlers、modules、httpErrors、rewrite


修复(任选其一):

powershell
# 方案A:在 IIS 管理器里解锁(推荐,最小改动)
#   打开 IIS 管理器 → 点服务器节点 → 功能视图双击"配置编辑器"
#   → 节选 system.webServer/xxx → 右侧"解锁节"

# 方案B:命令行解锁(管理员 PowerShell)
%windir%\system32\inetsrv\appcmd.exe unlock config -section:system.webServer/handlers
%windir%\system32\inetsrv\appcmd.exe unlock config -section:system.webServer/rewrite/rules


问题二:CS0016 —— 编译输出目录没有写权限

现象:站点能加载,但一访问 .aspx 就报 CS0016: 未能写入输出文件 ... 拒绝访问。

根因:ASP.NET 需要把动态编译的 DLL 写到 Temporary ASP.NET Files 目录,而 IIS 应用池身份(IIS AppPool\你的池名 或 NETWORK SERVICE)对该目录没有写权限。手工新建过目录、或从别的机器拷过配置时尤其常见。

powershell
# ① 给应用池身份授予编译目录权限(注意是"该应用池"而不是 Everyone)
icacls "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files" `
      /grant "IIS AppPool\wzxt_pool:(OI)(CI)M" /T

# ② 应用池"加载用户配置文件"必须为 True,否则临时目录会解析到错误位置
%windir%\system32\inetsrv\appcmd.exe set apppool "wzxt_pool" ^
      /processModel.loadUserProfile:"True"

# ③ 改完回收应用池生效
%windir%\system32\inetsrv\appcmd.exe recycle apppool "wzxt_pool"


!注意:只授权了根目录、而历史遗留的子目录权限没继承,依然会报错。/T 参数就是用来递归处理所有子目录的。

问题三:静态资源 404 —— MIME 类型缺失

现象:页面出来了,但 CSS、JS、字体文件全是 404,控制台一片红。

根因:IIS 不会自动识别 .woff2、.webp、.json 这类扩展名,需要手工加 MIME 映射。

xml
<!-- web.config 里直接声明,随站点走,最省事 -->
<system.webServer>
  <staticContent>
    <remove fileExtension=".woff2" />
    <mimeMap fileExtension=".woff2" mimeType="font/woff2" />
    <remove fileExtension=".webp" />
    <mimeMap fileExtension=".webp" mimeType="image/webp" />
  </staticContent>
</system.webServer>


问题四:ASP.NET 专属资源被直接下载

现象:浏览器能直接下载到 App_Code/xxx.cs、web.config 的内容,源码暴露。

根因:IIS 默认对 .cs、.config 有 requestFiltering 隐藏规则,但如果站点是"静态文件"模式,或者规则被误删过,就会裸奔。

xml
<system.webServer>
  <security>
    <requestFiltering>
      <hiddenSegments>
        <add segment="App_Code" />
        <add segment="App_Data" />
      </hiddenSegments>
    </requestFiltering>
  </security>
</system.webServer>


实测加完之后,/App_Data/*.xml、/App_Code/*.cs 全部返回 404,而站点自身通过 Server.MapPath 读取不受影响。

服务器机柜

问题五:配了 HTTPS 强转,结果全站打不开

这个是最坑的。为了强制 HTTPS,在 web.config 里加了一条 URL 重写规则:

xml
<!-- ❌ 错误示范:没有 HTTPS 条件判断 -->
<rule name="ForceHTTPS" stopProcessing="true">
  <match url="(.*)" />
  <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
</rule>


如果服务器上没有有效证书、或者规则对 HTTP/HTTPS 都命中,就会触发重定向循环,IIS 变量解析失败后甚至会把字面量 {HTTP_HOST} 输出到地址栏,出现 https://你的域名/https;//%7BHTTP_HOST%7D// 这种畸形 URL。

正确写法必须同时满足两点:加 HTTPS 条件判断 + 确认证书已就绪:

xml
<!-- ✅ 正确:仅当请求不是 HTTPS 时才跳转 -->
<rule name="ForceHTTPS" stopProcessing="true">
  <match url="(.*)" />
  <conditions>
    <add input="{HTTPS}" pattern="^OFF$" />
  </conditions>
  <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
</rule>


部署检查清单

□ 应用池 .NET 版本 = 站点目标框架(4.5 站点别选成"无托管代码")
□ 应用池"加载用户配置文件" = True
□ Temporary ASP.NET Files 对该应用池身份有写权限(含子目录)
□ 被 web.config 引用的配置节已在 applicationHost.config 中解锁
□ 静态资源扩展名(woff2/webp/json)已加 MIME 映射
□ App_Code / App_Data 已在 hiddenSegments 中屏蔽
□ 改 .cs/.ashx 后回收应用池(ashx 不会自动重编译)
□ HTTP 强转前确认证书有效,且规则带 {HTTPS} 条件


小结

IIS 部署的大多数故障都落在三类:权限(编译目录、目录 ACL)、配置锁定(applicationHost.config 锁节)、配置逻辑(重写规则、MIME)。按上面清单逐项过一遍,90% 的"本地好好的、服务器就崩"都能定位到具体那一行。
IISASP.NET部署HTTPS性能