ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

ASP.NET Core 共享错误页(ErrorPage)的生成与渲染原理:从 cshtml 到 Designer.cs 的完整链路

ASP.NET Core 共享错误页(ErrorPage)的生成与渲染原理:从 cshtml 到 Designer.cs 的完整链路 ASP.NET Core 共享错误页ErrorPage的生成与渲染原理从 cshtml 到 Designer.cs 的完整链路【免费下载链接】aspnetcoreASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.项目地址: https://gitcode.com/GitHub_Trending/as/aspnetcoreASP.NET Core 在应用启动失败时呈现的Internal Server Error页面来自 src/Shared/ErrorPage 这一被多个项目共享的 Razor 视图。本文以 src/Shared/ErrorPage/README.md 为主线完整讲解该共享错误页的文件组织、ErrorPage.Designer.cs的自动生成机制、视图与模型的数据绑定以及它在 Hosting 层启动失败兜底与 Diagnostics 中间件开发期异常页两条消费链路中的实际用途并给出修改视图后重新生成代码的完整操作流程。读完本文你将掌握如何安全修改共享错误页的 cshtml 并借助 RazorPageGenerator 重新生成 Designer 代码、错误页模型与视图之间如何传递异常详情与运行时信息以及该共享视图在 ASP.NET Core 源码树中的真实消费方式。共享错误页的文件结构与定位src/Shared/ErrorPage不是某个独立程序集而是一个被多个项目共享的视图源码目录。README 开篇即点明多个项目共享此文件夹ErrorPage.Designer.cs与ErrorPageModel.cs负责渲染这个共享视图。目录内共包含 6 个文件Views/ErrorPage.cshtml— 视图模板唯一的手写源文件正文以using Microsoft.AspNetCore.Hosting.Views声明模型命名空间Views/ErrorPage.css、Views/ErrorPage.js— 视图内联引入的样式与脚本通过% include: ErrorPage.css %这类 RazorPageGenerator 预处理指令嵌入ErrorPage.cshtml经生成器编译产出的ErrorPage.Designer.cs自动生成带// auto-generated/标记共约 1000 行ErrorPageModel.cs— 页面数据模型ErrorPageModelBuilder.cs— 模型的构建工厂GeneratePage.ps1— 一键重新生成的 PowerShell 脚本。从源码结构看该共享视图被链接compile include进多个程序集最典型的两个消费方是src/Hosting/Hosting 中的Microsoft.AspNetCore.Hosting程序集——用于应用启动失败时兜底渲染错误页src/Middleware/Diagnostics 中的DeveloperExceptionPage中间件——用于开发期请求处理异常时渲染开发者异常页。这也解释了为什么视图的命名空间是Microsoft.AspNetCore.Hosting.Views而非某个中间件专属命名空间它天然服务于整个 Hosting 层。核心机制cshtml → Designer.cs 的代码生成闭环生成器工具RazorPageGeneratorREADME 明确指出ErrorPage.Designer.cs由 RazorPageGenerator 工具从Views/ErrorPage.cshtml生成。在当前的仓库结构中该工具的源码位于 src/Middleware/tools/RazorPageGenerator/RazorPageGenerator.csproj其 csproj 描述为Builds Razor pages for views in a project. For internal use only.仅供内部使用程序集名称为dotnet-razorpagegenerator是一个可执行工具并引用Microsoft.AspNetCore.Razor.Language完成 Razor 语法解析与代码生成。一键重生成脚本GeneratePage.ps1README 给出的核心操作只有两个步骤编辑 cshtml → 运行GeneratePage.ps1。脚本 GeneratePage.ps1 的实现揭示了完整流程.\GeneratePage.ps1脚本逻辑如下由$PSScriptRoot向上回溯三级得到仓库根目录$RepoRoot..\..\..即aspnetcore仓库根定位生成器可执行文件artifacts\bin\RazorPageGenerator\Debug\net11.0\dotnet-razorpagegenerator.exe注意其目标框架为net11.0需先按仓库构建流程产出该工具若工具不存在则抛出异常Unable to find razor page generator tool at $ToolPath以Microsoft.AspNetCore.Hosting.Views作为目标命名空间对$PSScriptRoot即src/Shared/ErrorPage下的Views/目录执行生成 $ToolPath Microsoft.AspNetCore.Hosting.Views $PSScriptRoot Views/生成器会在Views/下产出ErrorPage.Designer.cs脚本随后将其移动到src/Shared/ErrorPage/ErrorPage.Designer.cs完成替换。因此修改错误页的正确姿势是只改Views/ErrorPage.cshtml绝不手改ErrorPage.Designer.cs——后者是构建产物任何手工改动都会在下次运行时被覆盖。生成结果ErrorPage.Designer.cs生成出的 ErrorPage.Designer.cs 首行带有// auto-generated/与#pragma warning disable 1591类声明为internal sealed class ErrorPage : Microsoft.Extensions.RazorViews.BaseView其中BaseView是Microsoft.Extensions.RazorViews命名空间下的基础视图类提供ExecuteAsync()与WriteLiteral(...)等渲染基元cshtml 中每个文本片段被编译为对WriteLiteral的调用Razor 表达式与functions块则被编译为 C# 代码如构造函数public ErrorPage(ErrorPageModel model)文件内通过#line 1 Views/ErrorPage.cshtml等指令保留源映射使堆栈信息能指回 cshtml 原始行号便于调试。从源码结构看这正是手写 Razor 生成 C#双文件模式的经典应用仓库内其他视图如 src/Middleware/Diagnostics/src/DeveloperExceptionPage/Views/ErrorPage.cshtml 与对应的ErrorPage.Designer.cs也遵循同样的生成约定。视图与模型页面渲染的数据契约模型定义ErrorPageModelErrorPageModel.cs 定义了错误页的完整数据契约internal sealed class位于Microsoft.AspNetCore.Hosting.Views命名空间属性类型含义ErrorDetailsIEnumerableExceptionDetails异常链中每个异常的详细信息类型、消息、堆栈帧ExceptionDetails来自Microsoft.Extensions.StackTrace.Sources由堆栈跟踪源提供ShowRuntimeDetailsbool是否展示运行时详情即是否启用详细错误RuntimeDisplayNamestring运行时展示名如.NET 9.0.xRuntimeArchitecturestring进程架构如X64ClrVersionstringCLR 版本CurrentAssemblyVesionstring当前程序集的InformationalVersion注意模型属性名保留了这个拼写OperatingSystemDescriptionstring操作系统描述模型通过构造函数一次性注入全部数据只读属性暴露给视图避免视图直接接触异常对象以外的副作用。模型构建ErrorPageModelBuilderErrorPageModelBuilder.cs 是静态工厂其CreateErrorPageModel(IFileProvider, ILogger?, bool showDetailedErrors, Exception)完成了三个关键动作版本信息采集以System.ComponentModel.DefaultValueAttribute程序集作为系统运行库锚点取AssemblyName.Version作为clrVersion再取当前程序集即承载ErrorPage的程序集的AssemblyInformationalVersionAttribute.InformationalVersion作为currentAssemblyVesion异常详情展开当showDetailedErrors为 true 时使用ExceptionDetailsProvider(contentRootFileProvider, logger, sourceCodeLineCount: 6)展开异常链每个异常抓取6 行源码上下文为 false 时传入空数组Array.EmptyExceptionDetails()运行时环境描述通过RuntimeInformation.FrameworkDescription、RuntimeInformation.ProcessArchitecture、RuntimeInformation.OSDescription组装运行环境信息。该工厂在 Hosting 层由 ErrorPageBuilder.cs 调用ErrorPageModelBuilder.CreateErrorPageModel(...)随后构造new ErrorPage(model)并返回渲染委托。视图渲染ErrorPage.cshtmlViews/ErrorPage.cshtml 通过functions块声明带模型参数的构造函数并将模型暴露为Model属性顶部错误摘要遍历Model.ErrorDetails输出异常类型名与消息消息经HtmlEncodeAndReplaceLineBreaks处理以安全换行并定位首个堆栈帧显示位置文件、行号ReflectionTypeLoadException特判若异常为ReflectionTypeLoadException额外以列表渲染LoaderExceptions中每个加载器异常的消息——这对启动阶段程序集加载失败的场景非常实用堆栈帧列表为每个异常渲染堆栈帧li classframe帧内含函数名、源文件名若帧携带上下文代码frame.ContextCode则渲染可展开/折叠的源码块前文PreContextCode、高亮行ContextCode、后文PostContextCode三段ol并通过按钮data-frameId关联展开行为原始异常详情每个异常附带一个Show raw exception details按钮点击后展示errorDetail.Error.ToString()的完整pre文本便于排查堆栈上下文之外的原始信息运行时页脚当Model.ShowRuntimeDetails为 true 时页脚输出RuntimeDisplayName RuntimeArchitecture、CLR 版本、Microsoft.AspNetCore.Hosting version即CurrentAssemblyVesion以及OperatingSystemDescription并附带微软Need help?帮助链接内联资源样式与脚本通过% include: ErrorPage.css %、% include: ErrorPage.js %预处理指令内联进单个 HTML最终页面无需额外静态文件请求离线可用。注意该共享视图没有展示 Query、Headers、Cookie、路由值等请求上下文这些属于 Diagnostics 中间件专属版页面的能力它聚焦于启动失败/未处理异常这一纯粹场景。两条消费链路启动兜底与开发期异常页链路一Hosting 启动失败兜底当应用启动阶段抛出异常例如 DI 解析失败、Startup配置异常WebHost 与 GenericWebHostService 会经由ErrorPageBuilder.BuildErrorPageApplication(...)见 ErrorPageBuilder.cs构建兜底请求管道若异常是TargetInvocationException先解包取其InnerException调用ErrorPageModelBuilder.CreateErrorPageModel(...)构造模型返回的RequestDelegate固定输出HTTP 500、Cache-Control: no-cache,no-store与Pragma: no-cache禁止缓存敏感堆栈信息、Content-Type: text/html; charsetutf-8随后执行errorPage.ExecuteAsync(context)。是否展示详细堆栈由showDetailedErrors参数决定——生产环境关闭详细错误时ErrorDetails为空数组页面仅显示An error occurred while starting the application.通用文案避免泄露内部实现细节。链路二DeveloperExceptionPage 开发期异常页在 DeveloperExceptionPageMiddlewareImpl.cs约 L373-L386中中间件构造了自己专属版的ErrorPageModel包含Options、ErrorDetails、Query、Cookies、Headers、RouteValues、Endpoint、Title等字段甚至对BadHttpRequestException依据状态码短语定制页面标题并new ErrorPage(model)后调用errorPage.ExecuteAsync(context)。该版视图位于 src/Middleware/Diagnostics/src/DeveloperExceptionPage/Views其配套的ErrorPageModel.cs、ErrorPage.Designer.cs与共享目录下的文件同源同构均由同一生成器产出——这正好印证了 README多个项目共享此文件夹指共享视图的源码与生成流程的表述。两条链路的共同点是手写 cshtml → RazorPageGenerator 生成 Designer.cs → 构造模型 →ErrorPage(model).ExecuteAsync(context)区别在于模型数据的丰富度共享版仅异常 运行时信息中间件版额外携带请求上下文。修改错误页的完整操作流程基于 README 与脚本源码修改共享错误页的标准流程如下编辑 Views/ErrorPage.cshtml调整页面结构、文案或样式如需要可同步修改ErrorPage.css/ErrorPage.js确保已按仓库构建流程产出RazorPageGenerator工具artifacts\bin\RazorPageGenerator\Debug\net11.0\dotnet-razorpagegenerator.exe若不存在需先构建 src/Middleware/tools/RazorPageGenerator/RazorPageGenerator.csproj在 PowerShell 中执行.\GeneratePage.ps1脚本会自动在Views/下生成新的ErrorPage.Designer.cs并将其移动到src/Shared/ErrorPage/ErrorPage.Designer.cs重新构建依赖该共享视图的项目Hosting、Diagnostics 等并运行测试验证可参考 src/Middleware/Diagnostics/test/UnitTests/DeveloperExceptionPageMiddlewareTest.cs 对异常页输出的断言。关键约束切勿手工编辑ErrorPage.Designer.cs生成的 Designer 文件通过#line指令映射回 cshtml若需定位渲染逻辑请以 cshtml 为准。小结src/Shared/ErrorPage展示了 ASP.NET Core 内部一个典型的单一手写视图源 代码生成器 多项目共享工程模式README 仅两段话却精确锚定了三个关键事实——共享归属多个项目共用、生成工具RazorPageGenerator、修改流程改 cshtml → 跑 GeneratePage.ps1。在此基础上ErrorPageModelBuilder负责采集运行时与异常信息ErrorPageModel定义渲染契约ErrorPage.Designer.cs提供无反射的强类型渲染实现最终由 Hosting 启动兜底与 DeveloperExceptionPage 中间件两条链路消费。理解这条链路对任何需要定制 ASP.NET Core 内部错误页或复用其Razor 模板 生成器模式的开发者都极具参考价值。【免费下载链接】aspnetcoreASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.项目地址: https://gitcode.com/GitHub_Trending/as/aspnetcore创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表