@code {
private Person person = new();
事件处理程序
使用以下内容创建事件处理程序时,客户端代码将触发 C# 代码调用:
@onclick
@onchange
其他 @on...
特性
@bind
在这些情况下,事件处理程序代码可能会引发未经处理的异常。
如果应用调用可能因外部原因而失败的代码,请使用 try-catch
语句捕获异常,并进行错误处理和日志记录。
如果事件处理程序引发未经处理的异常(例如数据库查询失败),其未捕获且由开发人员代码处理:
框架会记录异常。
在线路上运行的 Blazor 应用中,异常对于应用的线路来说是严重异常。
例如,可从 UI 中删除组件,因为用户已导航到其他页面。 当从 UI 中删除实现 System.IDisposable 的组件时,框架将调用该组件的 Dispose 方法。
如果组件的 Dispose
方法在线路上运行的 Blazor 应用中引发未经处理的异常,则该异常对于应用的线路来说是严重异常。
如果处置逻辑可能引发异常,应用应使用 try-catch
语句捕获异常,并进行错误处理和日志记录。
有关组件处置的详细信息,请参阅 ASP.NET Core Razor 组件生命周期。
JavaScript 互操作
IJSRuntime 由 Blazor 框架注册。 IJSRuntime.InvokeAsync 允许 .NET 代码在用户浏览器中对 JavaScript (JS) 运行时进行异步调用。
以下条件适用于带有 InvokeAsync 的错误处理:
如果无法对 InvokeAsync 进行同步调用,则会发生 .NET 异常。 例如,对 InvokeAsync 的调用可能会失败,因为不能序列化提供的自变量。 开发人员代码必须捕获异常。 如果事件处理程序或组件生命周期方法中的应用代码在线路上运行的 Blazor 应用中没有处理异常,则该异常对于应用的线路来说是严重异常。
如果无法对 InvokeAsync 进行异步调用,则 .NET Task 会失败。 例如,对 InvokeAsync 的调用可能会失败,这是因为 JS 端代码会引发异常或返回完成状态为 rejected
的 Promise
。 开发人员代码必须捕获异常。 如果使用 await
运算符,请考虑使用 try-catch
语句包装方法调用,并进行错误处理和日志记录。 否则,在线路上运行的 Blazor 应用中,失败的代码会导致未经处理的异常,这对于应用的线路来说是严重异常。
默认情况下,对 InvokeAsync 的调用必须在特定时间段内完成,否则调用会超时。默认超时时间为一分钟。 超时会保护代码免受网络连接丢失的影响,或者保护永远不会发回完成消息的 JS 代码。 如果调用超时,则生成的 System.Threading.Tasks 将失败,并出现 OperationCanceledException。 捕获异常,并进行异常处理和日志记录。
同样,JS 代码可以对 [JSInvokable]
特性指示的 .NET 方法发起调用。 如果这些 .NET 方法引发未经处理的异常:
在线路上运行的 Blazor 应用中,异常不会被视为对应用线路严重异常。
JS 端 Promise
将被拒绝。
可选择在方法调用的 .NET 端或 JS 端使用错误处理代码。
有关详细信息,请参阅以下文章:
在 ASP.NET Core Blazor 中从 .NET 方法调用 JavaScript 函数
在 ASP.NET Core Blazor 中从 JavaScript 函数调用 .NET 方法
默认情况下,Razor 组件是预先呈现的,因此它们呈现的 HTML 标记将作为用户初始 HTTP 请求的一部分返回。
在线路上运行的 Blazor 应用中,预呈现的工作方式如下:
为属于同一页面的所有预呈现组件创建新的线路。
生成初始 HTML。
将线路视为 disconnected
,直到用户浏览器与同一服务器重新建立起 SignalR 连接。 建立该连接后,将恢复线路的交互性,并更新组件的 HTML 标记。
对于预提交的客户端组件,预提交的工作方式如下:
针对属于同一页的所有预呈现组件,在服务器上生成初始 HTML。
在浏览器加载应用的已编译代码和 .NET 运行时后(如果尚未加载),使组件在客户端上交互。
如果组件在预呈现期间引发未经处理的异常,例如在生命周期方法或呈现逻辑中:
在线路上运行的 Blazor 应用中,异常对于线路来说是严重异常。 对于预呈现的客户端组件,异常会阻止呈现组件。
此异常将从 ComponentTagHelper 中的调用堆栈引发。
在正常情况下,如果预呈现失败,则继续生成和呈现组件都将没有作用,因为无法呈现工作组件。
若要容许在预呈现期间可能发生的错误,必须将错误处理逻辑置于可能引发异常的组件中。 请使用 try-catch
语句,并进行错误处理和日志记录。 请勿将 ComponentTagHelper 包装在 try-catch
语句中,而是将错误处理逻辑放在由 ComponentTagHelper 呈现的组件中。
组件能以递归方式嵌套。 这适用于表示递归数据结构。 例如,TreeNode
组件可以为节点的每个子级呈现更多 TreeNode
组件。
以递归方式呈现时,请避免采用会导致无限递归的编码模式:
请勿以递归方式呈现包含循环的数据结构。 例如,请勿呈现其子级包含其自身的树节点。
请勿创建包含循环的布局链。 例如,请勿创建布局为其本身的布局。
请勿允许最终用户通过恶意数据输入或 JavaScript 互操作调用违反递归固定协定(规则)。
呈现过程中的无限循环:
会导致呈现过程永久地继续下去。
相当于创建不终止的循环。
在这些情况下,Blazor 会失败,通常会尝试:
在操作系统允许范围内无限期地消耗 CPU 时间。
消耗不限量的内存。 消耗不限量的内存相当于不终止的循环在每次迭代时向集合添加条目的情况。
若要避免无限递归模式,请确保递归呈现代码包含合适的停止条件。
自定义呈现器树逻辑
大多数 Razor 组件都实现为 Razor 组件文件 (.razor
),并由框架编译以生成在 RenderTreeBuilder 上运行的逻辑,从而呈现其输出。 但是,开发人员可使用程序 C# 代码手动实现 RenderTreeBuilder 逻辑。 有关详细信息,请参阅 ASP.NET Core Blazor 高级方案(呈现器树构造)。
手动呈现树生成器逻辑被视为一种高级且不安全的方案,不建议开发人员在常规组件开发工作中采用。
如果编写 RenderTreeBuilder 代码,开发人员必须保证代码的正确性。 例如,开发人员必须确保:
对 OpenElement 和 CloseElement 的调用已正确均衡。
仅将特性添加到正确的位置。
如果手动呈现树生成器逻辑不正确,可能会出现任意未定义的行为(包括崩溃、应用或服务器挂起)以及安全漏洞。
请知悉:手动呈现树生成器逻辑的复杂程度和危险程度与手动编写程序集代码或 Microsoft 中间语言 (MSIL) 指令是一样的。
在 Razor 组件的生命周期外处理捕获的异常
ASP.NET Core Blazor 日志记录
处理 ASP.NET Core 中的错误†
使用 ASP.NET Core 创建 Web API
Blazor 示例 GitHub 存储库 (dotnet/blazor-samples
)(下载方法)
处理 ASP.NET Core 中的错误†
使用 ASP.NET Core 创建 Web API
Blazor 示例 GitHub 存储库 (dotnet/blazor-samples
)(下载方法)
†适用于客户端 Blazor 应用用于日志记录的后端 ASP.NET Core Web API 应用。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:https://aka.ms/ContentUserFeedback。
提交和查看相关反馈