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

Blazor客户端托管项目筛选后组件数据不刷新问题解决

Blazor 客户端项目筛选后表格不更新?API参数绑定问题踩坑记

最近在做Blazor客户端托管项目时碰到个糟心的问题:原本能正常从API加载数据的表格,添加筛选功能后,点击搜索按钮,控制台显示PersonList的数量已经变了,但页面上的表格就是纹丝不动。折腾了好一会儿才找到问题根源,给大家分享下排查和解决过程。

问题场景

我项目里的代码结构大概是这样的:

前端组件(index.razor)

继承自PersonBase,包含筛选输入框和表格,点击按钮调用LoadItems方法加载数据:

@inherits PersonBase;
<h2>list size: @PersonList.Count()</h2>
<EditForm Model="@Obj ">
<div class="col-md-12">
<div class="well">
<table class='table borderless'>
<tr>
<td colspan="2" style="text-align: right">
<InputText @bind-Value="@Search" class="form-control input-sm" style="width:200px;margin-bottom:0px" type="text" name="input3" placeholder="Pesquisar por:" />
<button class="btn btn-info" @onclick="@(() => LoadItems(@Search))">
<i class="fas fa-search"></i>
</button>
</td>
</tr>
</table>
</div>
</div>
</EditForm>
<table class="table">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
</tr>
</thead>
<tbody>
@foreach (var person in PersonList)
{
<tr>
<td>@person.Id</td>
<td>@person.Name</td>
</tr>
}
</tbody>
</table>

组件基类(PersonBase.cs)

负责调用API加载数据,并且已经手动调用了StateHasChanged()通知组件更新:

namespace MyProject.Client.Pages.PersonComponent
{
public class PersonBase : ComponentBase
{
[Inject]
public HttpClient Http { get; set; }
[Inject]
public NavigationManager Navigation { get; set; }
[Parameter]
public string Search { get; set; } = string.Empty;
protected IEnumerable<Person> Itens { get; set; }
[Parameter]
public List<Person> PersonList { get; set; }
public int idObj;
[Parameter]
public Person Obj { get; set; }
protected override async Task OnInitializedAsync()
{
Obj = new Person();
await LoadItems(null);
Console.WriteLine("OnInitializedAsync => " + PersonList.Count);
}

protected async Task LoadItems(string search)
{
try
{
var httpResponse = await Http.GetAsync($"api/person/list/{search}");
if (httpResponse.IsSuccessStatusCode)
{
var responseString = await httpResponse.Content.ReadAsStringAsync();
PersonList = JsonSerializer.Deserialize<List<Person>>(responseString, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });
Itens = PersonList;
Console.WriteLine("LoadItems => PersonList => " + PersonList.Count);
await InvokeAsync(() => StateHasChanged()).ConfigureAwait(false);
}
}
catch (Exception)
{
throw;
}
}
}
}

API控制器(PersonController.cs)

原本的路由定义是把search作为路由参数:

[HttpGet("list/{search}")]
public async Task<ActionResult<List<Person>>> GetByAll(string search)
{
try
{
if (string.IsNullOrEmpty(search))
{
return await _context.Person
.AsNoTracking()
.Take(3)
.ToListAsync();
}
else
{
return await _context.Person
.AsNoTracking()
.Where(n => n.Name.ToLower().Contains(search.ToLower()))
.Take(3)
.ToListAsync();
}
}
catch (Exception)
{
throw;
}
}

现象是:页面初始加载3条数据正常,但输入筛选关键词点击搜索后,控制台打印的PersonList.Count是正确的筛选后数量,但页面表格就是不更新。

排查与解决

一开始我以为是Blazor的组件更新问题,检查了StateHasChanged()也调用了,PersonList也重新赋值了,前端逻辑没问题。那问题肯定出在API这边——是不是API没正确接收到筛选参数,导致返回的还是初始数据?

仔细看API的路由定义:[HttpGet("list/{search}")],这里是把search作为路由参数,但当我调用Http.GetAsync($"api/person/list/{search}")时,如果search是空字符串,请求路径会变成api/person/list/,这会导致路由匹配异常;而且就算有值,这种方式也不如查询字符串直观,更关键的是,API没有显式指定参数的绑定来源。

修正方案

  1. 调整API控制器的路由和参数绑定
    把路由改成查询字符串模式,用[FromQuery]特性明确指定参数来自查询字符串:
[HttpGet]
[Route("list")]
public async Task<ActionResult<List<Person>>> GetByAll([FromQuery]string search = "")
{
try
{
if (string.IsNullOrEmpty(search))
{
return await _context.Person
.AsNoTracking()
.Take(3)
.ToListAsync();
}
else
{
return await _context.Person
.AsNoTracking()
.Where(n => n.Name.ToLower().Contains(search.ToLower()))
.Take(3)
.ToListAsync();
}
}
catch (Exception)
{
throw;
}
}
  1. 调整前端的API请求方式
    把原来的路由参数请求改成查询字符串请求:
var httpResponse = await Http.GetAsync($"api/person/list?search={search}");

改完之后再测试,筛选功能正常了,表格也能实时更新新的数据列表了!

总结

这个问题的核心是API参数绑定方式错误,导致筛选参数没有被正确接收,API返回的还是初始数据,所以前端看起来表格没更新。Blazor这边的组件更新逻辑是没问题的,只要API返回了正确的筛选后数据,前端就能正常渲染。

内容的提问来源于stack exchange,提问作者Diego Venâncio

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 15:37:55