C#Web开发之blazor前后端分离及API接口编写参考汇总

2022/11/14 program 共 4129 字,约 12 分钟

解决方案里的项目结构

项目说明所需三方库
APIs作为访问数据库的服务和提供WebApi的项目,其实可以再拆分,把访问数据库的服务拆出来。Microsoft.EntityFrameworkCore.Design Microsoft.EntityFrameworkCore.Tools Pomelo.EntityFrameworkCore.MySql Newtonsoft.Json Microsoft.Extensions.Configuration.Abstractions System.Linq.Dynamic.Core
Client前端 
Shared前端 (其实 ClientShared 可以合并为一个,因为是模板自动生成,暂且这样)BootstrapBlazor
Server后端Microsoft.EntityFrameworkCore.Design Microsoft.EntityFrameworkCore.Tools Pomelo.EntityFrameworkCore.MySql Newtonsoft.Json Swashbuckle.AspNetCore System.Linq.Dynamic.Core
Entities前后端共用的一些结构体Microsoft.Extensions.Configuration.Abstractions
Util前后端共用的类封装。根据实际需要

项目引用关系

  1. Client:引用 SharedEntitiesUtil
  2. Shared:引用 EntitiesUtil
  3. Server:引用 APIsEntitiesUtil

人员分工

如果全程是一个人开发,全部项目添加到同一个解决方案里即可,如果是前后端不同人员开发,则按照下面方式:

  1. 前端开发负责:ClientSharedEntitiesUtil
  2. 后端开发负责:ServerAPIsEntitiesUtil
  3. 公共部分:EntitiesUtil,除此之外的项目应该按照权限隔离开来。

调试运行

  1. 迁移数据库时:设置 Server项目为启动项目,打开PM控制台并切换到APIs,然后执行迁移命令;
  2. 联调运行时:配置启动项目 - 通用属性 - 启动项目 - 多个启动项目,勾选:ClientServer,然后调试运行即可。这个时候会同时运行服务端和前端,两个项目可以同时调试,比较方便。

接口编写步骤

  1. 先写Model,模型设计及数据库迁移可以参考:C# blazor Web开发之数据库汇总 — 朱皮特的烂笔头

  2. 配置数据源:创建好数据库,然后配置appsettings.json

  3. 添加并注册DbContext派生类;

  4. 如果模型及数据有变更,需要执行一次数据迁移;

  5. 编写写服务端的service(使用DbContext)并注册,一般是三个文件:一个接口、一个实现、一个扩展服务(可选);

  6. 编写服务端的controller

  7. 使用 swagger 测试

    1. 添加三方库:Swashbuckle.AspNetCore

    2. 添加初始化代码:

      if(env.IsDevelopment()) {
          app.UseSwagger();
          app.UseSwaggerUI();
      }
            
      builder.Services.AddSwaggerGen();
      
    3. 服务运行后访问:https://localhost:7155/swagger/index.html 测试接口及服务编写的正确性。

  8. 编写客户端的service(使用http发送请求)并注册,一般是两个文件:一个接口、一个实现。

服务请求方法

PostAsync

public async Task<ServiceResponse<bool>> Create(Module obj) {
    ServiceResponse<bool> ret = new();
    if (obj.Memo?.Length > Settings.MemoMaxSize) {
        obj.Memo = obj.Memo.Substring(0, Settings.MemoMaxSize);
    }
    var postContent = System.Text.Json.JsonSerializer.Serialize(obj, _jsonSerializerOptions);
    var bodyContent = new StringContent(postContent, Encoding.UTF8, "application/json");

    var response = await _client.PostAsync("api/module/create", bodyContent);
    if (response.IsSuccessStatusCode) {
        ret = await response.Content.ReadFromJsonAsync<ServiceResponse<bool>>(_jsonSerializerOptions) ?? ret;
    } else {
        ret.Success = false;
        var content = await response.Content.ReadAsStringAsync();
        ret.Message = $"Create failed with status code: {response.StatusCode}\nResponse content: {content}";
        throw new ApplicationException(content);
    }

    return ret;
}

PostAsJsonAsync

public async Task<ServiceResponse<PagedList<Module>>> GetAll(ModuleFilterParam param) {
    HttpResponseMessage response = await _client.PostAsJsonAsync($"api/module", param);
    response.EnsureSuccessStatusCode(); // 确保响应成功
    var content = await response.Content.ReadFromJsonAsync<ServiceResponse<PagedList<Module>>>(_jsonSerializerOptions);
    return content ?? new();
}

DeleteAsync

public async Task Delete(long id) {
    var postResult = await _client.DeleteAsync("api/module/delete/" + id);
    var postContent = await postResult.Content.ReadAsStringAsync();

    if (!postResult.IsSuccessStatusCode) {
        throw new ApplicationException(postContent);
    }
}

PutAsync

public async Task<ServiceResponse<bool>> Update(Module obj) {
    ServiceResponse<bool> ret = new();
    try {
        var postContent = System.Text.Json.JsonSerializer.Serialize(obj, _jsonSerializerOptions);
        var bodyContent = new StringContent(postContent, Encoding.UTF8, "application/json");

        var response = await _client.PutAsync("api/module/update", bodyContent);

        if (response.IsSuccessStatusCode) {
            ret = await response.Content.ReadFromJsonAsync<ServiceResponse<bool>>(_jsonSerializerOptions) ?? ret;
        } else {
            var content = await response.Content.ReadAsStringAsync();
            ret.Success = false;
            ret.Message = $"Update failed with status code: {response.StatusCode}\nResponse content: {content}";
            throw new ApplicationException(content);
        }
    } catch (Exception e) {
        ret.Success = false;
        ret.Message = $"Exception occured in Update: {e.Message}";
        if (e.InnerException != null) {
            ret.Message += $"\nInner exception: {e.InnerException.Message}";
        }
        ret.Message += $"\bStack trace: {e.StackTrace}";
        throw;
    }

    return ret;
}

DeleteFromJsonAsync

GetFromJsonAsync

var res = await _client.GetFromJsonAsync<ServiceResponse<xxx>>(Url + "/api/chat/message");
res.Data

PatchAsJsonAsync

PostAsJsonAsync

PutAsJsonAsync

文档信息

Search

    Table of Contents