<httpErrors errorMode="Detailed" existingResponse="Replace">
<httpErrors errorMode="Custom" existingResponse="Replace">
- `<httpErrors errorMode="Detailed" existingResponse="Replace">`:**无论本地 / 远程访问,全部返回 IIS 原生详细错误页(堆栈、模块信息)**,并且强制覆盖掉[ASP.NET](https://ASP.NET)自己输出的错误内容。**调试用,严禁生产**Microsoft ...
- `<httpErrors errorMode="Custom" existingResponse="Replace">`:**无论本地 / 远程访问,全部使用你配置的自定义错误页面**,强制覆盖[ASP.NET](https://ASP.NET)抛出的错误内容。**生产环境用来展示友好 404/500 页面**Microsoft ...
>
> `existingResponse="Replace"` 两者是一样的:只要状态码 >=400,**IIS 会直接覆盖掉应用程序([ASP.NET](https://ASP.NET) Framework / [ASP.NET](https://ASP.NET) Core)本身已经生成的错误 html**,无视代码里输出的错误内容,交给 httpErrors 模块接管输出。
> 另外两个可选值:`Auto`(默认)、`PassThrough`(透传,保留应用输出的错误内容)Microsoft ...
## errorMode 三个枚举完整说明
1、`Detailed`
所有客户端(包括外网)都返回 IIS 详细错误页:包含出错模块、管道阶段、物理路径、HRESULT 等底层信息。
>
> ⚠️ 非常危险:外网任何人都能看到服务器物理路径、程序报错堆栈,泄露敏感信息,**仅本地调试临时打开**Microsoft ...
2、`Custom`
**所有客户端(本机 + 外网)一律使用自定义错误页面**,不显示任何详细错误信息。
需要在`<httpErrors>`内部配置`<error statusCode="404" path="/404.html" responseMode="File" />`这类自定义页面规则。
3、`DetailedLocalOnly`(IIS 默认值)
本机访问:详细错误;外网访问:自定义错误页。**开发服务器推荐,兼顾调试和安全**Microsoft ...
## existingResponse="Replace" 重点理解(容易踩坑)
>
> 很多人疑惑:明明[ASP.NET](https://ASP.NET)代码抛异常输出了错误页面,为什么看不到?就是这个属性控制。
- `Replace`:只要 HTTP 状态码 >=400,**IIS httpErrors 模块强制接管,替换掉应用已经输出的响应内容**。
- .NET Framework:会覆盖`customErrors`的错误页
- [ASP.NET](https://ASP.NET) Core:覆盖中间件自己写的错误页
- `PassThrough`:应用程序输出的错误内容原样返回,IIS 不替换。如果你想让 Core 中间件的错误页面生效,要改成`PassThrough`。
- `Auto`:默认行为,只有 IIS 模块主动设置 status 时才接管;[ASP.NET](https://ASP.NET)代码抛出的错误一般透传。
## 两套配置适用场景对比
### 场景 A:调试排错(临时)
```
<httpErrors errorMode="Detailed" existingResponse="Replace">
```
✅ 远程也能看到完整 IIS 错误详情(比如 413 上传过大、请求过滤拦截)
❌ 生产环境绝对不能开,信息泄露风险极大
### 场景 B:生产,统一自定义友好错误页
```
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" subStatusCode="-1"/>
<error statusCode="404" path="/err/404.html" responseMode="File"/>
</httpErrors>
```
✅ 所有访问者看到统一的静态错误页面,隐藏服务器底层信息
>
> 注意:.NET Core 部署在 IIS 时,如果用 Core 中间件写错误页面,**不能用 Replace,要用 PassThrough**,否则 Core 写的错误内容会被 IIS 直接吞掉。
## 和你之前 web.config 的搭配关系
- `<system.web><customErrors mode="Off"></customErrors>`:**[ASP.NET](https://ASP.NET) Framework 托管层错误**,只管控.NET 代码抛出异常;
- `<system.webServer><httpErrors>`:**IIS 内核层错误**,管控 IIS 模块拦截的错误(413、403、静态文件 404 等)。
两者是两套独立错误处理,很多时候需要一起配合。
### 快速给你推荐两套完整可用模板
#### 1、开发调试(WebForm .NET Framework)
```
<system.webServer>
<httpErrors errorMode="DetailedLocalOnly" existingResponse="Auto" />
</system.webServer>
```
#### 2、生产环境(WebForm .NET Framework,自定义错误页)
```
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" path="/404.html" responseMode="File" />
<remove statusCode="500" subStatusCode="-1" />
<error statusCode="500" path="/500.html" responseMode="File" />
</httpErrors>
</system.webServer>
```