.NET 6 之 ABP vNext 初体验

马上国庆了,dotNative 预祝大家假期愉快,Happy National Day!

本文将介绍在 .net6 平台的 asp.net core webapi 框架中,如何使用 abp vnext 框架进行模块化开发,重在思想理解。

hellp, ABP vNext

ABP vNext 介绍

  • 官方介绍

ABP vNext 本身是一个包含许多 NuGet 包的 模块化(Module) 框架。它还提供了一个完整的基础架构来开发你自己的具有实体、服务、数据库集成、API、UI 组件等等功能的应用程序模块。

  • 专业介绍

ABP vNext 框架是一个基于 ASP.NET Core 的完整基础设施,通过遵循软件开发最佳实践和最新技术来创建现代 web 应用程序和 API,不同于老的 ABP 框架。新的 ABP vNext 框架核心库更加精简,因为将原有许多的组件从其核心库抽离成独立的组件。这样开发人员可以更加灵活的选择自己需要的功能进行集成,使项目远离臃肿的库,比起原有的 ABP 框架 ABP vNext 完全基于 ASP.NET Core 丢掉了历史包袱,设计更加合理,更加细粒度的模块化设计。

  • 通俗介绍

ABP vNext 框架是一个集成多个第三方组件类库的一个应用程序集,遵循 模块化(Module) 思想实践的最佳方式。

.NET 6 之 MiniAPI 的 ABP vNext 初体验

新建项目 Demo.Abp.WebApplication1 项目

通过 dotnet cli 命令新建 asp.net core webapi 项目,命名为 Demo.Abp.WebApplication1,执行如下命令:

dotnet new webapi -n Demo.Abp.WebApplication1

或者通过 Visual Studio Community 2022 (64 位) IDE 工具创建该项目。

在这里插入图片描述

  1. 添加新建项目,选择 ASP.NET Core Web API 项目模板,点击【下一步】。

添加新建项目

  1. 配置新建项目,输入项目名称 ASP.NET Core Web API ,继续点击【下一步】。

配置项目

  1. 其他信息,这里只勾选【使用控制器】,然后点击【创建】。

其他信息

经过上面步骤, Demo.Abp.WebApplication1 项目就创建完毕了,项目结构如下:

Demo.Abp.WebApplication1

NuGet 添加 Abp 相关模块包

然后在 Demo.Abp.WebApplication1 项目中添加 nuget 包:

  • Volo.Abp.AspNetCore
  • Volo.Abp.Swashbuckle
NuGet\Install-Package Volo.Abp.AspNetCore -Version 6.0.0-rc.5

Volo.Abp.AspNetCore

NuGet\Install-Package Volo.Abp.Swashbuckle -Version 6.0.0-rc.5

Volo.Abp.Swashbuckle

Program.cs 文件默认代码如下:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();

var app = builder.Build();
// Configure the HTTP request pipeline.
app.UseAuthorization();
app.MapControllers();
app.Run();

接下来我们改造默认的 Program.cs 文件,让其遵循 ABP vNext 模块化(Module)的编程风格,操作步骤如下:

  1. 首先在 Program.cs 文件中新建一个 class 类,名称为 DemoWebApiModule,并继承 AbpModule
  2. 其次通过 DependsOn 特性来定义模块的依赖关系。
  3. 然后在 Program.cs 文件中通过 AddApplication 注入自定义模块类。
  4. 最后在 InitializeApplication 初始化 http 请求管道(request pipeline)。

Abp 模块化(Module)改造

模块化改造【同步版】

