如何在 Blazor 中校验组件参数并理解 SetParametersAsync 的执行流程?
通常可以在 OnParametersSet 中校验组件参数,[Parameter] 属性保持为自动属性。需要在参数赋值前拒绝非法值,或必须在初始化逻辑执行前完成校验时,再重写 SetParametersAsync。
如何校验字符串长度和数值范围?
下面的组件示例要求 Title 不能为空且长度不超过 100,Count 至少为 1。这些数值仅用于演示,应替换成实际业务约束。
@using System
@using Microsoft.AspNetCore.Components
<p>@Title:@Count</p>
@code {
[Parameter]
public string? Title { get; set; }
[Parameter]
public int Count { get; set; } = 1;
protected override void OnParametersSet()
{
if (string.IsNullOrWhiteSpace(Title))
{
throw new ArgumentException(
"Title 不能为空。", nameof(Title));
}
if (Title.Length > 100)
{
throw new ArgumentException(
"Title 长度不能超过 100。", nameof(Title));
}
if (Count < 1)
{
throw new ArgumentOutOfRangeException(
nameof(Count), Count, "Count 必须至少为 1。");
}
}
}
进入 OnParametersSet 时,本轮传入的参数已经赋给组件属性,可以直接读取,也可以检查多个参数之间的约束。使用自动属性可以避免 setter 中的副作用干扰参数传递和渲染流程。组件参数文档
这里的异常适用于调用方传入了组件不支持的配置。如果非法值来自用户正在编辑的表单,应保存错误状态并展示提示,或使用表单验证机制,不要把正常的输入错误都处理成组件异常。
SetParametersAsync 在赋值前还是赋值后执行?
SetParametersAsync 是接收一批参数的入口。默认实现先调用 parameters.SetParameterProperties(this),然后进入初始化和参数生命周期逻辑。
以问题所引用的 .NET 9 实现为例,主要调用顺序如下:
SetParametersAsync(parameters)
→ parameters.SetParameterProperties(this)
→ 首次调用时执行 OnInitialized / OnInitializedAsync
→ OnParametersSet
→ OnParametersSetAsync
→ 发起相应的渲染请求
如果异步生命周期方法尚未完成,中间也可能发生渲染,并不是只有最后一步才会渲染。具体流程可参照 ComponentBase 的 .NET 9 源码。
在自己的重写方法中:
- 调用
SetParameterProperties之前,本轮参数还没有由这次调用写入组件属性,应从parameters读取传入值。 - 调用之后,组件属性已经包含本轮传入值,可以直接校验属性。
OnParametersSet发生在首次初始化之后。如果OnInitialized会使用这些参数,且必须在使用前校验,应把检查提前到SetParametersAsync。
调用 OnParametersSet 并不代表参数值一定发生了变化。若业务需要检测变化,应自行保存并比较上次的值。
如何在赋值前校验某个参数?
可以先用 ParameterView.TryGetValue 检查本轮传入的值,再交给基类完成赋值和生命周期处理:
public override Task SetParametersAsync(ParameterView parameters)
{
if (parameters.TryGetValue<string?>(nameof(Title), out var title))
{
if (string.IsNullOrWhiteSpace(title) || title.Length > 100)
{
throw new ArgumentException(
"Title 不能为空,且长度不能超过 100。",
nameof(Title));
}
}
return base.SetParametersAsync(parameters);
}
这个示例只检查本轮包含的 Title。未包含的参数会保留组件属性原有的值,不会自动清空。如果还要检查最终状态是否完整,或检查多个参数的组合关系,仍可在 OnParametersSet 中处理。SetParametersAsync 文档
原代码中的两处调用能否省略?
省略 SetParameterProperties(this)
原代码传给基类的是 ParameterView.Empty。如果同时省略手动赋值,基类就没有本轮参数可供写入,属性会保留之前的值,或首次调用前的默认值。
如果不需要手动赋值,直接使用下面的调用即可:
return base.SetParametersAsync(parameters);
如果已经手动执行了 parameters.SetParameterProperties(this),再传 ParameterView.Empty,则表示参数已经处理完,只让基类继续执行生命周期和渲染逻辑。空的 ParameterView 不会重置现有属性。生命周期文档
省略基类调用
仅调用 SetParameterProperties 只完成属性赋值,不会自动执行 ComponentBase.SetParametersAsync 中的初始化、参数生命周期及相关渲染调度。普通组件应保留基类调用。
还要区分“省略调用”和“省略 return”:当前方法没有声明 async,必须返回 Task。保留 return base.SetParametersAsync(...),或改成 async Task 并使用 await base.SetParametersAsync(...),都可以正确传递完成状态和异常。ComponentBase 源码
使用时还有哪些注意事项?
- 不要为了修正参数而在组件内部反复改写
[Parameter]属性。需要规范化后的值时,使用单独的字段或计算属性。 [EditorRequired]提供编辑或构建阶段的提示,不保证运行时值有效,也不能替代长度和范围校验。组件参数文档- 示例中的
Title.Length计算 UTF-16 代码单元数量。如果业务要求按用户看到的字符计数,需要另行确定计数规则。
备注:内容仅供参考。
