Blazor SignalR项目Scoped服务注入失败,无法提供RoomState属性值求助
问题排查与解决
错误信息
InvalidOperationException: Cannot provide a value for property 'RoomState' on type 'BlazorSignalRApp.Client.Pages.Components.JoinRoom'. There is no registered service of type 'BlazorSignalRApp.Client.RoomStateService'.
问题根源
从代码来看,核心问题出在IRoomStateService的命名空间缺失,以及可能存在的服务注册上下文错误:
IRoomStateService未声明命名空间,但实现类RoomStateService属于BlazorSignalRApp.Client命名空间,导致DI容器无法正确识别接口与实现的绑定关系。- 若服务注册代码写在服务器端Program.cs而非客户端项目的Program.cs中,Blazor客户端无法访问该服务,也会触发此错误。
修复步骤
1. 给IRoomStateService补充命名空间
修改IRoomStateService.cs,添加与实现类一致的命名空间:
namespace BlazorSignalRApp.Client; public interface IRoomStateService { string? RoomId { get; set; } event EventHandler? OnRoomIdChanged; }
2. 确认服务注册在客户端Program.cs
确保服务注册代码位于Blazor客户端项目的Program.cs中,若命名空间未自动引用需手动添加:
using BlazorSignalRApp.Client; var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.RootComponents.Add<App>("#app"); builder.RootComponents.Add<HeadOutlet>("head::after"); // 注册状态服务 builder.Services.AddScoped<IRoomStateService, RoomStateService>(); builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); await builder.Build().RunAsync();
3. 组件注入无需修改
JoinRoom.razor中的@inject IRoomStateService RoomState代码正确,DI容器会自动解析到实现类。
完整代码参考
IRoomStateService.cs
namespace BlazorSignalRApp.Client; public interface IRoomStateService { string? RoomId { get; set; } event EventHandler? OnRoomIdChanged; }
RoomStateService.cs
namespace BlazorSignalRApp.Client; public class RoomStateService : IRoomStateService { private string? roomId; public string? RoomId { get => roomId; set { if (roomId != value) { roomId = value; OnRoomIdChanged?.Invoke(this, EventArgs.Empty); } } } public event EventHandler? OnRoomIdChanged; }
客户端Program.cs
using BlazorSignalRApp.Client; using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.WebAssembly.Hosting; var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.RootComponents.Add<App>("#app"); builder.RootComponents.Add<HeadOutlet>("head::after"); builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); builder.Services.AddScoped<IRoomStateService, RoomStateService>(); await builder.Build().RunAsync();
JoinRoom.razor
@inject IRoomStateService RoomState <div class="card"> <div class="card-body"> <h5 class="card-title">Join room</h5> <p class="card-text">Enter the room ID to join a room.</p> <div class="input-group"> <input class="form-control" @bind="roomId" placeholder="Enter Room ID" /> <button type="button" class="btn btn-primary" @onclick="StoreRoomId">Store Room ID</button> </div> </div> </div> @code { private string? roomId; private void StoreRoomId() { RoomState.RoomId = roomId; } }
内容的提问来源于stack exchange,提问作者SkyriderDragoon
相关产品推荐
相关产品推荐