Abp 模块化(Module 改造后,Program.cs 文件 同步 版本的代码如下:

using Volo.Abp;
using Volo.Abp.AspNetCore;
using Volo.Abp.Modularity;
using Volo.Abp.Swashbuckle;

var builder = WebApplication.CreateBuilder(args);
// 重新注册 Configuration
builder.Services.ReplaceConfiguration(builder.Configuration);
// 添加自定义模块 DemoWebApiModule
builder.Services.AddApplication<DemoWebApiModule>();

/* 同上等效代码
 * 添加自定义模块 DemoWebApiModule
builder.Services.AddApplication<DemoWebApiModule>(options => {
    options.Services.ReplaceConfiguration(builder.Configuration); // 重新注册 Configuration
});
*/

var app = builder.Build();
// 初始化 http 请求管道(request pipeline)
app.InitializeApplication();

app.Run();

// 声明 ABP 对应的模块(Module)依赖
[DependsOn(typeof(AbpAspNetCoreModule))]
// 自定义模块类 DemoWebApiModule,并继承自 AbpModule 
public class DemoWebApiModule : AbpModule 
{
    // IoC 注册服务容器
    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        var services = context.Services;
        services.AddControllers();
    }
    //  http 请求管道(request pipeline)初始化
    public override void OnApplicationInitialization(ApplicationInitializationContext context)
    {
        var app = context.GetApplicationBuilder();
        var env = context.GetEnvironment();

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseRouting();
        app.UseAuthorization();

        app.UseConfiguredEndpoints(); // 替换原来的 app.MapControllers();
    }
}

