You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 8 Blazor Web App页面加载数据后自动刷新问题排查

.NET 8 Blazor Web App 页面加载后自动重置问题

我在.NET 8 Blazor Web App(同时支持Server与Client模式)中开发了如下页面:

@page "/modifySpec/{SpecID}"
@rendermode InteractiveServer
@attribute [StreamRendering()]

@using Corrugated_IO.Data
@using Corrugated_IO.Portal.Data

@inject CosmosDataSource cosmosDataSource
@inject NotificationService NotificationService
@inject DialogService DialogService

<h3>ManageSpecTemplates</h3>

@if (spec == null)
{
    <div>
        <RadzenProgressBarCircular Value="100" ShowValue="false" Mode="ProgressBarMode.Indeterminate" Size="ProgressBarCircularSize.Large" />
        <RadzenText TextStyle="TextStyle.Caption">Loading...</RadzenText>
    </div>
    return;
}

<RadzenRow>
    <RadzenColumn Size="6">
        <RadzenStack Orientation="Orientation.Vertical" >
            <RadzenRow >
                <RadzenColumn>
                    <RadzenText>Product ID: </RadzenText> <RadzenTextBox Value="@spec?.ProductId" Disabled="true" Style="width: 100%" />
                </RadzenColumn>
                <RadzenColumn Size="6">
                    <RadzenTextArea Value="@spec?.Description" Placeholder="Description" Style="width: 100%; height: 100%" />
                </RadzenColumn>
            </RadzenRow>
            <RadzenRow>
                <RadzenColumn Size="3"><RadzenText Text="Customer:" Style="margin-top: 10px" /></RadzenColumn>
                <RadzenColumn><RadzenTextBox Disabled="true" Style="width: 100%" Value="@spec.Customer.Name"/></RadzenColumn>
                <RadzenColumn><RadzenButton Text="Change" /><RadzenButton Text="Copy" /></RadzenColumn>
            </RadzenRow>
            <RadzenRow>
                <RadzenColumn Size="3"><RadzenText Style="margin-top: 10px" Text="Style:" /></RadzenColumn>
                <RadzenColumn><RadzenTextBox Disabled="true" Style="width: 100%" Value="@spec.CutStyle.Name" /></RadzenColumn>
                <RadzenColumn><RadzenButton Text="Change" /></RadzenColumn>
            </RadzenRow>
            <RadzenRow Style="height: 40px">
                <RadzenColumn Size="3"><RadzenText Text="Starting Material or Operation:" /></RadzenColumn>
                <RadzenColumn Size="2"><RadzenTextBox Disabled="true" Style="width: 100%" Value="@spec.StartingMaterial_Op" /></RadzenColumn>
                <RadzenColumn Size="2"><RadzenButton Text="Change" /></RadzenColumn>
                <RadzenColumn Size="4">
                    <RadzenStack Orientation="Orientation.Horizontal">
                        <RadzenText Text="Flute:" Style="margin-top: 10px" />
                        <RadzenDropDown Data=@flutes TValue="Flute" TextProperty="LetterGrade" @bind-Value="@selectedFlute" SelectedItem="@selectedFlute" Change="@(args => selectedFlute = (Flute)args)" Style="width: 50%" />
                    </RadzenStack>
                </RadzenColumn>
                
            </RadzenRow>
            <RadzenRow>
                <RadzenColumn><RadzenButton Text="Discard Changes" /></RadzenColumn>
                <RadzenColumn><RadzenButton Text="Estimate Spec" Style="float: right" /></RadzenColumn>
            </RadzenRow>
        </RadzenStack>
    </RadzenColumn>
    <RadzenColumn>
        
    </RadzenColumn>
    <RadzenColumn>

    </RadzenColumn>
</RadzenRow>
<RadzenRow>
    @* <CutStyleComponent /> *@
</RadzenRow>

