马上国庆了,dotNative 预祝大家假期愉快,Happy National Day!
本文将介绍在 .net6
平台的 asp.net core webapi
框架中,如何使用 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
项目模板,点击【下一步】。
2、配置新建项目,输入项目名称 ASP.NET Core Web API
,继续点击【下一步】。
3、其他信息,这里只勾选【使用控制器】,然后点击【创建】。
经过上面步骤, 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
NuGet\Install-Package Volo.Abp.Swashbuckle -Version 6.0.0-rc.5
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
)的编程风格,操作步骤如下:
- 首先在
Program.cs
文件中新建一个class
类,名称为DemoWebApiModule
,并继承AbpModule
。 - 其次通过
DependsOn
特性来定义模块的依赖关系。 - 然后在
Program.cs
文件中通过AddApplication
注入自定义模块类。 - 最后在
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
这里安装 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
,插件机制),遵循开闭原则,只需添加 NuGet
包 Volo.Abp.Modularity.PlugIns
,便可实现 Module
模块的插件式加载,只需如下两不操作即可:
- 在项目根文件添加一个文件夹,如:
DemoAbpPulgins
(文件夹命名尽量见名知意)。 - 固定模式,在
AddApplication
或AddApplicationAsync
的options
中添加如上代码(注释部分)。 - 将模块化组件编译好的
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 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
】执行业务 Service
的 DI
注册并调用,运行如下所示:
1、curl
命令访问:
curl -X 'GET' \
'http://localhost:5165/WeatherForecast' \
-H 'accept: text/plain' \
-H 'RequestVerificationToken: CfDJ8ODjDXixt1tDuxO1cuT_L2z6DM3lUqtnRF0xKJPwuuLU0SKbwulLhV35ySmCqoC3CuQksJoqHnyzRQw5ZT-sE5Q20mC3vFONoLQ2Tx5Y1Y9qvQ67mtBCqNnSPtCePtukjn1Ocd6ocr-0E2fJVLroRYU' \
-H 'X-Requested-With: XMLHttpRequest'
2、浏览器输入 url
访问:
http://localhost:5165/WeatherForecast
SwaggerUI 权限配置
在生产环境中,考虑安全性,通常需要 Swagger 接入 OAuth2 认证。
ABP vNext
集成了 Identity Server
来做权限认证,需要使用 AddAbpSwaggerGenWithOAuth
扩展,在 Module
的 ConfigureServices
方法中,使用 OAuth issuer
和 scopes
来配置 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 webapi
的 MiniAPI
模式开始,遵循 ABP vNext Web
框架的 Module
模块化思想并学会使用,再到 Program.cs & Startup.cs
模式的改造,使得项目工程化体验更佳、目录层级结构更清晰,再逐步引入其他模块(Module
)依赖,并通过 DependsOn
特性显示声明。
遵循 ABP vNext
框架的规则,在代码层面更加直观的体现 Module 模块化开发思想
。当依赖模块多,需要频繁的调整代码模块的依赖, 此时 ABP vNext
框架提供了 PlugIns
插件化机制,实现 ABP vNext
模块 插件式 的动态加载,可热插拔,符合符合 开闭原则
。