说明:请求管道(request pipeline) 由各种业务逻辑对应的 中间件(middleware 组成。

到这里默认的 asp.net core webapi 项目就依据 ABP vNext 模块化(Module)的风格改造完毕。

模块化改造【异步版】

我们继续上面的 Abp 模块化(Module 【同步版】修改,此处使用【异步】模式构建,并集成 Swagger 模块,改造后代码如下:

using Microsoft.OpenApi.Models;
using Volo.Abp;
using Volo.Abp.AspNetCore;
using Volo.Abp.Modularity;
using Volo.Abp.Swashbuckle;

var builder = WebApplication.CreateBuilder(args);
//builder.Services.ReplaceConfiguration(builder.Configuration);
await builder.Services.AddApplicationAsync<DemoWebApiModule>(options => {
    options.Services.ReplaceConfiguration(builder.Configuration);
});

var app = builder.Build();
await app.InitializeApplicationAsync();

await app.RunAsync();

[DependsOn(
    typeof(AbpAspNetCoreModule),
    typeof(AbpSwashbuckleModule)
 )]
public class DemoWebApiModule : AbpModule
{
    public override async Task ConfigureServicesAsync(ServiceConfigurationContext context)
    {
        var services = context.Services;
        services.AddControllers();
        services.AddEndpointsApiExplorer();
        services.AddAbpSwaggerGen(options => {
            options.SwaggerDoc("TestAPI", new OpenApiInfo { Title = "Test DemoWebApiModule API", Version = "v1", Description = "Module 模块化 DemoWebApiModule 自定义类。" });
            options.DocInclusionPredicate((docName, description) => true);
            options.CustomSchemaIds(type => type.FullName);
        });
        await Task.CompletedTask;
    }

    public override async Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
    {
        var app = context.GetApplicationBuilder();
        var env = context.GetEnvironment();

        if (env.IsDevelopment())
        {
            //app.UseDeveloperExceptionPage();
            app.UseSwaggerUI();
            app.UseAbpSwaggerUI(options => {
                options.SwaggerEndpoint("/swagger/v1/swagger.json", "TestAPI");
            });
        }
        else
        {
            app.UseExceptionHandler("/Error");
        }

        //app.UseHttpsRedirection();
        app.UseRouting();
        app.UseAuthorization();
        app.UseConfiguredEndpoints(); //代替原来的 app.MapControllers();
        await Task.CompletedTask;
    }
}

Properties —— launchSettings.json

启动配置文件,你可以在项目中 “Properties” 文件夹中找到 launchSettings.json 文件。该文件是 ASP.NET Core 应用特有的配置标准,用于应用的启动准备工作,包括环境变量,开发端口等。

launchSettings.json 文件中进行配置和右键项目—属性中所提交的更改的效果是一样的,并且支持同步更新。此文件设置了 Visual Studio 可以启动的不同环境,以下是示例项目中 launchSettings.json 文件生成的默认配置:

{
  "$schema": "https://json.schemastore.org/launchsettings.json",
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:48492",
      "sslPort": 0
    }
  },
  "profiles": {
    "Demo.Abp.WebApplication1": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "launchUrl": "swagger",
      "applicationUrl": "http://localhost:5220",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "launchUrl": "swagger",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

运行 Module 模块化项目

我们先运行下 Demo.Abp.WebApplication1 项目,正常运行后请求默认的 WeatherForecastController

浏览器输入 weatherforecast API 地址:

http://localhost:5220/weatherforecast

API 接口访问成功,如下所示:

在这里插入图片描述

​通过以上步骤我们就完成了对 asp.net core webapi 框架 MiniAPI 模式的 ABP vNext 模块化改造。

.NET 6 还原 Program.cs & Startup.cs

由于本人不太喜欢 MiniAPI 模式,因此再继续改造,还原为 .net core 3.1 时代的玩法 —— Program.cs + Startup.cs 模式(此处不知是否有同感的小伙伴呢?)。

此处为了和上面项目形成对照(原有项目保留不变),新建一个 asp.net core webapi 项目,命名为 Demo.Abp.WebApplication2,项目结构的改造对比如下图所示:

模式对比

说明:为了演示业务 Service 类中 DI 的注入方式,这里会引入一个 Abp 集成 Autofac 的模块 —— Volo.Abp.Autofac

NuGet\Install-Package Volo.Abp.Autofac -Version 6.0.0-rc.5

Volo.Abp.Autofac

这里安装 NuGet 包同上,不再叙述,下面的步骤假定安装了如下 Abp vNext 依赖模块:

  • Volo.Abp.AspNetCore
  • Volo.Abp.Swashbuckle
  • Volo.Abp.Autofac

通过这个改造过程,学会使用 Abp vNext 模块化、规范化的应用在实际项目开发中,并且会使用 Abp vNext 依赖模块( Module 模块化具有传染性)。

改造步骤

如下改造步骤,尽量详细的介绍一下项目结构中的每一个模块,相应的类使用文件夹划分,目录层次更佳清晰明了。

1、提取 DemoWebApiModule.cs 模块化文件

MiniAPI 模式中,为了避免新建文件,直接在 Program.cs 文件中新建自定义模块化类,此处为了更好的工程化对该文件单独提取,改造代码如下所示:

using Microsoft.OpenApi.Models;
using Volo.Abp;
using Volo.Abp.AspNetCore;
using Volo.Abp.Autofac;
using Volo.Abp.Modularity;
using Volo.Abp.Swashbuckle;
using Demo.Abp.WebApplication2.Services; 

namespace Demo.Abp.WebApplication2.Module;

// 使用 Abp 模块(Module)
[DependsOn(
    typeof(AbpAspNetCoreModule),
    typeof(AbpAutofacModule),
    typeof(AbpSwashbuckleModule)
)]

// 自定义类 Module 化
public class DemoWebApiModule : AbpModule
{
    // IoC 注册服务容器
    public override async Task ConfigureServicesAsync(ServiceConfigurationContext context)
    {
        //1、IoC 注册服务类
        var services = context.Services;
        services.AddControllers();
        services.AddEndpointsApiExplorer();
        services.AddAbpSwaggerGen(options => {
            options.SwaggerDoc("v1", new OpenApiInfo { Title = "Test DemoWebApiModule API", Version = "v1", Description = "Module 模块化 DemoWebApiModule 自定义类。" });
            options.DocInclusionPredicate((docName, description) => true);
            options.CustomSchemaIds(type => type.FullName);
        });

        // 2、注册具体的业务服务(声明式)
        context.Services.AddScoped<IWeatherForecastService, WeatherForecastService>();

        await Task.CompletedTask;
    }

    // Pipeline 管道中间件初始化
    public override async Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
    {
        var app = context.GetApplicationBuilder();
        var env = context.GetEnvironment();

        if (env.IsDevelopment())
        {
            //app.UseDeveloperExceptionPage();
            app.UseSwagger();
            app.UseAbpSwaggerUI(options => {
                options.SwaggerEndpoint("/swagger/v1/swagger.json", "Test DemoWebApiModule API");
            });
        }
        else
        {
            app.UseExceptionHandler("/Error");
        }

        //app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseRouting();
        app.UseAuthorization();
        app.UseConfiguredEndpoints(); // 替代 app.MapControllers();

        await Task.CompletedTask;
    }
}

2、Startup.cs 文件代码改造

.net core 3.1.x 时代,默认 Program.cs + Startup.cs 模式,而在 Startup.cs 中存在两个方法:

  • ConfigureServices(),在该方法中注册依赖关系/服务(无序)。
  • Configure(),在该方法中(有序)注册中间件(Middleware),多个中间件组成 http 请求管道(Http request pipeline)。

这里为了上述两个方法命名更佳见名知意,特此修改如下:

  • ConfigureServices() 修改为 RegisterServicesAsync();
  • Configure() 修改为 SetupMiddlewaresAsync();

说明:这里是改造为异步模式,同步方式去除方法名称的 Async 后缀即可。

新建 Startup.cs 类,添加如下代码:

using Volo.Abp;
using Volo.Abp.Modularity.PlugIns;
using Demo.Abp.WebApplication2.Module;

namespace Demo.Abp.WebApplication2;

public class Startup
{
    public IConfiguration Configuration { get; }

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    // Add services to the container. 注册服务到 Ioc 容器
    public async Task RegisterServicesAsync(IServiceCollection services, IHostBuilder host)
    {
        Console.WriteLine($"{DateTime.UtcNow},加载 DemoWebApiModule 模块...");
        
        host.UseAutofac(); // 使用 Autofac 第三方 DI

        //services.ReplaceConfiguration(Configuration);

        // 注册自定义模块 DemoWebApiModule
        await services.AddApplicationAsync<DemoWebApiModule>(options => {
            // options.UseAutofac();

            options.Services.ReplaceConfiguration(Configuration); // 等效同上代码

            // 加载插件,固定模式,可热插拔
            // options.PlugInSources.AddFolder(@"E:\CodeStuday\dotnet6\DemoAbpPulgins");
        });
    }

    // Configure the HTTP request pipeline. 配置 HTTP 请求管道(中间件管道即中间件委托链)
    public async Task SetupMiddlewaresAsync(IApplicationBuilder app, IWebHostEnvironment env)
    {
        Console.WriteLine($"{env.ApplicationName},{DateTime.UtcNow},启动中间件管道初始化 InitializeApplicationAsync...");
        await app.InitializeApplicationAsync();
    }
}

思考:当依赖模块变多,需要频繁的调整,这样就会违背开闭原则,那么该如规避该问题呢?

其实 ABP vNext 官网提供了解决方案(PlugIns,插件机制),遵循开闭原则,只需添加 NuGetVolo.Abp.Modularity.PlugIns ,便可实现 Module 模块的插件式加载,只需如下两不操作即可:

  1. 在项目根文件添加一个文件夹,如:DemoAbpPulgins(文件夹命名尽量见名知意)。
  2. 固定模式,在 AddApplicationAddApplicationAsyncoptions 中添加如上代码(注释部分)。
  3. 将模块化组件编译好的 Xxx.dll 文件拷贝到新建的根文件夹里面,保存运行即可。

以上就实现了 Abp 模块动态加载,规避了 开闭原则 之冲突点。

开闭原则:在面向对象编程中声明 “软件实体(类、模块、函数等)应该对扩展开放,但对修改关闭”;这样的实体可以允许在不修改源代码的情况下对其行为进行扩展。

3、Program.cs 文件代码改造

由于 Startup.cs 文件里面的代码是异步的,所以 Program.cs 文件也需要调整为异步模式(异步具有传染性)。

namespace Demo.Abp.WebApplication2;

public class Program
{
    public static async Task Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);

        // 此处代码,已经调整到 RegisterServicesAsync 方法,注意观察。
        //builder.Services.ReplaceConfiguration(builder.Configuration);
        //builder.Host.UseAutofac(); // 直接使用Autofacz

        var startup = new Startup(builder.Configuration);
        await startup.RegisterServicesAsync(builder.Services, builder.Host);

        var app = builder.Build();
        await startup.SetupMiddlewaresAsync(app, builder.Environment);

        await app.RunAsync();
    }
}

