.NET 6 Blazor Server中SfGrid筛选后ImageViewer图片加载异常求助
问题原因分析
- Blazor组件的
OnInitializedAsync仅在首次初始化时执行,SfGrid筛选后组件可能被复用,此时DocumentID参数更新但不会触发OnInitializedAsync,导致图片未重新加载。 - 参数setter中用
Task.Run调用异步方法存在错误:既未等待任务完成,也未触发组件状态更新,还可能引发线程安全问题。 - HttpClient头部处理不当,每次调用都清空默认头会影响其他请求,且重复实例化
DocumentService属于冗余操作。
最优实现方案
1. 用OnParametersSetAsync处理初始化与参数更新
替换OnInitializedAsync,改用OnParametersSetAsync——该方法会在组件初始化以及参数变更时执行,完美适配网格筛选后的场景:
@inject HttpClient httpClient @if (isLoading) { <div>加载中...</div> } else if (DocumentFileData != null) { <img src="data:image;base64,@(Convert.ToBase64String(DocumentFileData))" /> } else { <div>无可用图片</div> } @code { private int _currentDocumentId; private byte[] DocumentFileData { get; set; } private bool isLoading; [Parameter] public string AuthCookieValue { get; set; } [Parameter] public int DocumentID { get; set; } protected override async Task OnParametersSetAsync() { // 仅当DocumentID变化时重新加载,避免重复请求 if (DocumentID != 0 && DocumentID != _currentDocumentId) { _currentDocumentId = DocumentID; isLoading = true; StateHasChanged(); // 触发UI更新显示加载状态 try { DocumentFileData = await GetDocumentAsync(DocumentID); } finally { isLoading = false; } } } private async Task<byte[]> GetDocumentAsync(int documentId) { // 单独创建请求消息设置头部,避免修改HttpClient全局默认头 using var request = new HttpRequestMessage(HttpMethod.Get, $"api/documents/{documentId}"); request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", AuthCookieValue); var response = await httpClient.SendAsync(request); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsByteArrayAsync(); } }
2. 优化服务与依赖注入
- 将
DocumentService注册为Scoped服务(在Program.cs中添加builder.Services.AddScoped<DocumentService>()),直接注入组件而非每次实例化:
@inject DocumentService documentService
- 调整
GetDocumentAsync逻辑:
private async Task<byte[]> GetDocumentAsync(int documentId) { var doc = await documentService.GetDocumentAsync(documentId); return doc.FileData; }
- 在
DocumentService内部处理请求头,避免在组件中操作HttpClient全局配置。
3. 配合SfGrid的组件实例管理
给MyImageViewer添加@key,让Blazor根据DocumentID准确识别组件实例,避免复用导致的状态混乱:
<SfGrid Data="@GridData"> <GridColumns> <GridColumn> <Template> @{ var data = (YourDataType)context; } <MyImageViewer AuthCookieValue="@AuthCookieValue" DocumentID="@data.DocumentID" @key="@data.DocumentID" /> </Template> </GridColumn> </GridColumns> </SfGrid>
关键要点总结
- 用
OnParametersSetAsync替代OnInitializedAsync,覆盖初始化与参数变更两种场景。 - 通过
@key帮助Blazor正确管理组件实例,避免复用引发的状态异常。 - 异步逻辑必须在生命周期方法中处理,禁止在参数setter中调用无等待的异步方法。
- 避免修改HttpClient全局请求头,改用独立请求消息配置头部,防止影响其他组件请求。
内容的提问来源于stack exchange,提问作者user13714356
相关产品推荐
相关产品推荐

