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

ASP.NET MVC迁移Blazor:Web API与Blazor共享模型方案咨询

最佳方案:共享类库 + 客户端数据管理实践

一、共享模型类库的实现

这是复用模型的核心方案,步骤如下:

  • 创建**.NET Standard 2.1+或.NET 6+**类库项目(Blazor WebAssembly和Web API均兼容此目标框架)
  • 将Web API中Manga、MangaChapterViewModel等模型迁移至该类库,保留序列化相关特性(如[JsonPropertyName]、[Required])以保证两端序列化逻辑一致
  • 在Web API项目和Blazor客户端项目中添加对该类库的引用

示例模型代码:

// 共享类库中的模型定义
using System.Text.Json.Serialization;

namespace SharedModels
{
    public class Manga
    {
        [JsonPropertyName("id")]
        public int Id { get; set; }
        
        [JsonPropertyName("title")]
        public string Title { get; set; } = string.Empty;
        
        [JsonPropertyName("author")]
        public string Author { get; set; } = string.Empty;
    }

    public class MangaChapterViewModel
    {
        [JsonPropertyName("chapterNumber")]
        public int ChapterNumber { get; set; }
        
        [JsonPropertyName("title")]
        public string Title { get; set; } = string.Empty;
        
        [JsonPropertyName("releaseDate")]
        public DateTime ReleaseDate { get; set; }
    }
}

二、Blazor客户端序列化/反序列化配置

Blazor WebAssembly默认使用System.Text.Json,与Web API默认序列化工具一致,需确保两端配置对齐:
在Blazor的Program.cs中配置HttpClient的序列化选项:

builder.Services.AddScoped(sp => new HttpClient
{
    BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
}.ConfigureHttpClientJsonOptions(options =>
{
    // 与Web API保持驼峰命名规则
    options.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
    // 序列化时忽略null值
    options.SerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
}));

三、Blazor客户端HTTP请求封装

建议封装统一的API服务类,避免重复编写HTTP请求逻辑,同时直接复用共享模型:

// Blazor客户端的API服务类
using SharedModels;
using System.Net.Http.Json;

namespace BlazorClient.Services
{
    public class MangaApiService
    {
        private readonly HttpClient _httpClient;

        public MangaApiService(HttpClient httpClient)
        {
            _httpClient = httpClient;
        }

        public async Task<List<Manga>> GetAllMangasAsync()
        {
            return await _httpClient.GetFromJsonAsync<List<Manga>>("api/manga") ?? new List<Manga>();
        }

        public async Task<MangaChapterViewModel?> GetChapterAsync(int mangaId, int chapterNumber)
        {
            return await _httpClient.GetFromJsonAsync<MangaChapterViewModel>($"api/manga/{mangaId}/chapters/{chapterNumber}");
        }

        // 新增漫画示例方法
        public async Task<Manga> AddMangaAsync(Manga newManga)
        {
            var response = await _httpClient.PostAsJsonAsync("api/manga", newManga);
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadFromJsonAsync<Manga>() ?? new Manga();
        }
    }
}

在Program.cs中注册该服务:

builder.Services.AddScoped<MangaApiService>();

四、客户端模型管理实践

1. 组件内数据管理

在Blazor组件中通过依赖注入获取API服务,直接加载并使用共享模型:

@page "/mangas"
@inject MangaApiService MangaService
@using SharedModels

<h3>漫画列表</h3>

@if (_mangas == null)
{
    <p><em>加载中...</em></p>
}
else
{
    <ul>
        @foreach (var manga in _mangas)
        {
            <li>@manga.Title - @manga.Author</li>
        }
    </ul>
}

@code {
    private List<Manga>? _mangas;

    protected override async Task OnInitializedAsync()
    {
        _mangas = await MangaService.GetAllMangasAsync();
    }
}

2. 全局状态管理(可选)

如果多个组件需要共享同一模型数据(如用户选中的漫画),可实现简单的状态容器:

// 全局状态容器
using SharedModels;

namespace BlazorClient.State
{
    public class MangaStateContainer
    {
        public Manga? SelectedManga { get; set; }

        public event Action? OnChange;

        public void SetSelectedManga(Manga manga)
        {
            SelectedManga = manga;
            NotifyStateChanged();
        }

        private void NotifyStateChanged() => OnChange?.Invoke();
    }
}

注册为单例服务:

builder.Services.AddSingleton<MangaStateContainer>();

在组件中使用状态容器:

@inject MangaStateContainer State
@using SharedModels

<button @onclick="SelectManga">选择当前漫画</button>

@code {
    [Parameter] public Manga? CurrentManga { get; set; }

    private void SelectManga()
    {
        if (CurrentManga != null)
        {
            State.SetSelectedManga(CurrentManga);
        }
    }
}

注意事项

  • 不要在共享模型中添加Web API专属特性(如EF Core的[Key]、[Table]),若需数据库映射,可拆分模型:共享DTO模型 + Web API项目内的EF实体模型,用AutoMapper等工具实现转换
  • 确保日期、枚举等类型在两端的序列化配置一致,避免解析错误
  • Blazor中HttpClient为作用域/单例对象,禁止在模型中持有HttpClient引用,需通过依赖注入获取

内容的提问来源于stack exchange,提问作者Darth Vader

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 10:05:04