4、WeatherForecastService.cs 文件改造

这里使用 WeatherForecastService.cs 文件来模拟具体的业务服务,继承自 IWeatherForecastService 接口,结构如上图中 Services 文件夹部分,代码定义如下:

  • IWeatherForecastService 接口,定义业务方法规范。
using Demo.Abp.WebApplication2.Model;

namespace Demo.Abp.WebApplication2.Services;

public interface IWeatherForecastService
{
    public IEnumerable<WeatherForecast> GetWeatherForecast();
}
  • WeatherForecastService.cs 类,继承自 IWeatherForecastService 接口。
using Volo.Abp.DependencyInjection; //引入 DI 
using Demo.Abp.WebApplication2.Model;

namespace Demo.Abp.WebApplication2.Services;

// Dependency 特性声明 Service 服务生命周期
[Dependency(ServiceLifetime.Scoped, ReplaceServices = true)]
public class WeatherForecastService : IWeatherForecastService
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    // 模拟业务操作,数据库取数据
    public IEnumerable<WeatherForecast> GetWeatherForecast()
    {
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = Random.Shared.Next(-20, 55),
            Summary = Summaries[Random.Shared.Next(Summaries.Length)]
        }).ToArray();
    }
}

5、WeatherForecast.cs 模型类

这里使用默认的模型,代码如下:

