01手动搭建基本的ABP框架
手动搭建基本的ABP框架
ABP是用于创建现代Web应用程序的完整架构和强大的基础设施! 遵循最佳实践和约定,为你提供SOLID开发经验。
创建项目
创建类库:
- Domian
- Domain.Shared
- Application
- Application.Contracts
- EntityFrameworkCore
- HttpApi
- HttpApi.Client
创建ASP.NET Core Web 应用 HttpApi.Host
,作为后端接口主机。
Domain.Shared
领域共享层,该层存放领域层的常量、枚举、值对象、本土化配置文件和其他对象,这些对象实际是领域层的一部分,但是解决方案中所有的层/项目中都会使用到。
- 该项目不依赖解决中的其他项目,其他项目直接或间接引用该项目。
需要添加的Nugget包:
Volo.Abp.Localization
Volo 本地化模块,使应用程序支持全球化
创建文件夹Localization/MyLocalization
,在该文件夹下放语言配置配置文件(如:zh-Hans.json
)。
zh-Hans.json
配置如下:
{ "culture": "zh-Hans", "texts": { "LongWelcomeMessage": "欢迎使用Abp框架", // 一些其它配置 } }
在文件夹Localization
文件夹下新增类MyLocalizationResource.cs
,添加以下代码:
namespace Domain.Shared.Localization { [LocalizationResourceName("MyLocalization")] public class MyLocalizationResource { } }
在根目录下新增类DomainSharedModule.cs
,添加以下代码:
namespace Domain.Shared { // 添加依赖 本地化模组 [DependsOn( typeof(AbpLocalizationModule) )] public class DomainSharedModule : AbpModule // 必须继承AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { // 配置虚拟文件系统 配置全球化资源文件必须配置该选项 Configure<AbpVirtualFileSystemOptions>(options => { options.FileSets.AddEmbedded<DomainSharedModule>(); }); // 配置全球化资源文件 Configure<AbpLocalizationOptions>(options => { options.Resources.Add<MyLocalizationResource>("zh-Hans") .AddVirtualJson("/Localization/MyLocalization"); options.DefaultResourceType = typeof(MyLocalizationResource); }); Configure<AbpExceptionLocalizationOptions>(options => { options.MapCodeNamespace("MyLocalization", typeof(MyLocalizationResource)); }); base.ConfigureServices(context); } } }
Domian
领域层,在该层实现系统核心业务逻辑,该层主要包含实体、集合跟、领域服务、值类型、仓储接口和解决方案的其他领域对象
- 依赖
Domain.Shared
,项目中会用到它的一些常量、枚举、值对象和其他对象。
需要添加的Nugget包:
Volo.Abp.Ddd.Domain
领域驱动模块
添加类DomainModule.cs
,添加以下代码:
namespace Domain { // 依赖领域驱动模块 // 依赖领域共享模块 [DependsOn( typeof(AbpDddDomainModule), typeof(DomainSharedModule) )] public class DomainModule:AbpModule { } }
Application.Contracts
应用约定层,该层存放应用服务接口、数据传输对象、应用层常量和应用层提供程序。他用于分离应用层的接口和实现。这种方式可以将接口项目做为约定包共享给客户端。
- 依赖
Domain.Shared
,因为它可能会在应用接口和DTO中使用常量、枚举和其他的共享对象。
需要添加的Nugget包:
Volo.Abp.Ddd.Application.Contracts
应用层约定模块
添加类ApplicationContractsModule.cs
,添加以下代码:
namespace Application.Contracts { // 依赖应用层约定模块 // 依赖领域共享模块 [DependsOn( typeof(AbpDddApplicationContractsModule), typeof(DomainSharedModule) )] public class ApplicationContractsModule:AbpModule { } }
Application
应用层,该层实现系统应用业务逻辑,实现服务接口。
- 依赖
Application.Contracts
,需要实现服务接口与使用DTO。 - 依赖
Domain
需要使用领域对象(实体、仓储接口等)执行应用程序逻辑。
需要添加Nugget包:
Volo.Abp.Ddd.Application
应用层模块Volo.Abp.AutoMapper
自动映射模块
添加类ApplicationAutoMapperProfile.cs
,应用层自动映射配置类,添加以下代码:
namespace Application { public class ApplicationAutoMapperProfile: Profile { public ApplicationAutoMapperProfile() { // 配置自动映射 //CreateMap<T1, T2>(); } } }
添加类ApplicationModule.cs
,添加以下代码:
namespace Application { // 依赖自动配置模块 // 依赖领域驱动应用层模块 // 依赖领域模块 // 依赖应用层约定模块 [DependsOn( typeof(AbpAutoMapperModule), typeof(AbpDddApplicationModule), typeof(DomainModule), typeof(ApplicationContractsModule) )] public class ApplicationModule:AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { base.ConfigureServices(context); // 配置自动映射 Configure<AbpAutoMapperOptions>(options => { options.AddMaps<ApplicationModule>(); }); } } }
EntityFrameworkCore
数据库层,定义了DbContext
并实现Domain
项目中定义的仓储接口。
- 依赖
Domain
,需要引用实体和实现仓储接口。
需要添加Nugget包:
Volo.Abp.EntityFrameworkCore.SqlServer
SqlServer数据库模块
添加类EntityFrameworkCoreModule.cs
,添加以下代码
namespace EntityFrameworkCore { // 依赖SqlServer数据库模块 [DependsOn( typeof(AbpEntityFrameworkCoreSqlServerModule), typeof(DomainModule) )] public class EntityFrameworkCoreModule:AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { base.ConfigureServices(context); // 配置使用 SqlServer // Configure<AbpDbContextOptions>(options => // { // options.UseSqlServer(); // }); } } }
HttpApi
用于定义API控制器。
大多数情况下,不需要手动定义API控制器,因为ABP的动态API功能会根据应用层自动创建API控制器。但是,如果你需要编写API控制器,则可以在该层中定义。
- 依赖
Application.Contracts
项目,因为它需要注入应用服务接口
需要添加Nugget包:
Volo.Abp.AspNetCore.Mvc
AspNetCore MVC模块
添加类HttpApiModule.cs
,添加以下代码
namespace HttpApi { // 依赖MVC模块 // 依赖应用约定模块 [DependsOn( typeof(AbpAspNetCoreMvcModule), typeof(ApplicationContractsModule) )] public class HttpApiModule:AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { ConfigureLocalization(); base.ConfigureServices(context); } private void ConfigureLocalization() { // 配置本地化资源库 Configure<AbpLocalizationOptions>(options => { options.Resources .Get<MyLocalizationResource>() .AddBaseTypes(typeof(AbpUiResource)); }); } } }
HttpApi.Client
定义C#客户端代理,使用解决方案的HttpAPI项目。可以将该项目共享给第三方客户端,使其轻松的在DotNet应用程序中使用你的HttpAPI(其他类型应用程序可以手动或使用其平台的工具来使用你的API)。
ABP有动态C#API客户端功能,所以大多数情况下你不需要手动创建C#客户端代理。
- 依赖
Application.Contracts
,需要使用应用服务接口和DTO
需要添加Nugget包:
Volo.Abp.Http.Client
添加类HttpApiClientModule.cs
,添加以下代码
namespace HttpApi.Client { [DependsOn( typeof(AbpHttpClientModule), typeof(ApplicationContractsModule) )] public class HttpApiClientModule:AbpModule { public const string RemoteServiceName = "Default"; public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddHttpClientProxies( typeof(ApplicationContractsModule).Assembly, RemoteServiceName ); Configure<AbpVirtualFileSystemOptions>(options => { options.FileSets.AddEmbedded<HttpApiClientModule>(); }); } } }
HttpApi.Host
HttpAPI主机层,她有自己的appsettings.json
文件(数据库链接字符串等其他配置)
- 依赖
HttpApi
由于没有使用分层模式(没有选择--tiered
选项),还同时依赖:
Application
EntityFrameworkCore
需要添加Nugget包:
Volo.Abp.Autofac
依赖注入模块Volo.Abp.Swashbuckle
添加类HttpApiHostModule.cs
,添加以下代码:
namespace HttpApi.Host { [DependsOn( typeof(HttpApiModule), typeof(AbpAutofacModule), typeof(ApplicationModule), typeof(EntityFrameworkCoreModule), typeof(AbpSwashbuckleModule) )] public class HttpApiHostModule:AbpModule { public override void PreConfigureServices(ServiceConfigurationContext context) { } public override void ConfigureServices(ServiceConfigurationContext context) { var configuration = context.Services.GetConfiguration(); var hostingEnvironment = context.Services.GetHostingEnvironment(); ConfigureUrls(configuration); ConfigureVirtualFileSystem(context); ConfigureConventionalControllers(); ConfigureLocalization(); ConfigureCors(context, configuration); ConfigureSwaggerServices(context, configuration); } /// <summary> /// 配置URL /// </summary> /// <param name="configuration"></param> private void ConfigureUrls(IConfiguration configuration) { // 前端Ui地址配置 // Configure<AppUrlOptions>(options => // { // options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"]; // options.RedirectAllowedUrls.AddRange(configuration["App:RedirectAllowedUrls"].Split(',')); // options.Applications["Angular"].RootUrl = configuration["App:ClientUrl"]; // }); } /// <summary> /// 配置 虚拟文件系统 /// </summary> /// <param name="context"></param> private void ConfigureVirtualFileSystem(ServiceConfigurationContext context) { var hostingEnvironment = context.Services.GetHostingEnvironment(); if (hostingEnvironment.IsDevelopment()) { Configure<AbpVirtualFileSystemOptions>(options => { options.FileSets.ReplaceEmbeddedByPhysical<DomainSharedModule>( Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}Domain.Shared")); options.FileSets.ReplaceEmbeddedByPhysical<DomainModule>( Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}Domain")); options.FileSets.ReplaceEmbeddedByPhysical<ApplicationContractsModule>( Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}Application.Contracts")); options.FileSets.ReplaceEmbeddedByPhysical<ApplicationModule>( Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}Application")); }); } } /// <summary> /// 配置 传统的控制器 /// </summary> private void ConfigureConventionalControllers() { Configure<AbpAspNetCoreMvcOptions>(options => { options.ConventionalControllers.Create(typeof(ApplicationModule).Assembly); }); } private static void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration) { // swagger配置及授权地址配置 context.Services.AddAbpSwaggerGenWithOAuth( configuration["AuthServer:Authority"], new Dictionary<string, string> { {"StudyAcme", "StudyAcme API"} }, options => { options.SwaggerDoc("v1", new OpenApiInfo { Title = "StudyAcme API", Version = "v1" }); options.DocInclusionPredicate((docName, description) => true); options.CustomSchemaIds(type => type.FullName); }); } /// <summary> /// 配置本地化 /// </summary> private void ConfigureLocalization() { Configure<AbpLocalizationOptions>(options => { //options.Languages.Add(new LanguageInfo("ar", "ar", "العربية")); //options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); //options.Languages.Add(new LanguageInfo("en", "en", "English")); //options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English (UK)")); //options.Languages.Add(new LanguageInfo("fi", "fi", "Finnish")); //options.Languages.Add(new LanguageInfo("fr", "fr", "Français")); //options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi", "in")); //options.Languages.Add(new LanguageInfo("is", "is", "Icelandic", "is")); //options.Languages.Add(new LanguageInfo("it", "it", "Italiano", "it")); //options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar")); //options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português")); //options.Languages.Add(new LanguageInfo("ro-RO", "ro-RO", "Română")); //options.Languages.Add(new LanguageInfo("ru", "ru", "Русский")); //options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak")); //options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); //options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文")); //options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch", "de")); //options.Languages.Add(new LanguageInfo("es", "es", "Español", "es")); //options.Languages.Add(new LanguageInfo("el", "el", "Ελληνικά")); }); } /// <summary> /// 配置Cors /// <para> /// 配置跨域请求 /// </para> /// </summary> /// <param name="context"></param> /// <param name="configuration"></param> private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration) { context.Services.AddCors(options => { options.AddDefaultPolicy(builder => { builder // ajax跨域访问白名单,没有配置,注释掉 //.WithOrigins( // configuration["App:CorsOrigins"] // .Split(",", StringSplitOptions.RemoveEmptyEntries) // .Select(o => o.RemovePostFix("/")) // .ToArray() //) .WithAbpExposedHeaders() .SetIsOriginAllowedToAllowWildcardSubdomains() .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); }); }); } public override void OnApplicationInitialization(Volo.Abp.ApplicationInitializationContext context) { var app = context.GetApplicationBuilder(); var env = context.GetEnvironment(); if(env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseAbpRequestLocalization(); app.UseStaticFiles(); app.UseRouting(); app.UseCors(); app.UseAuthorization(); app.UseUnitOfWork(); app.UseAuthorization(); app.UseSwagger(); app.UseAbpSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "StudyAcme API"); var configuration = context.ServiceProvider.GetRequiredService<IConfiguration>(); c.OAuthClientId(configuration["AuthServer:SwaggerClientId"]); c.OAuthScopes("StudyAcme"); }); app.UseAuditing(); app.UseConfiguredEndpoints(); } } }
在Program.cs
类中添加代码:
await builder.AddApplicationAsync<HttpApiHostModule>();
Program.cs
完整代码:
using BlankAbp.HttpApi.Host; try { var builder = WebApplication.CreateBuilder(args); builder.Host.AddAppSettingsSecretsJson() .UseAutofac(); await builder.AddApplicationAsync<HttpApiHostModule>(); var app = builder.Build(); await app.InitializeApplicationAsync(); await app.RunAsync(); return 0; } catch (Exception ex) { if (ex is HostAbortedException) { throw; } return 1; } finally { }
appsettings.json
配置为:
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*", "AuthServer": { // swagger授权地址 "Authority": "https://localhost:7067", "RequireHttpsMetadata": "false", "SwaggerClientId": "BlankAbp_Swagger" } }
添加测试服务
在Application
项目中添加类ApplicationAppService
,并添加以下代码
/// <summary> /// 应用层服务基类 /// </summary> public abstract class ApplicationAppService:ApplicationService { protected ApplicationAppService() { // 配置本地资源 LocalizationResource = typeof(MyLocalizationResource); } }
在Application
项目中添加类TestService
,并添加以下代码
public class TestService: ApplicationAppService { private IStringLocalizer<MyLocalizationResource> _l; public TestService( IStringLocalizer<MyLocalizationResource> l) { _l = l; } public string GetTest() { return "test service"; } public string GetWellCome() { return _l["LongWelcomeMessage"].Value; } }
运行HttpApi.Host
可见以下API:
语言选择
使用/Abp/Languages/Switch?culture=zh-Hans&uiCulture=zh-Hans&returnUrl=/
接口进行语言切换,该接口会在Cookie中添加或更新 lpx_lang=ZH; .AspNetCore.Culture=c=zh-Hans|uic=zh-Hans
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)