编辑分类名称后UI显示陈旧数据(数据库数据正确)
项目概述
我正在用Blazor Server/Web App开发学校的网店项目,已完成登录/注册页面,以及管理员可对分类执行增删改操作的概览页面。
问题描述
编辑分类时,系统不允许将分类名称修改为已存在的名称,后端逻辑已生效:提交重复名称时用户会收到错误提示,数据库中的分类名称也不会变更。但导航回分类概览页面时,UI却显示修改后的重复名称,刷新页面后该异常消失。
已尝试方案
我曾尝试以下操作,但均未解决问题:
- 在
OnInitializedAsync()中调用StateHasChanged() - 改用
OnParametersSetAsync()加载数据 - 监听
NavigationManager.LocationChanged事件 - 调用
ResetCategory函数重置分类数据
问题根源
该问题由Blazor Server的组件状态缓存机制导致:分类概览页面的categories列表仅在组件初始化时加载一次,从编辑页面导航返回时,组件未重新获取最新的分类数据,仍使用之前缓存的对象(其中被修改名称的分类对象引用未更新,因此UI显示了未被数据库持久化的修改值)。
解决方案
方案1:订阅导航事件,返回页面时重新加载数据
修改分类概览页面代码,订阅NavigationManager.LocationChanged事件,每次导航到该页面时重新从数据库拉取分类数据:
@page "/categories" @inject ICategoryService CategoryService @inject NavigationManager NavigationManager @rendermode @(new InteractiveServerRenderMode(prerender: false)) @attribute [Authorize(Roles = "Administrator")] @implements IDisposable <PageTitle>Categorieën</PageTitle> <h3>Categorieën</h3> @if (categories.Count == 0) { <p><em>Loading categories...</em></p> } else { <table class="table"> <thead> <tr> <th>Naam</th> <th>Beschrijving (optioneel)</th> <th></th> <th></th> </tr> </thead> <tbody> @foreach (var category in categories) { <tr> <td>@category.Name</td> <td>@category.Description</td> <td><button class="btn btn-primary" @onclick="@(() => EditCategory(category.Id))">Aanpassen</button></td> <td><button class="btn btn-danger" @onclick="@(() => DeleteCategory(category.Id))">Verwijderen</button></td> </tr> } </tbody> </table> <button class="btn btn-primary" @onclick="AddCategory">Categorie toevoegen</button> } @code { List<Category> categories = new List<Category>(); private IDisposable? _locationSubscription; protected override async Task OnInitializedAsync() { await LoadCategories(); // 订阅导航变更事件 _locationSubscription = NavigationManager.LocationChanged += OnLocationChanged; } private async void OnLocationChanged(object? sender, LocationChangedEventArgs e) { // 判断是否导航回当前分类页面 if (e.Location.Contains("/categories")) { await LoadCategories(); } } // 封装加载分类的逻辑,便于复用 private async Task LoadCategories() { categories = await CategoryService.GetAllCategoriesAsync(); StateHasChanged(); } void EditCategory(int? id) { NavigationManager.NavigateTo($"/edit-category/{id}"); } async Task DeleteCategory(int id) { await CategoryService.DeleteCategoryAsync(id); await LoadCategories(); } void AddCategory() { NavigationManager.NavigateTo("/edit-category"); } // 释放订阅资源 public void Dispose() { _locationSubscription?.Dispose(); } }
方案2:检查服务层是否存在缓存
若ICategoryService的实现中使用了内存缓存(如IMemoryCache),需确保GetAllCategoriesAsync方法每次都从数据库获取最新数据,而非返回缓存结果。例如移除服务层中对分类列表的缓存逻辑,或在编辑/删除操作后清空对应缓存。
方案3:强制整页刷新(不推荐)
虽然你已在编辑页面使用NavigationManager.NavigateTo("/categories", true)(第二个参数forceLoad设为true),该参数会强制浏览器整页刷新,若仍无效,需检查是否存在浏览器缓存或服务端输出缓存,可在响应头中添加禁用缓存的配置。
内容的提问来源于stack exchange,提问作者JipJip