namespace Demo.Abp.WebApplication2.Model;

public class WeatherForecast
{
    public DateTime Date { get; set; }
    public int TemperatureC { get; set; }
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
    public string? Summary { get; set; }
}

6、WeatherForecastController.cs 控制器类

此处稍作调整,为了演示业务操作中 DI 调用,把默认代码调整到 WeatherForecastService.cs 类。调整代码如下:

using Microsoft.AspNetCore.Mvc;
using Demo.Abp.WebApplication2.Model;
using Demo.Abp.WebApplication2.Services;

namespace Demo.Abp.WebApplication2.Controllers;

/// <summary>
/// WebAPI 入口 
/// </summary>
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    // 1、属性 DI 注入
    public IWeatherForecastService _IWeatherForecastService { get; set; }

    // 2、构造函数 DI 注入
    private readonly ILogger<WeatherForecastController> _logger;
    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="logger"></param>
    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    {
        _logger = logger;
    }

    [HttpGet]
    public IEnumerable<WeatherForecast> GetWeatherForecast()
    {
        _logger.LogDebug($"{DateTime.UtcNow}, hello abpvnext ...");
        return _IWeatherForecastService.GetWeatherForecast();
    }
}

7、appsettings.json 配置文件

此处就用默认生成的(这里只是为了尽量说明项目文件结构),配置如下:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}

8、launchsettings.json 配置文件

