Blazor .NET Core 8:如何在客户端使用服务器端组件?
解决方案
1. 拆分独立业务逻辑层
避免循环依赖的核心是把数据库访问、核心业务逻辑从服务器项目抽离到独立的类库项目(比如命名为YourApp.Data或YourApp.Core):
- 将EF Core上下文、数据库操作方法、业务逻辑类全部迁移到这个类库
- 服务器项目(Server)引用该类库,负责实际的数据处理和接口暴露
- 客户端项目(Client)无需引用服务器项目,仅通过API和服务器交互
2. 通过API层实现客户端-服务器数据交互
在服务器项目中封装数据库操作的API接口,客户端通过HttpClient调用这些接口获取数据:
服务器端示例(最小API)
// Server项目的Program.cs var builder = WebApplication.CreateBuilder(args); // 注册独立类库中的数据库上下文 builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("Default"))); var app = builder.Build(); // 暴露数据查询API app.MapGet("/api/products", async (AppDbContext db) => { return await db.Products.ToListAsync(); }); // 暴露数据新增API app.MapPost("/api/products", async (AppDbContext db, Product product) => { db.Products.Add(product); await db.SaveChangesAsync(); return Results.Created($"/api/products/{product.Id}", product); }); app.Run();
客户端调用示例
在客户端项目中注入HttpClient,通过API完成数据交互:
@page "/products" @inject HttpClient Http <h3>产品列表</h3> @if (products == null) { <p>加载中...</p> } else { <ul> @foreach (var product in products) { <li>@product.Name - @product.Price</li> } </ul> } @code { private List<Product>? products; protected override async Task OnInitializedAsync() { products = await Http.GetFromJsonAsync<List<Product>>("/api/products"); } }
3. 适配InteractiveAuto渲染模式
使用InteractiveAuto时,组件可能在客户端或服务器端渲染,注意两点:
- 如果组件需要依赖服务器资源,可给组件标记
[RenderModeServer]强制服务器端渲染,但数据获取仍建议通过API方式,保持逻辑统一 - 客户端渲染的部分,完全通过
HttpClient调用API,无需直接接触服务器端的数据库组件
4. 解决@inject无效的问题
客户端_Imports.razor只能注入客户端支持的服务(比如HttpClient、NavigationManager等),服务器端的数据库上下文、服务不能直接在客户端注入。正确做法是:
- 服务器端服务在Server项目的
Program.cs中注册 - 客户端通过API间接调用这些服务的功能,而非直接注入服务器端组件
内容的提问来源于stack exchange,提问作者sTaLa
相关产品推荐
相关产品推荐