@code {
    [Parameter]
    public string SpecID { get; set; } = string.Empty;

    public Spec? spec { get; private set; }

    List<string> stringList = new List<string>{"Foo","Bar"};

    List<Flute> flutes = new List<Flute>();
    Flute selectedFlute = null;

    protected override async Task OnInitializedAsync()
    {
        DefineFlutes();
        spec = await cosmosDataSource.GetSpec(SpecID);

        if(spec is null)
        {
            NotificationService.Notify(NotificationSeverity.Error, "Spec ID not Found", $"Spec ID ({SpecID}) was not found", 30000);
        }
    }
    

    public async Task ChangeCutStyle()
    {
        
    }

    private void DefineFlutes()
    {
        flutes.AddRange(new[]{
            new Flute
            {
                LetterGrade = 'A',
                FlutesPerFoot = 33,
                Thickness = 0.1875m
            },
            new Flute
            {
                LetterGrade = 'B',
                FlutesPerFoot = 47,
                Thickness = 0.125m
            },
            new Flute
            {
                LetterGrade = 'C',
                FlutesPerFoot = 38,
                Thickness = 0.15625m
            },
            new Flute
            {
                LetterGrade = 'E',
                FlutesPerFoot = 90,
                Thickness = 0.0625m
            },
            new Flute
            {
                LetterGrade = 'F',
                FlutesPerFoot = 125,
                Thickness = 0.03125m
            }
        });
    }

}

页面从本地Cosmos加载数据并完成渲染后,会立即重置视图至刚导航时的状态。请问该自动刷新的原因是什么,如何阻止此行为?

补充说明:注释掉@rendermode InteractiveServer后页面不再刷新,但失去服务器交互性;切换为InteractiveWebAssembly或InteractivityAuto模式时无刷新,但出现错误Error: One or more errors occurred. (Root component type 'Corrugated_IO.Portal.Components.Pages.ModifySpec' could not be found in the assembly 'Portal'.)且无交互性。


问题原因

  • StreamRendering与InteractiveServer模式冲突:你同时启用了StreamRendering特性和InteractiveServer渲染模式。StreamRendering用于静态/服务器端渲染时逐步输出内容,而InteractiveServer会通过SignalR维护组件的实时状态。两者结合时,流式渲染完成后会触发组件重新初始化,导致已加载的spec数据被覆盖,视图回到初始加载状态。
  • 组件状态未被正确保留:在流式渲染结束后,组件实例可能被重建,之前在OnInitializedAsync中加载的spec数据丢失,触发加载状态的重新渲染。

解决方案

方案1:移除StreamRendering特性(推荐)

直接删除@attribute [StreamRendering()]即可,因为InteractiveServer模式本身不需要流式渲染特性。修改后的页面顶部代码如下:

@page "/modifySpec/{SpecID}"
@rendermode InteractiveServer

@using Corrugated_IO.Data
@using Corrugated_IO.Portal.Data
...

这样既能保留服务器交互性,又能避免流式渲染引发的视图重置问题。

方案2:调整生命周期逻辑(如需保留StreamRendering)

如果必须保留流式渲染,需要避免重复加载数据和覆盖状态,将数据加载逻辑移至OnParametersSetAsync并添加判断:

protected override async Task OnParametersSetAsync()
{
    // 仅在spec未加载且SpecID有效时才执行加载
    if (spec == null && !string.IsNullOrEmpty(SpecID))
    {
        DefineFlutes();
        spec = await cosmosDataSource.GetSpec(SpecID);

        if(spec is null)
        {
            NotificationService.Notify(NotificationSeverity.Error, "Spec ID not Found", $"Spec ID ({SpecID}) was not found", 30000);
        }
    }
}

这种方式可以防止组件重新初始化时重复加载数据,但不如直接移除StreamRendering简洁。

WebAssembly模式错误修复

出现组件类型找不到的错误,是因为WebAssembly项目未正确注册或引用该组件:

  • 检查Web App的Program.cs,确保WebAssembly服务配置中包含组件所在的命名空间或程序集;
  • 确认ModifySpec页面的命名空间为Corrugated_IO.Portal.Components.Pages,且WebAssembly项目已引用包含该组件的程序集;
  • 如果组件在Razor类库中,确保WebAssembly项目添加了对该类库的引用。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 10:47:04