{
  "$schema": "https://json.schemastore.org/launchsettings.json",
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:36683",
      "sslPort": 0
    }
  },
  "profiles": {
    "Demo.Abp.WebApplication2": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "launchUrl": "swagger",
      "applicationUrl": "http://localhost:5165",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "launchUrl": "swagger",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

到这里就基本完成了 Startup.cs 文件的改造,接下来我们启动运行测试看下,是否正常符合预期情况。

启动运行测试

启动 Abp 集成 Swagger 模块 —— Volo.Abp.Swashbuckle 符合预期正常显示。

Abp 集成 Swagger 模块

如果要隐藏 ABP vNext默认端点,可以在 Swagger 配置中调用 HideAbpEndpoints 方法,

  • AbpApiDefinition
  • AbpApplicationConfiguration

完整代码如下:

services.AddAbpSwaggerGen(options => {
    options.SwaggerDoc("v1", new OpenApiInfo { Title = "Test DemoWebApiModule API", Version = "v1", Description = "Module 模块化 DemoWebApiModule 自定义类。" });
    options.DocInclusionPredicate((docName, description) => true);
    options.CustomSchemaIds(type => type.FullName);
    options.HideAbpEndpoints(); // 隐藏 ABP vNext 的默认端点
});

运行项目,注意和上图对比,SwaggerUI 页面如下图所示:
在这里插入图片描述

点击【WeatherForecast】执行业务 ServiceDI 注册并调用,运行如下所示:

在这里插入图片描述

  1. curl 命令访问:
curl -X 'GET' \
  'http://localhost:5165/WeatherForecast' \
  -H 'accept: text/plain' \
  -H 'RequestVerificationToken: CfDJ8ODjDXixt1tDuxO1cuT_L2z6DM3lUqtnRF0xKJPwuuLU0SKbwulLhV35ySmCqoC3CuQksJoqHnyzRQw5ZT-sE5Q20mC3vFONoLQ2Tx5Y1Y9qvQ67mtBCqNnSPtCePtukjn1Ocd6ocr-0E2fJVLroRYU' \
  -H 'X-Requested-With: XMLHttpRequest'
  1. 浏览器输入 url 访问:
http://localhost:5165/WeatherForecast

在这里插入图片描述

SwaggerUI 权限配置

在生产环境中,考虑安全性,通常需要 Swagger 接入 OAuth2 认证。

ABP vNext 集成了 Identity Server 来做权限认证,需要使用 AddAbpSwaggerGenWithOAuth 扩展,在 ModuleConfigureServices 方法中,使用 OAuth issuerscopes 来配置 Swagger

    // IoC 注册服务容器
    public override async Task ConfigureServicesAsync(ServiceConfigurationContext context)
    {
        //1、IoC 注册服务类
        var services = context.Services;
        services.AddControllers();
        services.AddEndpointsApiExplorer();
        // Swagger 配置权限
        services.AddAbpSwaggerGenWithOAuth(
            authority: "https://localhost:44341",      // authority issuer
            scopes: new Dictionary<string, string> {   // scopes                               
                {"Test", "Test DemoWebApiModule API"}                 
            },
            options => {
                options.SwaggerDoc("v1", new OpenApiInfo { Title = "Test DemoWebApiModule API", Version = "v1", Description = "Module 模块化 DemoWebApiModule 自定义类。" });
                options.DocInclusionPredicate((docName, description) => true);
                options.CustomSchemaIds(type => type.FullName);
                options.HideAbpEndpoints(); // 隐藏 ABP vNext 的默认端点
            });

        // 2、注册具体的业务服务(声明式)
        context.Services.AddScoped<IWeatherForecastService, WeatherForecastService>();

        await Task.CompletedTask;
    }

    // Pipeline 管道中间件初始化
    public override async Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
    {
        var app = context.GetApplicationBuilder();
        var env = context.GetEnvironment();

        if (env.IsDevelopment())
        {
            //app.UseDeveloperExceptionPage();
            app.UseSwagger();
            app.UseAbpSwaggerUI(options => {
                options.SwaggerEndpoint("/swagger/v1/swagger.json", "Test DemoWebApiModule API");
                var configuration = context.ServiceProvider.GetRequiredService<IConfiguration>();
                options.OAuthClientId("TestSwagger");   // clientId
                options.OAuthClientSecret("!QAZ2wsx");  // clientSecret
            });
        }
        else
        {
            app.UseExceptionHandler("/Error");
        }

        //app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseRouting();
        app.UseAuthorization();
        app.UseConfiguredEndpoints(); // 替代 app.MapControllers();

        await Task.CompletedTask;
    }

说明:修改上面的代码配置后,需要提前搭建好 Identity Server 服务并启动运行,再该服务中注册 clientId & clientSecret,然后把 authority: "https://localhost:44341" 修改为 Identity Server 服务地址。

关于 Identity Server 服务的搭建,这里不是重点,想了解更多,请自行查看官网或相关资料:

  • 欢迎使用 IdentityServer4,https://identityserver4docs.readthedocs.io/zh_CN/latest/index.html
  • IdentityServer4 中文文档,http://www.identityserver.com.cn/
  • IdentityServer4 认证服务器集成 Identity & 配置持久化数据库(Sqlite),http://t.zoukankan.com/liumengchen-boke-p-11179153.html

修改配置如上代码后,运行项目 Swagger UI 如下图所示:

在这里插入图片描述

总结

asp.net core webapiMiniAPI 模式开始,遵循 ABP vNext Web 框架的 Module 模块化思想并学会使用,再到 Program.cs & Startup.cs 模式的改造,使得项目工程化体验更佳、目录层级结构更清晰,再逐步引入其他模块(Module)依赖,并通过 DependsOn 特性显示声明。

没有你那才叫可悲

遵循 ABP vNext 框架的规则,在代码层面更加直观的体现 Module 模块化开发思想。当依赖模块多,需要频繁的调整代码模块的依赖, 此时 ABP vNext 框架提供了 PlugIns 插件化机制,实现 ABP vNext 模块 插件式 的动态加载,可热插拔,符合符合 开闭原则

<think>好的,我现在需要帮助用户了解.NET WebAPI微服务架构与ABP vNext框架之间的关系及集成方式。首先,我得先理清楚两者的基本概念和各自的特点,这样才能更好地分析它们的结合点。 首先,.NET WebAPI是微软提供的一个用于构建HTTP服务的框架,它支持RESTful风格,常用于创建后端服务,特别是微服务架构中的各个服务模块。微服务架构强调将应用拆分为多个小型、独立部署的服务,每个服务负责特定的业务功能,通过轻量级通信机制(如HTTP)进行交互。这种架构的好处包括可扩展性、灵活性和技术多样性等。 然后是ABP vNext框架,它是一个开源的应用框架,专注于企业级应用的开发,提供了模块化、多租户、身份验证、授权等基础设施。ABP vNext基于领域驱动设计(DDD),并内置了许多最佳实践,帮助开发者快速搭建复杂的应用程序。从用户提供的引用来看,ABP vNext.NET Core项目中需要安装一些依赖包,比如Volo.Abp.AspNetCore.Mvc和Volo.Abp.Autofac,说明它可能依赖于ASP.NET Core和Autofac进行依赖注入。此外,引用中还提到了配置数据库连接字符串,特别是在微服务场景下,每个服务可能有自己的数据库,比如OrderService,这符合微服务的数据库隔离原则。 接下来,我需要分析这两者如何集成。ABP vNext本身支持模块化开发,每个模块可以视为一个微服务。因此,使用ABP vNext来构建各个微服务模块,然后通过.NET WebAPI暴露HTTP接口,可能是一个自然的集成方式。例如,每个微服务对应一个ABP模块,内部实现领域逻辑,并通过WebAPI对外提供服务。此外,ABP vNext提供了基础设施支持,如依赖注入、身份认证、分布式事件总线等,这些都可以简化微服务架构中的常见问题处理。 在集成步骤方面,可能需要首先创建ABP vNext模块化应用,配置各个服务模块,设置数据库连接(如引用中提到的ABPMicServie.OrderService.HttpApi.Host和DbMigrator项目),然后通过WebAPI项目暴露接口。同时,需要考虑服务发现、API网关、分布式事务等问题,ABP vNext是否有现成的解决方案或需要结合其他工具(如Consul、Ocelot等)。 使用场景方面,ABP vNext适合需要快速开发、模块化程度高、需要企业级功能(如多租户、权限管理)的微服务项目。如果团队已经熟悉ABP框架,可以大幅提升开发效率;而对于简单的微服务,可能直接使用.NET WebAPI更为轻量。 可能还需要考虑ABP vNext的微服务相关模块,比如分布式事件总线、跨服务通信机制等,以及如何与容器化部署(Docker、Kubernetes)结合,这些在用户的问题中没有提到,但可能是集成时需要注意的部分。 现在,我需要将这些思考整理成一个结构化的回答,分点说明关系、集成方式、使用场景及注意事项,并确保引用提供的资料中的例子,比如安装依赖包和数据库配置。同时,生成相关的问题,帮助用户进一步探索。</think>### .NET WebAPI 微服务架构与 ABP vNext 的集成分析 #### 一、框架定位与互补关系 1. **.NET WebAPI** 是构建 RESTful 服务的核心框架,提供轻量级 HTTP 通信能力,适合实现微服务架构中单个服务的 API 层[^1]。其核心优势在于灵活性和标准化,可直接通过控制器(Controller)定义接口逻辑。 2. **ABP vNext** 是**企业级应用开发框架**,提供模块化设计、依赖注入、身份认证、多租户等基础设施。通过预置模块(如 `Volo.Abp.AspNetCore.Mvc`)可直接集成 ASP.NET Core,并支持自动化的数据库迁移(如 `DbMigrator` 项目管理多数据库)[^2]。 3. **关系总结** ABP vNext 可作为微服务的**基础设施层**,而 .NET WebAPI 提供**通信层实现**。两者结合时,ABP vNext 负责领域逻辑与通用能力,WebAPI 负责对外暴露服务接口。 --- #### 二、集成步骤与关键配置 1. **创建 ABP 微服务模块** - 安装依赖包:`Volo.Abp.AspNetCore.Mvc`(Web 支持)、`Volo.Abp.Autofac`(依赖注入)[^1] - 定义领域层(如订单服务 `OrderService`),通过 `[DependsOn]` 声明模块依赖。 2. **配置独立数据库** - 每个微服务使用独立数据库(如 `OrderService` 数据库),在 `appsettings.json` 中配置连接字符串[^2]: ```json "ConnectionStrings": { "OrderService": "Server=...;Database=OrderService;..." } ``` 3. **暴露 WebAPI 接口** - 在 `HttpApi.Host` 项目中添加控制器,继承 `AbpController`,直接调用应用服务: ```csharp public class OrderController : AbpController { private readonly IOrderAppService _orderAppService; public OrderController(IOrderAppService orderAppService) { _orderAppService = orderAppService; } [HttpGet] public async Task<List<OrderDto>> GetOrdersAsync() { return await _orderAppService.GetListAsync(); } } ``` 4. **服务间通信** - 使用 ABP 的**分布式事件总线**或集成 gRPC/HTTP 客户端,实现跨服务调用。 --- #### 三、典型使用场景 1. **企业级复杂系统** 需多租户、细粒度权限控制时,ABP vNext 的预置功能可减少重复开发。 2. **模块化微服务架构** 每个业务模块(如订单、支付)作为独立 ABP 模块,通过 WebAPI 提供标准化接口。 3. **快速原型开发** ABP CLI 生成代码结构,结合 Swagger 自动生成 API 文档,提升初期开发效率。 --- #### 四、注意事项 1. **性能权衡** ABP 的抽象层可能引入额外开销,对高性能场景需评估模块化带来的代价。 2. **技术耦合** 深度依赖 ABP 框架可能导致迁移成本,若需替换为其他微服务框架(如 Steeltoe),需提前设计解耦方案。 3. **基础设施依赖** 若需服务发现、API 网关等能力,需结合其他组件(如 Consul、Ocelot)或使用 ABP 商业版扩展。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ChaITSimpleLove

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值