You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何以编程方式访问ASP.NET/IIS默认错误描述及查询存储位置

关于IIS上ASP.NET默认HTTP错误描述的存储与编程访问

我来给你详细拆解这个问题,分几个部分说清楚:

一、默认错误描述存在哪儿?

首先得明确:这些ASP.NET专属的HTTP错误描述,不是存在IIS的某个配置文件或磁盘文件夹里,而是嵌入在ASP.NET框架的程序集资源当中,属于框架的一部分。

分两种框架情况:

  • 传统ASP.NET(.NET Framework):这些文本都在System.Web程序集的内部资源类里,具体是System.Web.SR(String Resources)这个内部类,对应的资源是编译进程序集的二进制资源,没有单独的磁盘文件。
  • ASP.NET Core:默认错误页的文本则在Microsoft.AspNetCore.Diagnostics这个NuGet包的程序集资源里,比如和StatusCodePagesMiddleware相关的内部资源类,同样是嵌入在程序集里的。

补充一下:如果是IIS自身处理的静态错误(比如非ASP.NET请求的404),才会存在系统目录C:\Windows\System32\inetsrv\errors下的html文件,但你问的是ASP.NET的HTTP错误,重点还是在框架资源里。

二、能不能通过代码访问?当然可以!

不管是传统ASP.NET还是ASP.NET Core,都能通过反射来获取这些内部资源里的文本,因为对应的资源类是内部的,没法直接引用,所以得用反射。

1. 传统ASP.NET(.NET Framework)的实现

比如你要获取404的默认描述,可以写这样的代码:

using System;
using System.Reflection;
using System.Web;

public static string GetAspNetHttpErrorDescription(int statusCode)
{
    // 拿到System.Web程序集
    Assembly systemWebAssembly = typeof(HttpException).Assembly;
    // 获取内部的SR资源类
    Type srType = systemWebAssembly.GetType("System.Web.SR");
    if (srType == null)
        return null;

    // 映射状态码到对应的资源属性名
    string resourceName = statusCode switch
    {
        404 => "HttpNotFoundDescription",
        403 => "HttpForbiddenDescription",
        500 => "HttpInternalServerErrorDescription",
        // 其他状态码可以自己补充对应的属性名
        _ => null
    };

    if (resourceName == null)
        return null;

    // 获取静态属性的值
    PropertyInfo prop = srType.GetProperty(resourceName, BindingFlags.Static | BindingFlags.NonPublic);
    return prop?.GetValue(null) as string;
}

这里的HttpNotFoundDescription就是对应你提到的那段404描述文本,其他状态码对应的属性名也都是类似的命名规则,比如403是HttpForbiddenDescription

另外,如果你已经捕获了HttpException,其实它的Message属性里也包含了这个描述(可能会附加URL等信息),但如果要纯描述的话,上面的反射方法更精准。

2. ASP.NET Core的实现

ASP.NET Core的资源类也是内部的,同样用反射来获取,示例代码如下:

using System;
using System.Reflection;
using Microsoft.AspNetCore.Diagnostics;

public static string GetAspNetCoreHttpErrorDescription(int statusCode)
{
    Assembly diagnosticsAssembly = typeof(StatusCodePagesMiddleware).Assembly;
    // 获取内部的资源类,不同版本可能命名略有差异
    Type resourcesType = diagnosticsAssembly.GetType("Microsoft.AspNetCore.Diagnostics.Resources.StatusCodePagesResources");
    if (resourcesType == null)
        return null;

    // 映射状态码到资源键名
    string resourceName = statusCode switch
    {
        404 => "NotFound_Description",
        403 => "Forbidden_Description",
        500 => "ServerError_Description",
        // 按需添加其他状态码
        _ => null
    };

    if (resourceName == null)
        return null;

    // 调用资源类的GetString方法获取文本
    MethodInfo getStringMethod = resourcesType.GetMethod("GetString", BindingFlags.Static | BindingFlags.NonPublic, new[] { typeof(string) });
    return getStringMethod?.Invoke(null, new object[] { resourceName }) as string;
}

注意:不同版本的ASP.NET Core,资源类的命名或者方法可能有小变动,需要根据你使用的框架版本调整。

三、额外小提示

  • 如果只是想在自定义错误页里用这些描述,传统ASP.NET里直接用HttpException.Message也能拿到带描述的信息;ASP.NET Core里可以直接用StatusCodePages中间件的默认文本,但如果需要纯描述内容,反射的方式更靠谱。
  • 这些资源文本是和框架版本绑定的,不同.NET Framework或.NET Core版本的文本可能有细微差别,代码要适配对应的版本哦。

内容的提问来源于stack exchange,提问作者Arkiliknam

火山引擎 最新活动