diff --git a/aspnet-core/.gitignore b/aspnet-core/.gitignore
index a7eaf8aeb..662fca440 100644
--- a/aspnet-core/.gitignore
+++ b/aspnet-core/.gitignore
@@ -4,5 +4,4 @@ LocalNuget
**/*.csproj.user
nupkg
consoles
-templates
*.configs.cache
\ No newline at end of file
diff --git a/aspnet-core/templates/.gitignore b/aspnet-core/templates/.gitignore
new file mode 100644
index 000000000..d327b6024
--- /dev/null
+++ b/aspnet-core/templates/.gitignore
@@ -0,0 +1,9 @@
+.vs
+LocalNuget
+*.DotSettings.user
+**/*.csproj.user
+nupkg
+consoles
+*.configs.cache
+*.nupkg
+*.nuspec
\ No newline at end of file
diff --git a/aspnet-core/templates/content/.template.config/template.json b/aspnet-core/templates/content/.template.config/template.json
new file mode 100644
index 000000000..8ba44d248
--- /dev/null
+++ b/aspnet-core/templates/content/.template.config/template.json
@@ -0,0 +1,99 @@
+{
+ "$schema": "http://json.schemastore.org/template",
+ "author": "colin.in@foxmail.com",
+ "classifications": [ "micro", "webapi", "cloud" ],
+ "name": "LINGYUN.Abp.MicroService",
+ "identity": "LINGYUN.Abp.MicroService", //模板唯一标识
+ "groupIdentity": "LINGYUN.Abp.Application",
+ "shortName": "lam",
+ "tags": {
+ "language": "C#",
+ "type": "project"
+ },
+ "sourceName": "ProjectName",
+ "preferNameDirectory": true,
+ "symbols": {
+ "AuthenticationScheme": {
+ "type": "parameter",
+ "description": "Authentication Scheme",
+ "datatype": "choice",
+ "defaultValue": "IdentityServer4",
+ "isRequired": false,
+ "choices": [
+ {
+ "choice": "IdentityServer4",
+ "description": "IdentityServer4"
+ },
+ {
+ "choice": "OpenIddict",
+ "description": "OpenIddict"
+ }
+ ]
+ },
+ "DatabaseManagement": {
+ "type": "parameter",
+ "description": "Database Management",
+ "dataType": "choice",
+ "defaultValue": "MySQL",
+ "isRequired": false,
+ "choices": [
+ {
+ "choice": "SqlServer",
+ "description": "Sql Server"
+ },
+ {
+ "choice": "MySQL",
+ "description": "My SQL"
+ },
+ {
+ "choice": "Sqlite",
+ "description": "Sqlite"
+ },
+ {
+ "choice": "Oracle",
+ "description": "Oracle"
+ },
+ {
+ "choice": "OracleDevart",
+ "description": "Oracle Devart Driver"
+ },
+ {
+ "choice": "PostgreSql",
+ "description": "Postgre Sql"
+ }
+ ]
+ },
+ "SqlServer": {
+ "type": "computed",
+ "value": "(DatabaseManagement == \"SqlServer\")"
+ },
+ "MySQL": {
+ "type": "computed",
+ "value": "(DatabaseManagement == \"MySQL\")"
+ },
+ "Sqlite": {
+ "type": "computed",
+ "value": "(DatabaseManagement == \"Sqlite\")"
+ },
+ "Oracle": {
+ "type": "computed",
+ "value": "(DatabaseManagement == \"Oracle\")"
+ },
+ "OracleDevart": {
+ "type": "computed",
+ "value": "(DatabaseManagement == \"Oracle.Devart\")"
+ },
+ "PostgreSql": {
+ "type": "computed",
+ "value": "(DatabaseManagement == \"PostgreSql\")"
+ },
+ "IdentityServer4": {
+ "type": "computed",
+ "value": "(AuthenticationScheme == \"IdentityServer4\")"
+ },
+ "OpenIddict": {
+ "type": "computed",
+ "value": "(AuthenticationScheme == \"OpenIddict\")"
+ }
+ }
+}
\ No newline at end of file
diff --git a/aspnet-core/templates/content/Directory.Build.props b/aspnet-core/templates/content/Directory.Build.props
new file mode 100644
index 000000000..39b252a30
--- /dev/null
+++ b/aspnet-core/templates/content/Directory.Build.props
@@ -0,0 +1,33 @@
+
+
+ 1.6.9
+ 7.0.2
+ 7.0.2
+ 7.0.3
+ 1.10.0
+ 1.0.2
+ 1.0.0-rc8
+ 1.3.1
+ 1.0.0-rc8
+ 1.0.0-rc8
+ 1.0.0-beta2
+ 2.10.0
+ 1.5.0
+ 5.0.0
+ 2.2.0
+ 2.0.0
+ 2.0.1
+ 3.1.0
+ 3.0.1
+ 3.4.0
+ 4.0.0
+ 8.4.1
+ 5.0.0
+ 6.1.5
+ 7.0.*
+ 7.0.2
+ 2.4.1
+ 3.0.2
+ 4.2.1
+
+
\ No newline at end of file
diff --git a/aspnet-core/templates/content/common.props b/aspnet-core/templates/content/common.props
new file mode 100644
index 000000000..413528f92
--- /dev/null
+++ b/aspnet-core/templates/content/common.props
@@ -0,0 +1,36 @@
+
+
+ latest
+ 7.0.2
+ colin
+ $(NoWarn);CS1591;CS0436
+ https://github.com/colinin/abp-next-admin
+ MIT
+ git
+ https://github.com/colinin/abp-next-admin
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(SolutionDir)LocalNuget
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/templates/content/configureawait.props b/aspnet-core/templates/content/configureawait.props
new file mode 100644
index 000000000..92f22f85f
--- /dev/null
+++ b/aspnet-core/templates/content/configureawait.props
@@ -0,0 +1,9 @@
+
+
+
+
+ All
+ runtime; build; native; contentfiles; analyzers
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.DbMigrator/DbMigratorHostedService.cs b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.DbMigrator/DbMigratorHostedService.cs
new file mode 100644
index 000000000..b61e0dc04
--- /dev/null
+++ b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.DbMigrator/DbMigratorHostedService.cs
@@ -0,0 +1,49 @@
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using PackageName.CompanyName.ProjectName.DbMigrator.EntityFrameworkCore;
+using Serilog;
+using Volo.Abp;
+
+namespace PackageName.CompanyName.ProjectName.DbMigrator;
+
+public class DbMigratorHostedService : IHostedService
+{
+ private readonly IHostApplicationLifetime _hostApplicationLifetime;
+ private readonly IConfiguration _configuration;
+
+ public DbMigratorHostedService(
+ IHostApplicationLifetime hostApplicationLifetime,
+ IConfiguration configuration)
+ {
+ _hostApplicationLifetime = hostApplicationLifetime;
+ _configuration = configuration;
+ }
+
+ public async Task StartAsync(CancellationToken cancellationToken)
+ {
+ using var application = await AbpApplicationFactory
+ .CreateAsync(options =>
+ {
+ options.Services.ReplaceConfiguration(_configuration);
+ options.UseAutofac();
+ options.Services.AddLogging(c => c.AddSerilog());
+ });
+ await application.InitializeAsync();
+
+ await application
+ .ServiceProvider
+ .GetRequiredService()
+ .MigrateAsync();
+
+ await application.ShutdownAsync();
+
+ _hostApplicationLifetime.StopApplication();
+ }
+
+ public Task StopAsync(CancellationToken cancellationToken)
+ {
+ return Task.CompletedTask;
+ }
+}
+
diff --git a/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.DbMigrator/FodyWeavers.xml b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.DbMigrator/FodyWeavers.xml
new file mode 100644
index 000000000..1715698cc
--- /dev/null
+++ b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.DbMigrator/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.DbMigrator/FodyWeavers.xsd b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.DbMigrator/FodyWeavers.xsd
new file mode 100644
index 000000000..11da52550
--- /dev/null
+++ b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.DbMigrator/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.DbMigrator/PackageName.CompanyName.ProjectName.DbMigrator.csproj b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.DbMigrator/PackageName.CompanyName.ProjectName.DbMigrator.csproj
new file mode 100644
index 000000000..5f46df834
--- /dev/null
+++ b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.DbMigrator/PackageName.CompanyName.ProjectName.DbMigrator.csproj
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+ Exe
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.DbMigrator/PackageNameCompanyNameProjectNameDbMigratorModule.cs b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.DbMigrator/PackageNameCompanyNameProjectNameDbMigratorModule.cs
new file mode 100644
index 000000000..18b109f71
--- /dev/null
+++ b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.DbMigrator/PackageNameCompanyNameProjectNameDbMigratorModule.cs
@@ -0,0 +1,13 @@
+using PackageName.CompanyName.ProjectName.EntityFrameworkCore;
+using Volo.Abp.Autofac;
+using Volo.Abp.Modularity;
+
+namespace PackageName.CompanyName.ProjectName.DbMigrator;
+
+[DependsOn(
+ typeof(AbpAutofacModule),
+ typeof(ProjectNameEntityFrameworkCoreModule)
+ )]
+public class PackageNameCompanyNameProjectNameDbMigratorModule : AbpModule
+{
+}
diff --git a/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.DbMigrator/Program.cs b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.DbMigrator/Program.cs
new file mode 100644
index 000000000..8f6151dfe
--- /dev/null
+++ b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.DbMigrator/Program.cs
@@ -0,0 +1,40 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using Serilog;
+using Serilog.Events;
+
+namespace PackageName.CompanyName.ProjectName.DbMigrator;
+
+public class Program
+{
+ public async static Task Main(string[] args)
+ {
+ Log.Logger = new LoggerConfiguration()
+ .MinimumLevel.Information()
+ .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
+ .MinimumLevel.Override("Volo.Abp", LogEventLevel.Warning)
+#if DEBUG
+ .MinimumLevel.Override("PackageName.CompanyName.ProjectName", LogEventLevel.Debug)
+#else
+ .MinimumLevel.Override("PackageName.CompanyName.ProjectName", LogEventLevel.Information)
+#endif
+ .Enrich.FromLogContext()
+ .WriteTo.Async(c => c.File("Logs/logs.txt"))
+ .WriteTo.Async(c => c.Console())
+ .CreateLogger();
+
+ await CreateHostBuilder(args).RunConsoleAsync();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args)
+ {
+ return Host.CreateDefaultBuilder(args)
+ .AddAppSettingsSecretsJson()
+ .ConfigureLogging((context, logging) => logging.ClearProviders())
+ .ConfigureServices((hostContext, services) =>
+ {
+ services.AddHostedService();
+ });
+ }
+}
diff --git a/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.DbMigrator/appsettings.Development.json b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.DbMigrator/appsettings.Development.json
new file mode 100644
index 000000000..93f33118f
--- /dev/null
+++ b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.DbMigrator/appsettings.Development.json
@@ -0,0 +1,145 @@
+{
+ "AgileConfig": {
+ "IsEnabled": false,
+ "env": "DEV",
+ "appId": "PackageName.CompanyName.ProjectName",
+ "secret": "1q2w3E*",
+ "nodes": "http://127.0.0.1:15000",
+ "name": "PackageName.CompanyName.ProjectName",
+ "tag": "PackageName.CompanyName.ProjectName"
+ },
+ "Auditing": {
+ "AllEntitiesSelector": true
+ },
+ "DistributedCache": {
+ "HideErrors": true,
+ "KeyPrefix": "LINGYUN.Abp.Application",
+ "GlobalCacheEntryOptions": {
+ "SlidingExpiration": "30:00:00",
+ "AbsoluteExpirationRelativeToNow": "60:00:00"
+ }
+ },
+ "ConnectionStrings": {
+ "Default": "Server=127.0.0.1;Database=ProjectName;User Id=root;Password=123456",
+ "ProjectName": "Server=127.0.0.1;Database=ProjectName;User Id=root;Password=123456",
+ "AbpSaas": "Server=127.0.0.1;Database=ProjectName;User Id=root;Password=123456",
+ "AbpFeatureManagement": "Server=127.0.0.1;Database=ProjectName;User Id=root;Password=123456",
+ "AbpPermissionManagement": "Server=127.0.0.1;Database=ProjectName;User Id=root;Password=123456",
+ "AbpSettingManagement": "Server=127.0.0.1;Database=ProjectName;User Id=root;Password=123456",
+ "AbpLocalizationManagement": "Server=127.0.0.1;Database=ProjectName;User Id=root;Password=123456",
+ "AbpTextTemplating": "Server=127.0.0.1;Database=ProjectName;User Id=root;Password=123456"
+ },
+ "DistributedLock": {
+ "IsEnabled": true,
+ "Redis": {
+ "Configuration": "127.0.0.1,defaultDatabase=15"
+ }
+ },
+ "OpenTelemetry": {
+ "IsEnabled": true,
+ "ZipKin": {
+ "Endpoint": "http://127.0.0.1:9411/api/v2/spans"
+ }
+ },
+ "RemoteServices": {},
+ "IdentityClients": {
+ "InternalServiceClient": {
+ "Authority": "http://127.0.0.1:44385",
+ "RequireHttps": false,
+ "GrantType": "client_credentials",
+ "Scope": "lingyun-abp-application",
+ "ClientId": "InternalServiceClient",
+ "ClientSecret": "1q2w3E*"
+ }
+ },
+ "CAP": {
+ "EventBus": {
+ "DefaultGroupName": "ProjectName",
+ "GroupNamePrefix": "Dev",
+ "Version": "v1",
+ "FailedRetryInterval": 300,
+ "FailedRetryCount": 10
+ },
+ "MySql": {
+ "TableNamePrefix": "ProjectName_cap",
+ "ConnectionString": "Server=127.0.0.1;Database=ProjectName;User Id=root;Password=123456"
+ },
+ "SqlServer": {
+ "TableNamePrefix": "ProjectName_cap",
+ "ConnectionString": "Server=127.0.0.1;Database=ProjectName;User Id=root;Password=123456"
+ },
+ "Sqlite": {
+ "TableNamePrefix": "ProjectName_cap",
+ "ConnectionString": "Data Source=./cap.db"
+ },
+ "Oracle": {
+ "TableNamePrefix": "ProjectName_cap",
+ "ConnectionString": "Data Source=ProjectName;Integrated Security=yes;"
+ },
+ "PostgreSql": {
+ "TableNamePrefix": "ProjectName_cap",
+ "ConnectionString": "Host=localhost;Port=5432;Database=ProjectName;User ID=root;Password=123456;"
+ },
+ "RabbitMQ": {
+ "HostName": "127.0.0.1",
+ "Port": 5672,
+ "UserName": "admin",
+ "Password": "123456",
+ "ExchangeName": "LINGYUN.Abp.Application",
+ "VirtualHost": "/"
+ }
+ },
+ "Redis": {
+ "Configuration": "127.0.0.1,defaultDatabase=10",
+ "InstanceName": "LINGYUN.Abp.Application"
+ },
+ "AuthServer": {
+ "Authority": "http://127.0.0.1:44385/",
+ "ApiName": "lingyun-abp-application",
+ "SwaggerClientId": "InternalServiceClient",
+ "SwaggerClientSecret": "1q2w3E*"
+ },
+ "Logging": {
+ "Serilog": {
+ "Elasticsearch": {
+ "IndexFormat": "abp.dev.logging-{0:yyyy.MM.dd}"
+ }
+ }
+ },
+ "AuditLogging": {
+ "Elasticsearch": {
+ "IndexPrefix": "abp.dev.auditing"
+ }
+ },
+ "Elasticsearch": {
+ "NodeUris": "http://127.0.0.1:9200"
+ },
+ "Serilog": {
+ "MinimumLevel": {
+ "Default": "Debug",
+ "Override": {
+ "System": "Warning",
+ "Microsoft": "Warning",
+ "DotNetCore": "Debug"
+ }
+ },
+ "WriteTo": [
+ {
+ "Name": "Console",
+ "Args": {
+ "restrictedToMinimumLevel": "Debug",
+ "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
+ }
+ },
+ {
+ "Name": "Elasticsearch",
+ "Args": {
+ "nodeUris": "http://127.0.0.1:9200",
+ "indexFormat": "abp.dev.logging-{0:yyyy.MM.dd}",
+ "autoRegisterTemplate": true,
+ "autoRegisterTemplateVersion": "ESv7"
+ }
+ }
+ ]
+ }
+}
diff --git a/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.DbMigrator/appsettings.json b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.DbMigrator/appsettings.json
new file mode 100644
index 000000000..d3d63c269
--- /dev/null
+++ b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.DbMigrator/appsettings.json
@@ -0,0 +1,80 @@
+{
+ "StringEncryption": {
+ "DefaultPassPhrase": "s46c5q55nxpeS8Ra",
+ "InitVectorBytes": "s83ng0abvd02js84",
+ "DefaultSalt": "sf&5)s3#"
+ },
+ "AllowedHosts": "*",
+ "Serilog": {
+ "MinimumLevel": {
+ "Default": "Debug",
+ "Override": {
+ "Microsoft.EntityFrameworkCore": "Debug",
+ "System": "Information",
+ "Microsoft": "Information"
+ }
+ },
+ "Enrich": [ "FromLogContext", "WithProcessId", "WithThreadId", "WithEnvironmentName", "WithMachineName", "WithApplicationName", "WithUniqueId" ],
+ "WriteTo": [
+ {
+ "Name": "Console",
+ "Args": {
+ "initialMinimumLevel": "Verbose",
+ "standardErrorFromLevel": "Verbose",
+ "restrictedToMinimumLevel": "Verbose",
+ "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
+ }
+ },
+ {
+ "Name": "File",
+ "Args": {
+ "path": "Logs/Debug-.log",
+ "restrictedToMinimumLevel": "Debug",
+ "rollingInterval": "Day",
+ "fileSizeLimitBytes": 5242880,
+ "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
+ }
+ },
+ {
+ "Name": "File",
+ "Args": {
+ "path": "Logs/Info-.log",
+ "restrictedToMinimumLevel": "Information",
+ "rollingInterval": "Day",
+ "fileSizeLimitBytes": 5242880,
+ "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
+ }
+ },
+ {
+ "Name": "File",
+ "Args": {
+ "path": "Logs/Warn-.log",
+ "restrictedToMinimumLevel": "Warning",
+ "rollingInterval": "Day",
+ "fileSizeLimitBytes": 5242880,
+ "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
+ }
+ },
+ {
+ "Name": "File",
+ "Args": {
+ "path": "Logs/Error-.log",
+ "restrictedToMinimumLevel": "Error",
+ "rollingInterval": "Day",
+ "fileSizeLimitBytes": 5242880,
+ "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
+ }
+ },
+ {
+ "Name": "File",
+ "Args": {
+ "path": "Logs/Fatal-.log",
+ "restrictedToMinimumLevel": "Fatal",
+ "rollingInterval": "Day",
+ "fileSizeLimitBytes": 5242880,
+ "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
+ }
+ }
+ ]
+ }
+}
diff --git a/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Controllers/HomeController.cs b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Controllers/HomeController.cs
new file mode 100644
index 000000000..f38f64d84
--- /dev/null
+++ b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Controllers/HomeController.cs
@@ -0,0 +1,12 @@
+using Microsoft.AspNetCore.Mvc;
+using Volo.Abp.AspNetCore.Mvc;
+
+namespace PackageName.CompanyName.ProjectName.Controllers;
+
+public class HomeController : AbpController
+{
+ public IActionResult Index()
+ {
+ return Redirect("/swagger/index.html");
+ }
+}
diff --git a/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Dockerfile b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Dockerfile
new file mode 100644
index 000000000..dfd0d25d1
--- /dev/null
+++ b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Dockerfile
@@ -0,0 +1,20 @@
+FROM mcr.microsoft.com/dotnet/aspnet:7.0
+LABEL maintainer="colin.in@foxmail.com"
+WORKDIR /app
+
+COPY . /app
+
+## 设置上海时区.(Set your own time zone.)
+#ENV TZ=Asia/Shanghai
+#RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo '$TZ' > /etc/timezone
+
+## 解决连接SqlServer TLS版本过高问题.(The version of connection SqlServer TLS is too high.)
+## 如果数据提供者是SqlServer,需要手动取消注释.(If the data provider is SqlServer, you need to manually uncomment it.)
+##RUN sed -i 's/TLSv1.2/TLSv1.0/g' /etc/ssl/openssl.cnf
+##RUN sed -i 's/TLSv1.2/TLSv1.0/g' /usr/lib/ssl/openssl.cnf
+
+EXPOSE 80/tcp
+VOLUME [ "./app/Logs" ]
+VOLUME [ "./app/Modules" ]
+
+ENTRYPOINT ["dotnet", "PackageName.CompanyName.ProjectName.HttpApi.Host.dll"]
diff --git a/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/EventBus/Handlers/TenantSynchronizer.cs b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/EventBus/Handlers/TenantSynchronizer.cs
new file mode 100644
index 000000000..1c6f1aae7
--- /dev/null
+++ b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/EventBus/Handlers/TenantSynchronizer.cs
@@ -0,0 +1,81 @@
+using PackageName.CompanyName.ProjectName.EntityFrameworkCore;
+using LINGYUN.Abp.Data.DbMigrator;
+using LINGYUN.Abp.MultiTenancy;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Logging;
+using System.Threading.Tasks;
+using Volo.Abp.Data;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.EventBus.Distributed;
+using Volo.Abp.MultiTenancy;
+using Volo.Abp.Uow;
+
+namespace PackageName.CompanyName.ProjectName.EventBus.Handlers;
+
+public class TenantSynchronizer :
+ IDistributedEventHandler,
+ ITransientDependency
+{
+ protected IDataSeeder DataSeeder { get; }
+ protected ICurrentTenant CurrentTenant { get; }
+ protected IDbSchemaMigrator DbSchemaMigrator { get; }
+ protected IUnitOfWorkManager UnitOfWorkManager { get; }
+
+ protected ILogger Logger { get; }
+
+ public TenantSynchronizer(
+ IDataSeeder dataSeeder,
+ ICurrentTenant currentTenant,
+ IDbSchemaMigrator dbSchemaMigrator,
+ IUnitOfWorkManager unitOfWorkManager,
+ ILogger logger)
+ {
+ DataSeeder = dataSeeder;
+ CurrentTenant = currentTenant;
+ DbSchemaMigrator = dbSchemaMigrator;
+ UnitOfWorkManager = unitOfWorkManager;
+
+ Logger = logger;
+ }
+
+ ///
+ /// 租户创建之后需要预置种子数据
+ ///
+ ///
+ ///
+ public virtual async Task HandleEventAsync(CreateEventData eventData)
+ {
+ using (var unitOfWork = UnitOfWorkManager.Begin())
+ {
+ using (CurrentTenant.Change(eventData.Id, eventData.Name))
+ {
+ Logger.LogInformation("Migrating the new tenant database with PackageName.CompanyName.ProjectName...");
+ // 迁移租户数据
+ await DbSchemaMigrator.MigrateAsync(
+ (connectionString, builder) =>
+ {
+#if MySQL
+ builder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
+#elif SqlServer
+ builder.UseSqlServer(connectionString);
+#elif Sqlite
+ builder.UseSqlite(connectionString);
+#elif Oracle
+ builder.UseOracle(connectionString);
+#elif OracleDevart
+ builder.UseOracle(connectionString);
+#elif PostgreSql
+ builder.UseNpgsql(connectionString);
+#endif
+
+ return new ProjectNameDbContext(builder.Options);
+ });
+ Logger.LogInformation("Migrated the new tenant database with PackageName.CompanyName.ProjectName...");
+
+ await DataSeeder.SeedAsync(new DataSeedContext(eventData.Id));
+
+ await unitOfWork.SaveChangesAsync();
+ }
+ }
+ }
+}
diff --git a/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/PackageName.CompanyName.ProjectName.HttpApi.Host.csproj b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/PackageName.CompanyName.ProjectName.HttpApi.Host.csproj
new file mode 100644
index 000000000..df2c575be
--- /dev/null
+++ b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/PackageName.CompanyName.ProjectName.HttpApi.Host.csproj
@@ -0,0 +1,74 @@
+
+
+
+ net7.0
+ PackageName.CompanyName.ProjectName
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Program.cs b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Program.cs
new file mode 100644
index 000000000..0fbaf6dfa
--- /dev/null
+++ b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Program.cs
@@ -0,0 +1,61 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Serilog;
+using System;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Volo.Abp.IO;
+using Volo.Abp.Modularity.PlugIns;
+
+namespace PackageName.CompanyName.ProjectName;
+
+public class Program
+{
+ public async static Task Main(string[] args)
+ {
+ try
+ {
+ Log.Information("Starting web host.");
+
+ var builder = WebApplication.CreateBuilder(args);
+ builder.Host.AddAppSettingsSecretsJson()
+ .UseAutofac()
+ .ConfigureAppConfiguration((context, config) =>
+ {
+ var configuration = config.Build();
+ var agileConfigEnabled = configuration["AgileConfig:IsEnabled"];
+ if (agileConfigEnabled.IsNullOrEmpty() || bool.Parse(agileConfigEnabled))
+ {
+ config.AddAgileConfig(new AgileConfig.Client.ConfigClient(configuration));
+ }
+ })
+ .UseSerilog((context, provider, config) =>
+ {
+ config.ReadFrom.Configuration(context.Configuration);
+ });
+ await builder.AddApplicationAsync(options =>
+ {
+ // 搜索 Modules 目录下所有文件作为插件
+ // 取消显示引用所有其他项目的模块,改为通过插件的形式引用
+ var pluginFolder = Path.Combine(
+ Directory.GetCurrentDirectory(), "Modules");
+ DirectoryHelper.CreateIfNotExists(pluginFolder);
+ options.PlugInSources.AddFolder(
+ pluginFolder,
+ SearchOption.AllDirectories);
+ });
+ var app = builder.Build();
+ await app.InitializeApplicationAsync();
+ await app.RunAsync();
+ return 0;
+ }
+ finally
+ {
+ Log.CloseAndFlush();
+ }
+ }
+}
diff --git a/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/ProjectNameHttpApiHostModule.Configure.cs b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/ProjectNameHttpApiHostModule.Configure.cs
new file mode 100644
index 000000000..a13c42307
--- /dev/null
+++ b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/ProjectNameHttpApiHostModule.Configure.cs
@@ -0,0 +1,361 @@
+using DotNetCore.CAP;
+using LINGYUN.Abp.Dapr.Client.ClientProxying;
+using LINGYUN.Abp.Dapr.Client.DynamicProxying;
+using LINGYUN.Abp.ExceptionHandling;
+using LINGYUN.Abp.ExceptionHandling.Emailing;
+using LINGYUN.Abp.Localization.CultureMap;
+using LINGYUN.Abp.Localization.Persistence;
+using LINGYUN.Abp.Serilog.Enrichers.Application;
+using LINGYUN.Abp.Serilog.Enrichers.UniqueId;
+using LINGYUN.Abp.Wrapper;
+using Medallion.Threading;
+using Medallion.Threading.Redis;
+using Microsoft.AspNetCore.Authentication.JwtBearer;
+using Microsoft.AspNetCore.DataProtection;
+using Microsoft.Extensions.Caching.StackExchangeRedis;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+using Microsoft.OpenApi.Models;
+using OpenTelemetry.Resources;
+using OpenTelemetry.Trace;
+using PackageName.CompanyName.ProjectName.Localization;
+using StackExchange.Redis;
+using System;
+using System.Collections.Generic;
+using System.Text.Encodings.Web;
+using System.Text.Unicode;
+using Volo.Abp;
+using Volo.Abp.Auditing;
+using Volo.Abp.Caching;
+using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.GlobalFeatures;
+using Volo.Abp.Http.Client;
+using Volo.Abp.Json;
+using Volo.Abp.Json.SystemTextJson;
+using Volo.Abp.Localization;
+using Volo.Abp.MultiTenancy;
+using Volo.Abp.Threading;
+using Volo.Abp.VirtualFileSystem;
+using static IdentityModel.ClaimComparer;
+
+namespace PackageName.CompanyName.ProjectName;
+
+public partial class ProjectNameHttpApiHostModule
+{
+ protected const string ApplicationName = "ProjectName";
+ private static readonly OneTimeRunner OneTimeRunner = new();
+
+ private void PreConfigureFeature()
+ {
+ OneTimeRunner.Run(() =>
+ {
+ GlobalFeatureManager.Instance.Modules.Editions().EnableAll();
+ });
+ }
+
+ private void PreConfigureApp()
+ {
+ AbpSerilogEnrichersConsts.ApplicationName = ApplicationName;
+
+ PreConfigure(options =>
+ {
+ // 以开放端口区别
+ options.SnowflakeIdOptions.WorkerId = 5;
+ options.SnowflakeIdOptions.WorkerIdBits = 5;
+ options.SnowflakeIdOptions.DatacenterId = 1;
+ });
+ }
+
+ private void PreConfigureCAP(IConfiguration configuration)
+ {
+ PreConfigure(options =>
+ {
+ options
+#if MySQL
+ .UseMySql(sqlOptions =>
+ {
+ configuration.GetSection("CAP:MySql").Bind(sqlOptions);
+ })
+#elif SqlServer
+ .UseSqlServer(sqlOptions =>
+ {
+ configuration.GetSection("CAP:SqlServer").Bind(sqlOptions);
+ })
+#elif Sqlite
+ .UseSqlite(sqlOptions =>
+ {
+ configuration.GetSection("CAP:Sqlite").Bind(sqlOptions);
+ })
+#elif Oracle || OracleDevart
+ .UseOracle(sqlOptions =>
+ {
+ configuration.GetSection("CAP:Oracle").Bind(sqlOptions);
+ })
+#elif PostgreSql
+ .UsePostgreSql(sqlOptions =>
+ {
+ configuration.GetSection("CAP:PostgreSql").Bind(sqlOptions);
+ })
+#endif
+ .UseRabbitMQ(rabbitMQOptions =>
+ {
+ configuration.GetSection("CAP:RabbitMQ").Bind(rabbitMQOptions);
+ })
+ .UseDashboard();
+ });
+ }
+
+ private void ConfigureJsonSerializer()
+ {
+ // 解决某些不支持类型的序列化
+ Configure(options =>
+ {
+ options.OutputDateTimeFormat = "yyyy-MM-dd HH:mm:ss";
+ options.InputDateTimeFormats.AddIfNotContains("yyyy-MM-dd HH:mm:ss");
+ options.InputDateTimeFormats.AddIfNotContains("yyyy-MM-ddTHH:mm:ss");
+ });
+ // 中文序列化的编码问题
+ Configure(options =>
+ {
+ options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
+ });
+ }
+
+ private void ConfigureDistributedLock(IServiceCollection services, IConfiguration configuration)
+ {
+ var distributedLockEnabled = configuration["Redis:IsEnabled"];
+ if (distributedLockEnabled.IsNullOrEmpty() || bool.Parse(distributedLockEnabled))
+ {
+ var redis = ConnectionMultiplexer.Connect(configuration["DistributedLock:Redis:Configuration"]);
+ services.AddSingleton(_ => new RedisDistributedSynchronizationProvider(redis.GetDatabase()));
+ }
+ }
+
+ private void ConfigureOpenTelemetry(IServiceCollection services, IConfiguration configuration)
+ {
+ var openTelemetryEnabled = configuration["OpenTelemetry:IsEnabled"];
+ if (openTelemetryEnabled.IsNullOrEmpty() || bool.Parse(openTelemetryEnabled))
+ {
+ services.AddOpenTelemetryTracing(cfg =>
+ {
+ cfg.AddSource(ApplicationName)
+ .SetResourceBuilder(
+ ResourceBuilder.CreateDefault().AddService(ApplicationName))
+ .AddHttpClientInstrumentation()
+ .AddAspNetCoreInstrumentation()
+ .AddEntityFrameworkCoreInstrumentation()
+ .AddCapInstrumentation()
+ .AddZipkinExporter(zipKinOptions =>
+ {
+ var endpoint = configuration["OpenTelemetry:ZipKin:Endpoint"];
+ if (!endpoint.IsNullOrWhiteSpace())
+ {
+ zipKinOptions.Endpoint = new Uri(configuration["OpenTelemetry:ZipKin:Endpoint"]);
+ }
+ });
+ });
+ }
+ }
+
+ private void ConfigureExceptionHandling()
+ {
+ // 自定义需要处理的异常
+ Configure(options =>
+ {
+ // 加入需要处理的异常类型
+ options.Handlers.Add();
+ options.Handlers.Add();
+ options.Handlers.Add();
+ options.Handlers.Add();
+ options.Handlers.Add();
+ options.Handlers.Add();
+ });
+ // 自定义需要发送邮件通知的异常类型
+ Configure(options =>
+ {
+ // 是否发送堆栈信息
+ options.SendStackTrace = true;
+ // 未指定异常接收者的默认接收邮件
+ // 指定自己的邮件地址
+ });
+ }
+
+ private void ConfigureAuditing(IConfiguration configuration)
+ {
+ Configure(options =>
+ {
+ options.ApplicationName = ApplicationName;
+ // 是否启用实体变更记录
+ var allEntitiesSelectorIsEnabled = configuration["Auditing:AllEntitiesSelector"];
+ if (allEntitiesSelectorIsEnabled.IsNullOrWhiteSpace() ||
+ (bool.TryParse(allEntitiesSelectorIsEnabled, out var enabled) && enabled))
+ {
+ options.EntityHistorySelectors.AddAllEntities();
+ }
+ });
+ }
+
+ private void ConfigureCaching(IConfiguration configuration)
+ {
+ Configure(options =>
+ {
+ configuration.GetSection("DistributedCache").Bind(options);
+ });
+
+ Configure(options =>
+ {
+ var redisConfig = ConfigurationOptions.Parse(options.Configuration);
+ options.ConfigurationOptions = redisConfig;
+ options.InstanceName = configuration["Redis:InstanceName"];
+ });
+ }
+
+ private void ConfigureVirtualFileSystem()
+ {
+ Configure(options =>
+ {
+ options.FileSets.AddEmbedded("PackageName.CompanyName.ProjectName");
+ });
+ }
+
+ private void ConfigureMultiTenancy(IConfiguration configuration)
+ {
+ // 多租户
+ Configure(options =>
+ {
+ options.IsEnabled = true;
+ });
+
+ var tenantResolveCfg = configuration.GetSection("App:Domains");
+ if (tenantResolveCfg.Exists())
+ {
+ Configure(options =>
+ {
+ var domains = tenantResolveCfg.Get();
+ foreach (var domain in domains)
+ {
+ options.AddDomainTenantResolver(domain);
+ }
+ });
+ }
+ }
+
+ private void ConfigureSwagger(IServiceCollection services)
+ {
+ // Swagger
+ services.AddSwaggerGen(
+ options =>
+ {
+ options.SwaggerDoc("v1", new OpenApiInfo { Title = "ProjectName API", Version = "v1" });
+ options.DocInclusionPredicate((docName, description) => true);
+ options.CustomSchemaIds(type => type.FullName);
+ options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
+ {
+ Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
+ Name = "Authorization",
+ In = ParameterLocation.Header,
+ Scheme = "bearer",
+ Type = SecuritySchemeType.Http,
+ BearerFormat = "JWT"
+ });
+ options.AddSecurityRequirement(new OpenApiSecurityRequirement
+ {
+ {
+ new OpenApiSecurityScheme
+ {
+ Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }
+ },
+ new string[] { }
+ }
+ });
+ options.OperationFilter();
+ });
+ }
+
+ private void ConfigureLocalization()
+ {
+ // 支持本地化语言类型
+ Configure(options =>
+ {
+ options.Languages.Add(new LanguageInfo("en", "en", "English"));
+ options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
+ });
+
+ Configure(options =>
+ {
+ // 持久化本地化资源
+ options.SaveStaticLocalizationsToPersistence = true;
+ options.AddPersistenceResource();
+ });
+
+ Configure(options =>
+ {
+ var zhHansCultureMapInfo = new CultureMapInfo
+ {
+ TargetCulture = "zh-Hans",
+ SourceCultures = new string[] { "zh", "zh_CN", "zh-CN" }
+ };
+
+ options.CulturesMaps.Add(zhHansCultureMapInfo);
+ options.UiCulturesMaps.Add(zhHansCultureMapInfo);
+ });
+ }
+
+ private void ConfigureSecurity(IServiceCollection services, IConfiguration configuration, bool isDevelopment = false)
+ {
+ services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
+ .AddJwtBearer(options =>
+ {
+ options.Authority = configuration["AuthServer:Authority"];
+ options.Audience = configuration["AuthServer:ApiName"];
+ options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]);
+ });
+
+ if (!isDevelopment)
+ {
+ var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
+ services
+ .AddDataProtection()
+ .SetApplicationName("LINGYUN.Abp.Application")
+ .PersistKeysToStackExchangeRedis(redis, "LINGYUN.Abp.Application:DataProtection:Protection-Keys");
+ }
+ }
+
+ private void ConfigureWrapper()
+ {
+ Configure(options =>
+ {
+ // 取消注释包装结果
+ // options.IsEnabled = true;
+ });
+
+ Configure(options =>
+ {
+ // http服务间调用发送不需要包装结果的请求头
+ options.ProxyClientBuildActions.Add(
+ (_, builder) =>
+ {
+ builder.ConfigureHttpClient((provider, client) =>
+ {
+ var wrapperOptions = provider.GetRequiredService>();
+ var wrapperHeader = wrapperOptions.Value.IsEnabled
+ ? AbpHttpWrapConsts.AbpWrapResult
+ : AbpHttpWrapConsts.AbpDontWrapResult;
+
+ client.DefaultRequestHeaders.TryAddWithoutValidation(wrapperHeader, "true");
+ });
+ });
+ });
+
+ Configure(options =>
+ {
+ // dapr服务间调用发送不需要包装结果的请求头
+ options.ProxyRequestActions.Add(
+ (appId, httpRequestMessage) =>
+ {
+ httpRequestMessage.Headers.TryAddWithoutValidation(AbpHttpWrapConsts.AbpDontWrapResult, "true");
+ });
+ });
+ }
+}
diff --git a/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/ProjectNameHttpApiHostModule.cs b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/ProjectNameHttpApiHostModule.cs
new file mode 100644
index 000000000..65dde60c7
--- /dev/null
+++ b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/ProjectNameHttpApiHostModule.cs
@@ -0,0 +1,128 @@
+using LINGYUN.Abp.AspNetCore.Mvc.Wrapper;
+using LINGYUN.Abp.AuditLogging.Elasticsearch;
+using LINGYUN.Abp.EventBus.CAP;
+using LINGYUN.Abp.ExceptionHandling.Emailing;
+using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore;
+using LINGYUN.Abp.TextTemplating.EntityFrameworkCore;
+using LINGYUN.Abp.Saas.EntityFrameworkCore;
+using LINGYUN.Abp.Serilog.Enrichers.Application;
+using LINGYUN.Abp.Serilog.Enrichers.UniqueId;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using PackageName.CompanyName.ProjectName.EntityFrameworkCore;
+using PackageName.CompanyName.ProjectName.SettingManagement;
+using Volo.Abp;
+#if IdentityServer4
+using Volo.Abp.AspNetCore.Authentication.JwtBearer;
+#elif OpenIddict
+using Volo.Abp.OpenIddict;
+#endif
+using Volo.Abp.AspNetCore.MultiTenancy;
+using Volo.Abp.AspNetCore.Serilog;
+using Volo.Abp.Autofac;
+using Volo.Abp.Caching.StackExchangeRedis;
+using Volo.Abp.DistributedLocking;
+using Volo.Abp.FeatureManagement.EntityFrameworkCore;
+using Volo.Abp.Http.Client.IdentityModel.Web;
+using Volo.Abp.Modularity;
+using Volo.Abp.PermissionManagement.EntityFrameworkCore;
+using Volo.Abp.SettingManagement.EntityFrameworkCore;
+using Volo.Abp.Swashbuckle;
+
+namespace PackageName.CompanyName.ProjectName;
+
+[DependsOn(
+ typeof(AbpSerilogEnrichersApplicationModule),
+ typeof(AbpSerilogEnrichersUniqueIdModule),
+ typeof(AbpAuditLoggingElasticsearchModule),
+ typeof(AbpAspNetCoreSerilogModule),
+ typeof(ProjectNameApplicationModule),
+ typeof(ProjectNameHttpApiModule),
+ typeof(ProjectNameEntityFrameworkCoreModule),
+ typeof(ProjectNameSettingManagementModule),
+ typeof(AbpEmailingExceptionHandlingModule),
+ typeof(AbpCAPEventBusModule),
+ typeof(AbpHttpClientIdentityModelWebModule),
+ typeof(AbpAspNetCoreMultiTenancyModule),
+ typeof(AbpSaasEntityFrameworkCoreModule),
+ typeof(AbpFeatureManagementEntityFrameworkCoreModule),
+ typeof(AbpPermissionManagementEntityFrameworkCoreModule),
+ typeof(AbpSettingManagementEntityFrameworkCoreModule),
+ typeof(AbpLocalizationManagementEntityFrameworkCoreModule),
+ typeof(AbpTextTemplatingEntityFrameworkCoreModule),
+#if IdentityServer4
+ typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
+#elif OpenIddict
+ typeof(AbpOpenIddictAspNetCoreModule),
+#endif
+ typeof(AbpCachingStackExchangeRedisModule),
+ typeof(AbpDistributedLockingModule),
+ typeof(AbpAspNetCoreMvcWrapperModule),
+ typeof(AbpSwashbuckleModule),
+ typeof(AbpAutofacModule)
+ )]
+public partial class ProjectNameHttpApiHostModule : AbpModule
+{
+ public override void PreConfigureServices(ServiceConfigurationContext context)
+ {
+ var configuration = context.Services.GetConfiguration();
+
+ PreConfigureApp();
+ PreConfigureFeature();
+ PreConfigureCAP(configuration);
+ }
+
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ var hostingEnvironment = context.Services.GetHostingEnvironment();
+ var configuration = context.Services.GetConfiguration();
+
+ ConfigureWrapper();
+ ConfigureLocalization();
+ ConfigureJsonSerializer();
+ ConfigureExceptionHandling();
+ ConfigureVirtualFileSystem();
+ ConfigureCaching(configuration);
+ ConfigureAuditing(configuration);
+ ConfigureMultiTenancy(configuration);
+ ConfigureSwagger(context.Services);
+ ConfigureOpenTelemetry(context.Services, configuration);
+ ConfigureDistributedLock(context.Services, configuration);
+ ConfigureSecurity(context.Services, configuration, hostingEnvironment.IsDevelopment());
+ }
+
+ public override void OnApplicationInitialization(ApplicationInitializationContext context)
+ {
+ var app = context.GetApplicationBuilder();
+ var env = context.GetEnvironment();
+
+ app.UseMapRequestLocalization();
+ app.UseCorrelationId();
+ app.UseStaticFiles();
+ app.UseRouting();
+ app.UseCors();
+ app.UseAuthentication();
+#if IdentityServer4
+ app.UseJwtTokenMiddleware();
+#elif OpenIddict
+ app.UseAbpOpenIddictValidation();
+#endif
+ app.UseMultiTenancy();
+ app.UseAuthorization();
+ app.UseSwagger();
+ app.UseAbpSwaggerUI(options =>
+ {
+ options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support ProjectName API");
+
+ var configuration = context.GetConfiguration();
+ options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]);
+ options.OAuthClientSecret(configuration["AuthServer:SwaggerClientSecret"]);
+ options.OAuthScopes("ProjectName");
+ });
+ app.UseAuditing();
+ app.UseAbpSerilogEnrichers();
+ app.UseConfiguredEndpoints();
+ }
+}
diff --git a/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Properties/launchSettings.json b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Properties/launchSettings.json
new file mode 100644
index 000000000..bfc8f50b6
--- /dev/null
+++ b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Properties/launchSettings.json
@@ -0,0 +1,28 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:20890",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "PackageName.CompanyName.ProjectName.HttpApi.Host": {
+ "commandName": "Project",
+ "launchBrowser": false,
+ "dotnetRunMessages": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "http://127.0.0.1:5000"
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": false,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/TenantHeaderParamter.cs b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/TenantHeaderParamter.cs
new file mode 100644
index 000000000..265c287de
--- /dev/null
+++ b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/TenantHeaderParamter.cs
@@ -0,0 +1,31 @@
+using Microsoft.Extensions.Options;
+using Microsoft.OpenApi.Models;
+using Swashbuckle.AspNetCore.SwaggerGen;
+using System.Collections.Generic;
+using Volo.Abp.MultiTenancy;
+
+namespace PackageName.CompanyName.ProjectName;
+
+public class TenantHeaderParamter : IOperationFilter
+{
+ private readonly AbpMultiTenancyOptions _options;
+ public TenantHeaderParamter(
+ IOptions options)
+ {
+ _options = options.Value;
+ }
+ public void Apply(OpenApiOperation operation, OperationFilterContext context)
+ {
+ if (_options.IsEnabled)
+ {
+ operation.Parameters = operation.Parameters ?? new List();
+ operation.Parameters.Add(new OpenApiParameter
+ {
+ Name = TenantResolverConsts.DefaultTenantKey,
+ In = ParameterLocation.Header,
+ Description = "Tenant Id/Name",
+ Required = false
+ });
+ }
+ }
+}
diff --git a/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/appsettings.Development.json b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/appsettings.Development.json
new file mode 100644
index 000000000..c6e784dad
--- /dev/null
+++ b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/appsettings.Development.json
@@ -0,0 +1,146 @@
+{
+ "AgileConfig": {
+ "IsEnabled": false,
+ "env": "DEV",
+ "appId": "PackageName.CompanyName.ProjectName",
+ "secret": "1q2w3E*",
+ "nodes": "http://127.0.0.1:15000",
+ "name": "PackageName.CompanyName.ProjectName",
+ "tag": "PackageName.CompanyName.ProjectName"
+ },
+ "Auditing": {
+ "AllEntitiesSelector": true
+ },
+ "DistributedCache": {
+ "HideErrors": true,
+ "KeyPrefix": "LINGYUN.Abp.Application",
+ "GlobalCacheEntryOptions": {
+ "SlidingExpiration": "30:00:00",
+ "AbsoluteExpirationRelativeToNow": "60:00:00"
+ }
+ },
+ "ConnectionStrings": {
+ "Default": "Server=127.0.0.1;Database=ProjectName;User Id=root;Password=123456",
+ "ProjectName": "Server=127.0.0.1;Database=ProjectName;User Id=root;Password=123456",
+ "AbpSaas": "Server=127.0.0.1;Database=ProjectName;User Id=root;Password=123456",
+ "AbpFeatureManagement": "Server=127.0.0.1;Database=ProjectName;User Id=root;Password=123456",
+ "AbpPermissionManagement": "Server=127.0.0.1;Database=ProjectName;User Id=root;Password=123456",
+ "AbpSettingManagement": "Server=127.0.0.1;Database=ProjectName;User Id=root;Password=123456",
+ "AbpLocalizationManagement": "Server=127.0.0.1;Database=ProjectName;User Id=root;Password=123456",
+ "AbpTextTemplating": "Server=127.0.0.1;Database=ProjectName;User Id=root;Password=123456"
+ },
+ "DistributedLock": {
+ "IsEnabled": true,
+ "Redis": {
+ "Configuration": "127.0.0.1,defaultDatabase=15"
+ }
+ },
+ "OpenTelemetry": {
+ "IsEnabled": true,
+ "ZipKin": {
+ "Endpoint": "http://127.0.0.1:9411/api/v2/spans"
+ }
+ },
+ "RemoteServices": {},
+ "IdentityClients": {
+ "InternalServiceClient": {
+ "Authority": "http://127.0.0.1:44385",
+ "RequireHttps": false,
+ "GrantType": "client_credentials",
+ "Scope": "lingyun-abp-application",
+ "ClientId": "InternalServiceClient",
+ "ClientSecret": "1q2w3E*"
+ }
+ },
+ "CAP": {
+ "EventBus": {
+ "DefaultGroupName": "ProjectName",
+ "GroupNamePrefix": "Dev",
+ "Version": "v1",
+ "FailedRetryInterval": 300,
+ "FailedRetryCount": 10
+ },
+ "MySql": {
+ "TableNamePrefix": "ProjectName_cap",
+ "ConnectionString": "Server=127.0.0.1;Database=ProjectName;User Id=root;Password=123456"
+ },
+ "SqlServer": {
+ "TableNamePrefix": "ProjectName_cap",
+ "ConnectionString": "Server=127.0.0.1;Database=ProjectName;User Id=root;Password=123456"
+ },
+ "Sqlite": {
+ "TableNamePrefix": "ProjectName_cap",
+ "ConnectionString": "Data Source=./cap.db"
+ },
+ "Oracle": {
+ "TableNamePrefix": "ProjectName_cap",
+ "ConnectionString": "Data Source=ProjectName;Integrated Security=yes;"
+ },
+ "PostgreSql": {
+ "TableNamePrefix": "ProjectName_cap",
+ "ConnectionString": "Host=localhost;Port=5432;Database=ProjectName;User ID=root;Password=123456;"
+ },
+ "RabbitMQ": {
+ "HostName": "127.0.0.1",
+ "Port": 5672,
+ "UserName": "admin",
+ "Password": "123456",
+ "ExchangeName": "LINGYUN.Abp.Application",
+ "VirtualHost": "/"
+ }
+ },
+ "Redis": {
+ "Configuration": "127.0.0.1,defaultDatabase=10",
+ "InstanceName": "LINGYUN.Abp.Application"
+ },
+ "AuthServer": {
+ "Authority": "http://127.0.0.1:44385/",
+ "ApiName": "lingyun-abp-application",
+ "RequireHttpsMetadata": false,
+ "SwaggerClientId": "InternalServiceClient",
+ "SwaggerClientSecret": "1q2w3E*"
+ },
+ "Logging": {
+ "Serilog": {
+ "Elasticsearch": {
+ "IndexFormat": "abp.dev.logging-{0:yyyy.MM.dd}"
+ }
+ }
+ },
+ "AuditLogging": {
+ "Elasticsearch": {
+ "IndexPrefix": "abp.dev.auditing"
+ }
+ },
+ "Elasticsearch": {
+ "NodeUris": "http://127.0.0.1:9200"
+ },
+ "Serilog": {
+ "MinimumLevel": {
+ "Default": "Debug",
+ "Override": {
+ "System": "Warning",
+ "Microsoft": "Warning",
+ "DotNetCore": "Debug"
+ }
+ },
+ "WriteTo": [
+ {
+ "Name": "Console",
+ "Args": {
+ "restrictedToMinimumLevel": "Debug",
+ "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
+ }
+ },
+ {
+ "Name": "Elasticsearch",
+ "Args": {
+ "nodeUris": "http://127.0.0.1:9200",
+ "indexFormat": "abp.dev.logging-{0:yyyy.MM.dd}",
+ "autoRegisterTemplate": true,
+ "autoRegisterTemplateVersion": "ESv7"
+ }
+ }
+ ]
+ }
+}
diff --git a/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/appsettings.json b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/appsettings.json
new file mode 100644
index 000000000..d3d63c269
--- /dev/null
+++ b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/appsettings.json
@@ -0,0 +1,80 @@
+{
+ "StringEncryption": {
+ "DefaultPassPhrase": "s46c5q55nxpeS8Ra",
+ "InitVectorBytes": "s83ng0abvd02js84",
+ "DefaultSalt": "sf&5)s3#"
+ },
+ "AllowedHosts": "*",
+ "Serilog": {
+ "MinimumLevel": {
+ "Default": "Debug",
+ "Override": {
+ "Microsoft.EntityFrameworkCore": "Debug",
+ "System": "Information",
+ "Microsoft": "Information"
+ }
+ },
+ "Enrich": [ "FromLogContext", "WithProcessId", "WithThreadId", "WithEnvironmentName", "WithMachineName", "WithApplicationName", "WithUniqueId" ],
+ "WriteTo": [
+ {
+ "Name": "Console",
+ "Args": {
+ "initialMinimumLevel": "Verbose",
+ "standardErrorFromLevel": "Verbose",
+ "restrictedToMinimumLevel": "Verbose",
+ "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
+ }
+ },
+ {
+ "Name": "File",
+ "Args": {
+ "path": "Logs/Debug-.log",
+ "restrictedToMinimumLevel": "Debug",
+ "rollingInterval": "Day",
+ "fileSizeLimitBytes": 5242880,
+ "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
+ }
+ },
+ {
+ "Name": "File",
+ "Args": {
+ "path": "Logs/Info-.log",
+ "restrictedToMinimumLevel": "Information",
+ "rollingInterval": "Day",
+ "fileSizeLimitBytes": 5242880,
+ "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
+ }
+ },
+ {
+ "Name": "File",
+ "Args": {
+ "path": "Logs/Warn-.log",
+ "restrictedToMinimumLevel": "Warning",
+ "rollingInterval": "Day",
+ "fileSizeLimitBytes": 5242880,
+ "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
+ }
+ },
+ {
+ "Name": "File",
+ "Args": {
+ "path": "Logs/Error-.log",
+ "restrictedToMinimumLevel": "Error",
+ "rollingInterval": "Day",
+ "fileSizeLimitBytes": 5242880,
+ "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
+ }
+ },
+ {
+ "Name": "File",
+ "Args": {
+ "path": "Logs/Fatal-.log",
+ "restrictedToMinimumLevel": "Fatal",
+ "rollingInterval": "Day",
+ "fileSizeLimitBytes": 5242880,
+ "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
+ }
+ }
+ ]
+ }
+}
diff --git a/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/dapr.sh b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/dapr.sh
new file mode 100644
index 000000000..01a8eb036
--- /dev/null
+++ b/aspnet-core/templates/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/dapr.sh
@@ -0,0 +1 @@
+dapr run --app-id ProjectName --app-port 5000 -H 3500 -- dotnet run --no-build
\ No newline at end of file
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/FodyWeavers.xml b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/FodyWeavers.xml
new file mode 100644
index 000000000..1715698cc
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/FodyWeavers.xsd b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/FodyWeavers.xsd
new file mode 100644
index 000000000..11da52550
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/PackageName.CompanyName.ProjectName.Application.Contracts.csproj b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/PackageName.CompanyName.ProjectName.Application.Contracts.csproj
new file mode 100644
index 000000000..4eb9907a3
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/PackageName.CompanyName.ProjectName.Application.Contracts.csproj
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/PackageName/CompanyName/ProjectName/Authorization/ProjectNamePermissionDefinitionProvider.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/PackageName/CompanyName/ProjectName/Authorization/ProjectNamePermissionDefinitionProvider.cs
new file mode 100644
index 000000000..487837400
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/PackageName/CompanyName/ProjectName/Authorization/ProjectNamePermissionDefinitionProvider.cs
@@ -0,0 +1,22 @@
+using PackageName.CompanyName.ProjectName.Localization;
+using Volo.Abp.Authorization.Permissions;
+using Volo.Abp.Localization;
+
+namespace PackageName.CompanyName.ProjectName.Authorization;
+
+public class ProjectNamePermissionDefinitionProvider : PermissionDefinitionProvider
+{
+ public override void Define(IPermissionDefinitionContext context)
+ {
+ var group = context.AddGroup(ProjectNamePermissions.GroupName, L("Permission:ProjectName"));
+
+ group.AddPermission(
+ ProjectNamePermissions.ManageSettings,
+ L("Permission:ManageSettings"));
+ }
+
+ private static LocalizableString L(string name)
+ {
+ return LocalizableString.Create(name);
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/PackageName/CompanyName/ProjectName/Authorization/ProjectNamePermissions.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/PackageName/CompanyName/ProjectName/Authorization/ProjectNamePermissions.cs
new file mode 100644
index 000000000..257d11988
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/PackageName/CompanyName/ProjectName/Authorization/ProjectNamePermissions.cs
@@ -0,0 +1,8 @@
+namespace PackageName.CompanyName.ProjectName.Authorization;
+
+public static class ProjectNamePermissions
+{
+ public const string GroupName = "ProjectName";
+
+ public const string ManageSettings = GroupName + ".ManageSettings";
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/PackageName/CompanyName/ProjectName/Features/ProjectNameFeatureDefinitionProvider.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/PackageName/CompanyName/ProjectName/Features/ProjectNameFeatureDefinitionProvider.cs
new file mode 100644
index 000000000..0dd18f176
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/PackageName/CompanyName/ProjectName/Features/ProjectNameFeatureDefinitionProvider.cs
@@ -0,0 +1,18 @@
+using PackageName.CompanyName.ProjectName.Localization;
+using Volo.Abp.Features;
+using Volo.Abp.Localization;
+
+namespace PackageName.CompanyName.ProjectName.Features;
+
+public class ProjectNameFeatureDefinitionProvider : FeatureDefinitionProvider
+{
+ public override void Define(IFeatureDefinitionContext context)
+ {
+ var group = context.AddGroup(ProjectNameFeatureNames.GroupName, L("Features:ProjectName"));
+ }
+
+ private static ILocalizableString L(string name)
+ {
+ return LocalizableString.Create(name);
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/PackageName/CompanyName/ProjectName/Features/ProjectNameFeatureNames.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/PackageName/CompanyName/ProjectName/Features/ProjectNameFeatureNames.cs
new file mode 100644
index 000000000..4af07a047
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/PackageName/CompanyName/ProjectName/Features/ProjectNameFeatureNames.cs
@@ -0,0 +1,6 @@
+namespace PackageName.CompanyName.ProjectName.Features;
+
+public static class ProjectNameFeatureNames
+{
+ public const string GroupName = "ProjectName";
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/PackageName/CompanyName/ProjectName/IProjectNameDynamicQueryableAppService.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/PackageName/CompanyName/ProjectName/IProjectNameDynamicQueryableAppService.cs
new file mode 100644
index 000000000..6cb9ead42
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/PackageName/CompanyName/ProjectName/IProjectNameDynamicQueryableAppService.cs
@@ -0,0 +1,10 @@
+using LINGYUN.Abp.Dynamic.Queryable;
+
+namespace PackageName.CompanyName.ProjectName;
+///
+/// 提供动态查询接口定义
+///
+/// 实体dto类型
+public interface IProjectNameDynamicQueryableAppService : IDynamicQueryableAppService
+{
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/PackageName/CompanyName/ProjectName/ProjectNameApplicationContractsModule.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/PackageName/CompanyName/ProjectName/ProjectNameApplicationContractsModule.cs
new file mode 100644
index 000000000..9899a0c97
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/PackageName/CompanyName/ProjectName/ProjectNameApplicationContractsModule.cs
@@ -0,0 +1,17 @@
+using LINGYUN.Abp.Dynamic.Queryable;
+using Volo.Abp.Application;
+using Volo.Abp.Authorization;
+using Volo.Abp.Features;
+using Volo.Abp.Modularity;
+
+namespace PackageName.CompanyName.ProjectName;
+
+[DependsOn(
+ typeof(AbpFeaturesModule),
+ typeof(AbpAuthorizationModule),
+ typeof(AbpDddApplicationContractsModule),
+ typeof(AbpDynamicQueryableApplicationContractsModule),
+ typeof(ProjectNameDomainSharedModule))]
+public class ProjectNameApplicationContractsModule : AbpModule
+{
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/PackageName/CompanyName/ProjectName/ProjectNameRemoteServiceConsts.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/PackageName/CompanyName/ProjectName/ProjectNameRemoteServiceConsts.cs
new file mode 100644
index 000000000..ef949b273
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application.Contracts/PackageName/CompanyName/ProjectName/ProjectNameRemoteServiceConsts.cs
@@ -0,0 +1,7 @@
+namespace PackageName.CompanyName.ProjectName;
+
+public static class ProjectNameRemoteServiceConsts
+{
+ public const string RemoteServiceName = "ProjectName";
+ public const string ModuleName = "ProjectName";
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application/FodyWeavers.xml b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application/FodyWeavers.xml
new file mode 100644
index 000000000..1715698cc
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application/FodyWeavers.xsd b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application/FodyWeavers.xsd
new file mode 100644
index 000000000..11da52550
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application/PackageName.CompanyName.ProjectName.Application.csproj b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application/PackageName.CompanyName.ProjectName.Application.csproj
new file mode 100644
index 000000000..c301dd4fb
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application/PackageName.CompanyName.ProjectName.Application.csproj
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+ netstandard2.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application/PackageName/CompanyName/ProjectName/ProjectNameAppServiceBase.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application/PackageName/CompanyName/ProjectName/ProjectNameAppServiceBase.cs
new file mode 100644
index 000000000..458c4dd29
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application/PackageName/CompanyName/ProjectName/ProjectNameAppServiceBase.cs
@@ -0,0 +1,13 @@
+using PackageName.CompanyName.ProjectName.Localization;
+using Volo.Abp.Application.Services;
+
+namespace PackageName.CompanyName.ProjectName;
+
+public abstract class ProjectNameAppServiceBase : ApplicationService
+{
+ protected ProjectNameAppServiceBase()
+ {
+ LocalizationResource = typeof(ProjectNameResource);
+ ObjectMapperContext = typeof(ProjectNameApplicationModule);
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application/PackageName/CompanyName/ProjectName/ProjectNameApplicationMapperProfile.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application/PackageName/CompanyName/ProjectName/ProjectNameApplicationMapperProfile.cs
new file mode 100644
index 000000000..b16e2bc1b
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application/PackageName/CompanyName/ProjectName/ProjectNameApplicationMapperProfile.cs
@@ -0,0 +1,10 @@
+using AutoMapper;
+
+namespace PackageName.CompanyName.ProjectName;
+
+public class ProjectNameApplicationMapperProfile : Profile
+{
+ public ProjectNameApplicationMapperProfile()
+ {
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application/PackageName/CompanyName/ProjectName/ProjectNameApplicationModule.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application/PackageName/CompanyName/ProjectName/ProjectNameApplicationModule.cs
new file mode 100644
index 000000000..723aa233e
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application/PackageName/CompanyName/ProjectName/ProjectNameApplicationModule.cs
@@ -0,0 +1,27 @@
+using LINGYUN.Abp.Dynamic.Queryable;
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Application;
+using Volo.Abp.Authorization;
+using Volo.Abp.AutoMapper;
+using Volo.Abp.Modularity;
+
+namespace PackageName.CompanyName.ProjectName;
+
+[DependsOn(
+ typeof(AbpAuthorizationModule),
+ typeof(AbpDddApplicationModule),
+ typeof(ProjectNameDomainModule),
+ typeof(ProjectNameApplicationContractsModule),
+ typeof(AbpDynamicQueryableApplicationModule))]
+public class ProjectNameApplicationModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddAutoMapperObjectMapper();
+
+ Configure(options =>
+ {
+ options.AddProfile(validate: true);
+ });
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application/PackageName/CompanyName/ProjectName/ProjectNameDynamicQueryableAppServiceBase.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application/PackageName/CompanyName/ProjectName/ProjectNameDynamicQueryableAppServiceBase.cs
new file mode 100644
index 000000000..36e98d204
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Application/PackageName/CompanyName/ProjectName/ProjectNameDynamicQueryableAppServiceBase.cs
@@ -0,0 +1,19 @@
+using LINGYUN.Abp.Dynamic.Queryable;
+using PackageName.CompanyName.ProjectName.Localization;
+
+namespace PackageName.CompanyName.ProjectName;
+///
+/// 提供动态查询接口实现
+///
+/// 实体类型
+/// 实体dto类型
+public abstract class ProjectNameDynamicQueryableAppServiceBase :
+ DynamicQueryableAppService,
+ IProjectNameDynamicQueryableAppService
+{
+ protected ProjectNameDynamicQueryableAppServiceBase()
+ {
+ LocalizationResource = typeof(ProjectNameResource);
+ ObjectMapperContext = typeof(ProjectNameApplicationModule);
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Dapr.Client/FodyWeavers.xml b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Dapr.Client/FodyWeavers.xml
new file mode 100644
index 000000000..1715698cc
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Dapr.Client/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Dapr.Client/FodyWeavers.xsd b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Dapr.Client/FodyWeavers.xsd
new file mode 100644
index 000000000..11da52550
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Dapr.Client/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Dapr.Client/PackageName.CompanyName.ProjectName.Dapr.Client.csproj b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Dapr.Client/PackageName.CompanyName.ProjectName.Dapr.Client.csproj
new file mode 100644
index 000000000..fc977bba6
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Dapr.Client/PackageName.CompanyName.ProjectName.Dapr.Client.csproj
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+ net7.0
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Dapr.Client/PackageName/CompanyName/ProjectName/ProjectNameDaprClientModule.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Dapr.Client/PackageName/CompanyName/ProjectName/ProjectNameDaprClientModule.cs
new file mode 100644
index 000000000..115cce260
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Dapr.Client/PackageName/CompanyName/ProjectName/ProjectNameDaprClientModule.cs
@@ -0,0 +1,18 @@
+using LINGYUN.Abp.Dapr.Client;
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Modularity;
+
+namespace PackageName.CompanyName.ProjectName;
+
+[DependsOn(
+ typeof(AbpDaprClientModule),
+ typeof(ProjectNameApplicationContractsModule))]
+public class ProjectNameDaprClientModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddDaprClientProxies(
+ typeof(ProjectNameApplicationContractsModule).Assembly,
+ ProjectNameRemoteServiceConsts.RemoteServiceName);
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/FodyWeavers.xml b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/FodyWeavers.xml
new file mode 100644
index 000000000..1715698cc
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/FodyWeavers.xsd b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/FodyWeavers.xsd
new file mode 100644
index 000000000..11da52550
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName.CompanyName.ProjectName.Domain.Shared.csproj b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName.CompanyName.ProjectName.Domain.Shared.csproj
new file mode 100644
index 000000000..e10b1cfdd
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName.CompanyName.ProjectName.Domain.Shared.csproj
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName/CompanyName/ProjectName/Localization/ProjectNameResource.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName/CompanyName/ProjectName/Localization/ProjectNameResource.cs
new file mode 100644
index 000000000..11db159c1
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName/CompanyName/ProjectName/Localization/ProjectNameResource.cs
@@ -0,0 +1,8 @@
+using Volo.Abp.Localization;
+
+namespace PackageName.CompanyName.ProjectName.Localization;
+
+[LocalizationResourceName("ProjectName")]
+public class ProjectNameResource
+{
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName/CompanyName/ProjectName/Localization/Resources/en.json b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName/CompanyName/ProjectName/Localization/Resources/en.json
new file mode 100644
index 000000000..a529d6960
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName/CompanyName/ProjectName/Localization/Resources/en.json
@@ -0,0 +1,8 @@
+{
+ "culture": "en",
+ "texts": {
+ "Features:ProjectName": "ProjectName",
+ "Permission:ProjectName": "ProjectName",
+ "Permission:ManageSettings": "Manage Settings"
+ }
+}
\ No newline at end of file
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName/CompanyName/ProjectName/Localization/Resources/zh-Hans.json b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName/CompanyName/ProjectName/Localization/Resources/zh-Hans.json
new file mode 100644
index 000000000..e2af58de8
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName/CompanyName/ProjectName/Localization/Resources/zh-Hans.json
@@ -0,0 +1,8 @@
+{
+ "culture": "zh-Hans",
+ "texts": {
+ "Features:ProjectName": "ProjectName",
+ "Permission:ProjectName": "ProjectName",
+ "Permission:ManageSettings": "管理设置"
+ }
+}
\ No newline at end of file
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName/CompanyName/ProjectName/ObjectExtending/ProjectNameModuleExtensionConfiguration.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName/CompanyName/ProjectName/ObjectExtending/ProjectNameModuleExtensionConfiguration.cs
new file mode 100644
index 000000000..6ce706932
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName/CompanyName/ProjectName/ObjectExtending/ProjectNameModuleExtensionConfiguration.cs
@@ -0,0 +1,16 @@
+using System;
+using Volo.Abp.ObjectExtending.Modularity;
+
+namespace PackageName.CompanyName.ProjectName.ObjectExtending;
+
+public class ProjectNameModuleExtensionConfiguration : ModuleExtensionConfiguration
+{
+ public ProjectNameModuleExtensionConfiguration ConfigureProjectName(
+ Action configureAction)
+ {
+ return this.ConfigureEntity(
+ ProjectNameModuleExtensionConsts.EntityNames.Entity,
+ configureAction
+ );
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName/CompanyName/ProjectName/ObjectExtending/ProjectNameModuleExtensionConfigurationDictionaryExtensions.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName/CompanyName/ProjectName/ObjectExtending/ProjectNameModuleExtensionConfigurationDictionaryExtensions.cs
new file mode 100644
index 000000000..d59e7c515
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName/CompanyName/ProjectName/ObjectExtending/ProjectNameModuleExtensionConfigurationDictionaryExtensions.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Volo.Abp.ObjectExtending.Modularity;
+
+namespace PackageName.CompanyName.ProjectName.ObjectExtending;
+
+public static class ProjectNameModuleExtensionConfigurationDictionaryExtensions
+{
+ public static ModuleExtensionConfigurationDictionary ConfigureProjectName(
+ this ModuleExtensionConfigurationDictionary modules,
+ Action configureAction)
+ {
+ return modules.ConfigureModule(
+ ProjectNameModuleExtensionConsts.ModuleName,
+ configureAction
+ );
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName/CompanyName/ProjectName/ObjectExtending/ProjectNameModuleExtensionConsts.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName/CompanyName/ProjectName/ObjectExtending/ProjectNameModuleExtensionConsts.cs
new file mode 100644
index 000000000..dd5e13da8
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName/CompanyName/ProjectName/ObjectExtending/ProjectNameModuleExtensionConsts.cs
@@ -0,0 +1,11 @@
+namespace PackageName.CompanyName.ProjectName.ObjectExtending;
+
+public static class ProjectNameModuleExtensionConsts
+{
+ public const string ModuleName = "ProjectName";
+
+ public static class EntityNames
+ {
+ public const string Entity = "Entity";
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName/CompanyName/ProjectName/ProjectNameDomainSharedModule.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName/CompanyName/ProjectName/ProjectNameDomainSharedModule.cs
new file mode 100644
index 000000000..7473c7453
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName/CompanyName/ProjectName/ProjectNameDomainSharedModule.cs
@@ -0,0 +1,32 @@
+using PackageName.CompanyName.ProjectName.Localization;
+using Volo.Abp.Localization;
+using Volo.Abp.Localization.ExceptionHandling;
+using Volo.Abp.Modularity;
+using Volo.Abp.VirtualFileSystem;
+
+namespace PackageName.CompanyName.ProjectName;
+
+[DependsOn(
+ typeof(AbpLocalizationModule))]
+public class ProjectNameDomainSharedModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ Configure(options =>
+ {
+ options.FileSets.AddEmbedded();
+ });
+
+ Configure(options =>
+ {
+ options.Resources
+ .Add()
+ .AddVirtualJson("/PackageName/CompanyName/ProjectName/Localization/Resources");
+ });
+
+ Configure(options =>
+ {
+ options.MapCodeNamespace(ProjectNameErrorCodes.Namespace, typeof(ProjectNameResource));
+ });
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName/CompanyName/ProjectName/ProjectNameErrorCodes.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName/CompanyName/ProjectName/ProjectNameErrorCodes.cs
new file mode 100644
index 000000000..7a652e651
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain.Shared/PackageName/CompanyName/ProjectName/ProjectNameErrorCodes.cs
@@ -0,0 +1,6 @@
+namespace PackageName.CompanyName.ProjectName;
+
+public static class ProjectNameErrorCodes
+{
+ public const string Namespace = "ProjectName";
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/FodyWeavers.xml b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/FodyWeavers.xml
new file mode 100644
index 000000000..1715698cc
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/FodyWeavers.xsd b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/FodyWeavers.xsd
new file mode 100644
index 000000000..11da52550
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/PackageName.CompanyName.ProjectName.Domain.csproj b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/PackageName.CompanyName.ProjectName.Domain.csproj
new file mode 100644
index 000000000..2b70ff5aa
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/PackageName.CompanyName.ProjectName.Domain.csproj
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+ netstandard2.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/PackageName/CompanyName/ProjectName/IProjectNameSpecificationSupport.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/PackageName/CompanyName/ProjectName/IProjectNameSpecificationSupport.cs
new file mode 100644
index 000000000..3e1975700
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/PackageName/CompanyName/ProjectName/IProjectNameSpecificationSupport.cs
@@ -0,0 +1,40 @@
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Volo.Abp.Domain.Entities;
+using Volo.Abp.Specifications;
+
+namespace PackageName.CompanyName.ProjectName;
+///
+/// 实现接口支持规约化查询
+///
+/// 实体类型
+/// 实体主键类型
+public interface IProjectNameSpecificationSupport
+ where TEntity : class, IEntity
+{
+ ///
+ /// 获取过滤后的实体数量
+ ///
+ ///
+ ///
+ ///
+ Task GetCountAsync(
+ ISpecification specification,
+ CancellationToken cancellationToken = default);
+ ///
+ /// 获取过滤后的实体列表
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task> GetListAsync(
+ ISpecification specification,
+ string sorting = nameof(IEntity.Id),
+ int maxResultCount = 10,
+ int skipCount = 0,
+ CancellationToken cancellationToken = default);
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/PackageName/CompanyName/ProjectName/ProjectNameDbProperties.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/PackageName/CompanyName/ProjectName/ProjectNameDbProperties.cs
new file mode 100644
index 000000000..5cd27642b
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/PackageName/CompanyName/ProjectName/ProjectNameDbProperties.cs
@@ -0,0 +1,11 @@
+namespace PackageName.CompanyName.ProjectName;
+
+public static class ProjectNameDbProperties
+{
+ public static string DbTablePrefix { get; set; } = "ProjectName_";
+
+ public static string DbSchema { get; set; } = null;
+
+
+ public const string ConnectionStringName = "ProjectName";
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/PackageName/CompanyName/ProjectName/ProjectNameDomainMapperProfile.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/PackageName/CompanyName/ProjectName/ProjectNameDomainMapperProfile.cs
new file mode 100644
index 000000000..b2cc42748
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/PackageName/CompanyName/ProjectName/ProjectNameDomainMapperProfile.cs
@@ -0,0 +1,11 @@
+using AutoMapper;
+
+namespace PackageName.CompanyName.ProjectName;
+
+public class ProjectNameDomainMapperProfile : Profile
+{
+ public ProjectNameDomainMapperProfile()
+ {
+
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/PackageName/CompanyName/ProjectName/ProjectNameDomainModule.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/PackageName/CompanyName/ProjectName/ProjectNameDomainModule.cs
new file mode 100644
index 000000000..83927c1d2
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/PackageName/CompanyName/ProjectName/ProjectNameDomainModule.cs
@@ -0,0 +1,43 @@
+using Microsoft.Extensions.DependencyInjection;
+using PackageName.CompanyName.ProjectName.ObjectExtending;
+using Volo.Abp.AutoMapper;
+using Volo.Abp.Domain.Entities.Events.Distributed;
+using Volo.Abp.Modularity;
+using Volo.Abp.ObjectExtending.Modularity;
+using Volo.Abp.Threading;
+
+namespace PackageName.CompanyName.ProjectName;
+
+[DependsOn(
+ typeof(AbpAutoMapperModule),
+ typeof(ProjectNameDomainSharedModule))]
+public class ProjectNameDomainModule : AbpModule
+{
+ private static readonly OneTimeRunner OneTimeRunner = new();
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddAutoMapperObjectMapper();
+
+ Configure(options =>
+ {
+ options.AddProfile(validate: true);
+ });
+
+ Configure(options =>
+ {
+ });
+ }
+
+ public override void PostConfigureServices(ServiceConfigurationContext context)
+ {
+ OneTimeRunner.Run(() =>
+ {
+ // 扩展实体配置
+ //ModuleExtensionConfigurationHelper.ApplyEntityConfigurationToEntity(
+ // ProjectNameModuleExtensionConsts.ModuleName,
+ // ProjectNameModuleExtensionConsts.EntityNames.Entity,
+ // typeof(Entity)
+ //);
+ });
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/PackageName/CompanyName/ProjectName/Settings/ProjectNameSettingDefinitionProvider.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/PackageName/CompanyName/ProjectName/Settings/ProjectNameSettingDefinitionProvider.cs
new file mode 100644
index 000000000..64db558bf
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/PackageName/CompanyName/ProjectName/Settings/ProjectNameSettingDefinitionProvider.cs
@@ -0,0 +1,11 @@
+using Volo.Abp.Settings;
+
+namespace PackageName.CompanyName.ProjectName.Settings
+{
+ public class ProjectNameSettingDefinitionProvider : SettingDefinitionProvider
+ {
+ public override void Define(ISettingDefinitionContext context)
+ {
+ }
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/PackageName/CompanyName/ProjectName/Settings/ProjectNameSettings.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/PackageName/CompanyName/ProjectName/Settings/ProjectNameSettings.cs
new file mode 100644
index 000000000..7561cf8da
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/PackageName/CompanyName/ProjectName/Settings/ProjectNameSettings.cs
@@ -0,0 +1,7 @@
+namespace PackageName.CompanyName.ProjectName.Settings
+{
+ public static class ProjectNameSettings
+ {
+ public const string GroupName = "ProjectName";
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/System/Linq/Expressions/ExpressionFuncExtensions.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/System/Linq/Expressions/ExpressionFuncExtensions.cs
new file mode 100644
index 000000000..74e3c828a
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.Domain/System/Linq/Expressions/ExpressionFuncExtensions.cs
@@ -0,0 +1,32 @@
+using Volo.Abp.Specifications;
+
+namespace System.Linq.Expressions;
+
+internal static class ExpressionFuncExtensions
+{
+ public static Expression> AndIf(
+ this Expression> first,
+ bool condition,
+ Expression> second)
+ {
+ if (condition)
+ {
+ return ExpressionFuncExtender.And(first, second);
+ }
+
+ return first;
+ }
+
+ public static Expression> OrIf(
+ this Expression> first,
+ bool condition,
+ Expression> second)
+ {
+ if (condition)
+ {
+ return ExpressionFuncExtender.Or(first, second);
+ }
+
+ return first;
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/FodyWeavers.xml b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/FodyWeavers.xml
new file mode 100644
index 000000000..1715698cc
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/FodyWeavers.xsd b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/FodyWeavers.xsd
new file mode 100644
index 000000000..11da52550
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName.CompanyName.ProjectName.EntityFrameworkCore.csproj b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName.CompanyName.ProjectName.EntityFrameworkCore.csproj
new file mode 100644
index 000000000..f2c877dd1
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName.CompanyName.ProjectName.EntityFrameworkCore.csproj
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+ net7.0
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/EfCoreSpecificationSupportRepository.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/EfCoreSpecificationSupportRepository.cs
new file mode 100644
index 000000000..a8ce44810
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/EfCoreSpecificationSupportRepository.cs
@@ -0,0 +1,60 @@
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Dynamic.Core;
+using System.Threading;
+using System.Threading.Tasks;
+using Volo.Abp.Domain.Entities;
+using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.Specifications;
+
+namespace PackageName.CompanyName.ProjectName.EntityFrameworkCore;
+///
+/// 实现仓储提供规约化查询
+///
+/// 实体类型
+/// 实体主键类型
+public abstract class EfCoreSpecificationSupportRepository :
+ EfCoreRepository,
+ IProjectNameSpecificationSupport
+ where TEntity : class, IEntity
+{
+ protected EfCoreSpecificationSupportRepository(
+ IDbContextProvider dbContextProvider) : base(dbContextProvider)
+ {
+ }
+
+ public async virtual Task GetCountAsync(
+ ISpecification specification,
+ CancellationToken cancellationToken = default)
+ {
+ return await (await GetDbSetAsync())
+ .Where(specification.ToExpression())
+ .CountAsync(GetCancellationToken(cancellationToken));
+ }
+
+ public async virtual Task> GetListAsync(
+ ISpecification specification,
+ string sorting = nameof(IEntity.Id),
+ int maxResultCount = 10,
+ int skipCount = 0,
+ CancellationToken cancellationToken = default)
+ {
+ return await (await GetDbSetAsync())
+ .Where(specification.ToExpression())
+ .OrderBy(GetSortingOrDefault(sorting))
+ .PageBy(skipCount, maxResultCount)
+ .ToListAsync(GetCancellationToken(cancellationToken));
+ }
+
+ protected virtual string GetSortingOrDefault(string sorting = nameof(IEntity.Id))
+ {
+ if (sorting.IsNullOrWhiteSpace())
+ {
+ return nameof(IEntity.Id);
+ }
+ return sorting;
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/IProjectNameDbContext.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/IProjectNameDbContext.cs
new file mode 100644
index 000000000..b9abdef0c
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/IProjectNameDbContext.cs
@@ -0,0 +1,9 @@
+using Volo.Abp.Data;
+using Volo.Abp.EntityFrameworkCore;
+
+namespace PackageName.CompanyName.ProjectName.EntityFrameworkCore;
+
+[ConnectionStringName(ProjectNameDbProperties.ConnectionStringName)]
+public interface IProjectNameDbContext : IEfCoreDbContext
+{
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameDbContext.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameDbContext.cs
new file mode 100644
index 000000000..5e43ea730
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameDbContext.cs
@@ -0,0 +1,21 @@
+using Microsoft.EntityFrameworkCore;
+using Volo.Abp.Data;
+using Volo.Abp.EntityFrameworkCore;
+
+namespace PackageName.CompanyName.ProjectName.EntityFrameworkCore;
+
+[ConnectionStringName(ProjectNameDbProperties.ConnectionStringName)]
+public class ProjectNameDbContext : AbpDbContext, IProjectNameDbContext
+{
+ public ProjectNameDbContext(
+ DbContextOptions options) : base(options)
+ {
+ }
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ base.OnModelCreating(modelBuilder);
+
+ modelBuilder.ConfigureProjectName();
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameDbContextFactory.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameDbContextFactory.cs
new file mode 100644
index 000000000..04338731b
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameDbContextFactory.cs
@@ -0,0 +1,49 @@
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Design;
+using Microsoft.Extensions.Configuration;
+using System.IO;
+
+namespace PackageName.CompanyName.ProjectName.EntityFrameworkCore;
+public class ProjectNameDbContextFactory : IDesignTimeDbContextFactory
+{
+ public ProjectNameDbContext CreateDbContext(string[] args)
+ {
+ var configuration = BuildConfiguration();
+ var connectionString = configuration.GetConnectionString("ProjectName");
+
+ DbContextOptionsBuilder builder = null;
+
+#if MySQL
+ builder = new DbContextOptionsBuilder()
+ .UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
+#elif SqlServer
+ builder = new DbContextOptionsBuilder()
+ .UseSqlServer(connectionString);
+#elif Sqlite
+ builder = new DbContextOptionsBuilder()
+ .UseSqlite(connectionString);
+#elif Oracle
+ builder = new DbContextOptionsBuilder()
+ .UseOracle(connectionString);
+#elif OracleDevart
+ builder = (DbContextOptionsBuilder) new DbContextOptionsBuilder()
+ .UseOracle(connectionString);
+#elif PostgreSql
+ builder = new DbContextOptionsBuilder()
+ .UseNpgsql(connectionString);
+#endif
+
+ return new ProjectNameDbContext(builder!.Options);
+ }
+
+ private static IConfigurationRoot BuildConfiguration()
+ {
+ var builder = new ConfigurationBuilder()
+ .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../PackageName.CompanyName.ProjectName.DbMigrator/"))
+ .AddJsonFile("appsettings.json", optional: false)
+ .AddJsonFile("appsettings.Development.json", optional: true);
+
+ return builder.Build();
+ }
+}
+
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameDbContextModelCreatingExtensions.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameDbContextModelCreatingExtensions.cs
new file mode 100644
index 000000000..f812977e6
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameDbContextModelCreatingExtensions.cs
@@ -0,0 +1,21 @@
+using Microsoft.EntityFrameworkCore;
+using System;
+using Volo.Abp;
+
+namespace PackageName.CompanyName.ProjectName.EntityFrameworkCore;
+
+public static class ProjectNameDbContextModelCreatingExtensions
+{
+ public static void ConfigureProjectName(
+ this ModelBuilder builder,
+ Action optionsAction = null)
+ {
+ Check.NotNull(builder, nameof(builder));
+
+ var options = new ProjectNameModelBuilderConfigurationOptions(
+ ProjectNameDbProperties.DbTablePrefix,
+ ProjectNameDbProperties.DbSchema
+ );
+ optionsAction?.Invoke(options);
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameDbMigrationService.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameDbMigrationService.cs
new file mode 100644
index 000000000..ea4490372
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameDbMigrationService.cs
@@ -0,0 +1,234 @@
+using LINGYUN.Abp.Data.DbMigrator;
+using LINGYUN.Abp.Saas.Tenants;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+using PackageName.CompanyName.ProjectName.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+using Volo.Abp.Data;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.MultiTenancy;
+
+namespace PackageName.CompanyName.ProjectName.DbMigrator.EntityFrameworkCore;
+
+public class ProjectNameDbMigrationService : ITransientDependency
+{
+ public ILogger Logger { get; set; }
+
+ private readonly IDataSeeder _dataSeeder;
+ private readonly IDbSchemaMigrator _dbSchemaMigrator;
+ private readonly ITenantRepository _tenantRepository;
+ private readonly ICurrentTenant _currentTenant;
+
+ public ProjectNameDbMigrationService(
+ IDataSeeder dataSeeder,
+ IDbSchemaMigrator dbSchemaMigrator,
+ ITenantRepository tenantRepository,
+ ICurrentTenant currentTenant)
+ {
+ _dataSeeder = dataSeeder;
+ _dbSchemaMigrator = dbSchemaMigrator;
+ _tenantRepository = tenantRepository;
+ _currentTenant = currentTenant;
+
+ Logger = NullLogger.Instance;
+ }
+
+ public async Task MigrateAsync()
+ {
+ var initialMigrationAdded = AddInitialMigrationIfNotExist();
+
+ if (initialMigrationAdded)
+ {
+ return;
+ }
+
+ Logger.LogInformation("Started database migrations...");
+
+ await MigrateDatabaseSchemaAsync();
+ await SeedDataAsync();
+
+ Logger.LogInformation($"Successfully completed host database migrations.");
+
+ var tenants = await _tenantRepository.GetListAsync(includeDetails: true);
+
+ var migratedDatabaseSchemas = new HashSet();
+ foreach (var tenant in tenants)
+ {
+ using (_currentTenant.Change(tenant.Id))
+ {
+ if (tenant.ConnectionStrings.Any())
+ {
+ var tenantConnectionStrings = tenant.ConnectionStrings
+ .Select(x => x.Value)
+ .ToList();
+
+ if (!migratedDatabaseSchemas.IsSupersetOf(tenantConnectionStrings))
+ {
+ await MigrateDatabaseSchemaAsync(tenant);
+
+ migratedDatabaseSchemas.AddIfNotContains(tenantConnectionStrings);
+ }
+ }
+
+ await SeedDataAsync(tenant);
+ }
+
+ Logger.LogInformation($"Successfully completed {tenant.Name} tenant database migrations.");
+ }
+
+ Logger.LogInformation("Successfully completed all database migrations.");
+ Logger.LogInformation("You can safely end this process...");
+ }
+
+ private async Task MigrateDatabaseSchemaAsync(Tenant? tenant = null)
+ {
+ Logger.LogInformation($"Migrating schema for {(tenant == null ? "host" : tenant.Name + " tenant")} database...");
+ // 迁移租户数据
+ await _dbSchemaMigrator.MigrateAsync(
+ (connectionString, builder) =>
+ {
+#if MySQL
+ builder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
+#elif SqlServer
+ builder.UseSqlServer(connectionString);
+#elif Sqlite
+ builder.UseSqlite(connectionString);
+#elif Oracle
+ builder.UseOracle(connectionString);
+#elif OracleDevart
+ builder.UseOracle(connectionString);
+#elif PostgreSql
+ builder.UseNpgsql(connectionString);
+#endif
+
+ return new ProjectNameDbContext(builder.Options);
+ });
+ }
+
+ private async Task SeedDataAsync(Tenant? tenant = null)
+ {
+ Logger.LogInformation($"Executing {(tenant == null ? "host" : tenant.Name + " tenant")} database seed...");
+
+ await _dataSeeder.SeedAsync(tenant?.Id);
+ }
+
+ private bool AddInitialMigrationIfNotExist()
+ {
+ try
+ {
+ if (!DbMigrationsProjectExists())
+ {
+ return false;
+ }
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+
+ try
+ {
+ if (!MigrationsFolderExists())
+ {
+ AddInitialMigration();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.LogWarning("Couldn't determinate if any migrations exist : " + e.Message);
+ return false;
+ }
+ }
+
+ private bool DbMigrationsProjectExists()
+ {
+ return Directory.Exists(GetEntityFrameworkCoreProjectFolderPath());
+ }
+
+ private bool MigrationsFolderExists()
+ {
+ var dbMigrationsProjectFolder = GetEntityFrameworkCoreProjectFolderPath();
+
+ return Directory.Exists(Path.Combine(dbMigrationsProjectFolder, "Migrations"));
+ }
+
+ private void AddInitialMigration()
+ {
+ Logger.LogInformation("Creating initial migration...");
+
+ string argumentPrefix;
+ string fileName;
+
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
+ {
+ argumentPrefix = "-c";
+ fileName = "/bin/bash";
+ }
+ else
+ {
+ argumentPrefix = "/C";
+ fileName = "cmd.exe";
+ }
+
+ var procStartInfo = new ProcessStartInfo(fileName,
+ $"{argumentPrefix} \"abp create-migration-and-run-migrator \"{GetEntityFrameworkCoreProjectFolderPath()}\" --nolayers\""
+ );
+
+ try
+ {
+ Process.Start(procStartInfo);
+ }
+ catch (Exception)
+ {
+ throw new Exception("Couldn't run ABP CLI...");
+ }
+ }
+
+ private string GetEntityFrameworkCoreProjectFolderPath()
+ {
+ var slnDirectoryPath = GetSolutionDirectoryPath();
+
+ if (slnDirectoryPath == null)
+ {
+ throw new Exception("Solution folder not found!");
+ }
+
+ return Path.Combine(slnDirectoryPath, "PackageName.CompanyName.ProjectName.HttpApi.Host");
+ }
+
+ private string? GetSolutionDirectoryPath()
+ {
+ var currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory());
+
+ while (Directory.GetParent(currentDirectory.FullName) != null)
+ {
+ currentDirectory = Directory.GetParent(currentDirectory.FullName);
+
+ if (Directory.GetFiles(currentDirectory!.FullName).FirstOrDefault(f => f.EndsWith(".sln")) != null)
+ {
+ return currentDirectory.FullName;
+ }
+
+ // parent host
+ currentDirectory = Directory.GetParent(currentDirectory.FullName);
+ if (Directory.GetFiles(currentDirectory!.FullName).FirstOrDefault(f => f.EndsWith(".sln")) != null)
+ {
+ return currentDirectory.FullName;
+ }
+ }
+
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameEfCoreQueryableExtensions.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameEfCoreQueryableExtensions.cs
new file mode 100644
index 000000000..eb9a9214b
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameEfCoreQueryableExtensions.cs
@@ -0,0 +1,6 @@
+namespace PackageName.CompanyName.ProjectName.EntityFrameworkCore;
+
+public static class ProjectNameEfCoreQueryableExtensions
+{
+ // 在此聚合仓储服务的扩展方法
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameEntityFrameworkCoreModule.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameEntityFrameworkCoreModule.cs
new file mode 100644
index 000000000..71bab6e63
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameEntityFrameworkCoreModule.cs
@@ -0,0 +1,65 @@
+using LINGYUN.Abp.Data.DbMigrator;
+using LINGYUN.Abp.Saas.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.Modularity;
+#if MySQL
+using Volo.Abp.EntityFrameworkCore.MySQL;
+#elif SqlServer
+using Volo.Abp.EntityFrameworkCore.SqlServer;
+#elif Sqlite
+using Volo.Abp.EntityFrameworkCore.Sqlite;
+#elif Oracle
+using Volo.Abp.EntityFrameworkCore.Oracle;
+#elif OracleDevart
+using Volo.Abp.EntityFrameworkCore.Oracle.Devart;
+#elif PostgreSql
+using Volo.Abp.EntityFrameworkCore.PostgreSql;
+#endif
+
+namespace PackageName.CompanyName.ProjectName.EntityFrameworkCore;
+
+[DependsOn(
+ typeof(ProjectNameDomainModule),
+ typeof(AbpDataDbMigratorModule),
+ typeof(AbpEntityFrameworkCoreModule),
+#if MySQL
+ typeof(AbpEntityFrameworkCoreMySQLModule),
+#elif SqlServer
+ typeof(AbpEntityFrameworkCoreSqlServerModule),
+#elif Sqlite
+ typeof(AbpEntityFrameworkCoreSqliteModule),
+#elif Oracle
+ typeof(AbpEntityFrameworkCoreOracleModule),
+#elif OracleDevart
+ typeof(AbpEntityFrameworkCoreOracleDevartModule),
+#elif PostgreSql
+ typeof(AbpEntityFrameworkCorePostgreSqlModule),
+#endif
+ typeof(AbpSaasEntityFrameworkCoreModule))]
+public class ProjectNameEntityFrameworkCoreModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ // 配置Ef
+ Configure(options =>
+ {
+#if MySQL
+ options.UseMySQL();
+#elif SqlServer
+ options.UseSqlServer();
+#elif Sqlite
+ options.UseSqlite();
+#elif Oracle || OracleDevart
+ options.UseOracle();
+#elif PostgreSql
+ options.UseNpgsql();
+#endif
+ });
+
+ context.Services.AddAbpDbContext(options =>
+ {
+ options.AddDefaultRepositories();
+ });
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameModelBuilderConfigurationOptions.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameModelBuilderConfigurationOptions.cs
new file mode 100644
index 000000000..ba62d48a8
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.EntityFrameworkCore/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameModelBuilderConfigurationOptions.cs
@@ -0,0 +1,17 @@
+using JetBrains.Annotations;
+using Volo.Abp.EntityFrameworkCore.Modeling;
+
+namespace PackageName.CompanyName.ProjectName.EntityFrameworkCore;
+
+public class ProjectNameModelBuilderConfigurationOptions : AbpModelBuilderConfigurationOptions
+{
+ public ProjectNameModelBuilderConfigurationOptions(
+ [NotNull] string tablePrefix = "",
+ [CanBeNull] string schema = null)
+ : base(
+ tablePrefix,
+ schema)
+ {
+
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi.Client/FodyWeavers.xml b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi.Client/FodyWeavers.xml
new file mode 100644
index 000000000..1715698cc
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi.Client/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi.Client/FodyWeavers.xsd b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi.Client/FodyWeavers.xsd
new file mode 100644
index 000000000..11da52550
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi.Client/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi.Client/PackageName.CompanyName.ProjectName.HttpApi.Client.csproj b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi.Client/PackageName.CompanyName.ProjectName.HttpApi.Client.csproj
new file mode 100644
index 000000000..3931245c0
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi.Client/PackageName.CompanyName.ProjectName.HttpApi.Client.csproj
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi.Client/PackageName/CompanyName/ProjectName/ProjectNameHttpApiClientModule.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi.Client/PackageName/CompanyName/ProjectName/ProjectNameHttpApiClientModule.cs
new file mode 100644
index 000000000..ea6a14c25
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi.Client/PackageName/CompanyName/ProjectName/ProjectNameHttpApiClientModule.cs
@@ -0,0 +1,18 @@
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Http.Client;
+using Volo.Abp.Modularity;
+
+namespace PackageName.CompanyName.ProjectName;
+
+[DependsOn(
+ typeof(AbpHttpClientModule),
+ typeof(ProjectNameApplicationContractsModule))]
+public class ProjectNameHttpApiClientModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddHttpClientProxies(
+ typeof(ProjectNameApplicationContractsModule).Assembly,
+ ProjectNameRemoteServiceConsts.RemoteServiceName);
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi/FodyWeavers.xml b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi/FodyWeavers.xml
new file mode 100644
index 000000000..1715698cc
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi/FodyWeavers.xsd b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi/FodyWeavers.xsd
new file mode 100644
index 000000000..11da52550
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi/PackageName.CompanyName.ProjectName.HttpApi.csproj b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi/PackageName.CompanyName.ProjectName.HttpApi.csproj
new file mode 100644
index 000000000..1cc138d19
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi/PackageName.CompanyName.ProjectName.HttpApi.csproj
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+ net7.0
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi/PackageName/CompanyName/ProjectName/ProjectNameControllerBase.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi/PackageName/CompanyName/ProjectName/ProjectNameControllerBase.cs
new file mode 100644
index 000000000..6797f475c
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi/PackageName/CompanyName/ProjectName/ProjectNameControllerBase.cs
@@ -0,0 +1,12 @@
+using PackageName.CompanyName.ProjectName.Localization;
+using Volo.Abp.AspNetCore.Mvc;
+
+namespace PackageName.CompanyName.ProjectName;
+
+public abstract class ProjectNameControllerBase : AbpControllerBase
+{
+ protected ProjectNameControllerBase()
+ {
+ LocalizationResource = typeof(ProjectNameResource);
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi/PackageName/CompanyName/ProjectName/ProjectNameDynamicQueryableControllerBase.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi/PackageName/CompanyName/ProjectName/ProjectNameDynamicQueryableControllerBase.cs
new file mode 100644
index 000000000..865145f86
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi/PackageName/CompanyName/ProjectName/ProjectNameDynamicQueryableControllerBase.cs
@@ -0,0 +1,17 @@
+using LINGYUN.Abp.Dynamic.Queryable;
+using PackageName.CompanyName.ProjectName.Localization;
+
+namespace PackageName.CompanyName.ProjectName;
+///
+/// 提供动态查询控制器实现
+///
+/// 实体dto类型
+public abstract class ProjectNameDynamicQueryableControllerBase : DynamicQueryableControllerBase
+{
+ protected ProjectNameDynamicQueryableControllerBase(
+ IDynamicQueryableAppService service)
+ : base(service)
+ {
+ LocalizationResource = typeof(ProjectNameResource);
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi/PackageName/CompanyName/ProjectName/ProjectNameHttpApiModule.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi/PackageName/CompanyName/ProjectName/ProjectNameHttpApiModule.cs
new file mode 100644
index 000000000..90dccd31c
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.HttpApi/PackageName/CompanyName/ProjectName/ProjectNameHttpApiModule.cs
@@ -0,0 +1,42 @@
+using PackageName.CompanyName.ProjectName.Localization;
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.AspNetCore.Mvc;
+using Volo.Abp.AspNetCore.Mvc.Localization;
+using Volo.Abp.Localization;
+using Volo.Abp.Modularity;
+using Volo.Abp.Validation.Localization;
+using LINGYUN.Abp.Dynamic.Queryable;
+
+namespace PackageName.CompanyName.ProjectName;
+
+[DependsOn(
+ typeof(AbpAspNetCoreMvcModule),
+ typeof(ProjectNameApplicationContractsModule),
+ typeof(AbpDynamicQueryableHttpApiModule))]
+public class ProjectNameHttpApiModule : AbpModule
+{
+ public override void PreConfigureServices(ServiceConfigurationContext context)
+ {
+ PreConfigure(mvcBuilder =>
+ {
+ mvcBuilder.AddApplicationPartIfNotExists(typeof(ProjectNameHttpApiModule).Assembly);
+ });
+
+ PreConfigure(options =>
+ {
+ options.AddAssemblyResource(
+ typeof(ProjectNameResource),
+ typeof(ProjectNameApplicationContractsModule).Assembly);
+ });
+ }
+
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ Configure(options =>
+ {
+ options.Resources
+ .Get()
+ .AddBaseTypes(typeof(AbpValidationResource));
+ });
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.SettingManagement/FodyWeavers.xml b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.SettingManagement/FodyWeavers.xml
new file mode 100644
index 000000000..1715698cc
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.SettingManagement/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.SettingManagement/FodyWeavers.xsd b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.SettingManagement/FodyWeavers.xsd
new file mode 100644
index 000000000..11da52550
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.SettingManagement/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.SettingManagement/PackageName.CompanyName.ProjectName.SettingManagement.csproj b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.SettingManagement/PackageName.CompanyName.ProjectName.SettingManagement.csproj
new file mode 100644
index 000000000..965086211
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.SettingManagement/PackageName.CompanyName.ProjectName.SettingManagement.csproj
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+ net7.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.SettingManagement/PackageName/CompanyName/ProjectName/SettingManagement/IProjectNameSettingAppService.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.SettingManagement/PackageName/CompanyName/ProjectName/SettingManagement/IProjectNameSettingAppService.cs
new file mode 100644
index 000000000..308135ed0
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.SettingManagement/PackageName/CompanyName/ProjectName/SettingManagement/IProjectNameSettingAppService.cs
@@ -0,0 +1,7 @@
+using LINGYUN.Abp.SettingManagement;
+
+namespace PackageName.CompanyName.ProjectName.SettingManagement;
+
+public interface IProjectNameSettingAppService : ISettingAppService, IUserSettingAppService
+{
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.SettingManagement/PackageName/CompanyName/ProjectName/SettingManagement/ProjectNameSettingAppService.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.SettingManagement/PackageName/CompanyName/ProjectName/SettingManagement/ProjectNameSettingAppService.cs
new file mode 100644
index 000000000..52641171c
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.SettingManagement/PackageName/CompanyName/ProjectName/SettingManagement/ProjectNameSettingAppService.cs
@@ -0,0 +1,106 @@
+using LINGYUN.Abp.SettingManagement;
+using Microsoft.AspNetCore.Authorization;
+using PackageName.CompanyName.ProjectName.Authorization;
+using PackageName.CompanyName.ProjectName.Localization;
+using System.Threading.Tasks;
+using Volo.Abp.Application.Services;
+using Volo.Abp.Features;
+using Volo.Abp.MultiTenancy;
+using Volo.Abp.SettingManagement;
+using Volo.Abp.Settings;
+using Volo.Abp.Users;
+
+namespace PackageName.CompanyName.ProjectName.SettingManagement;
+
+public class ProjectNameSettingAppService : ApplicationService, IProjectNameSettingAppService
+{
+ protected ISettingManager SettingManager { get; }
+ protected ISettingDefinitionManager SettingDefinitionManager { get; }
+
+ public ProjectNameSettingAppService(
+ ISettingManager settingManager,
+ ISettingDefinitionManager settingDefinitionManager)
+ {
+ SettingManager = settingManager;
+ SettingDefinitionManager = settingDefinitionManager;
+ LocalizationResource = typeof(ProjectNameResource);
+ }
+
+ public virtual async Task GetAllForCurrentTenantAsync()
+ {
+ return await GetAllForProviderAsync(TenantSettingValueProvider.ProviderName, CurrentTenant.GetId().ToString());
+ }
+
+ [Authorize]
+ public virtual async Task GetAllForCurrentUserAsync()
+ {
+ return await GetAllForProviderAsync(UserSettingValueProvider.ProviderName, CurrentUser.GetId().ToString());
+ }
+
+ public virtual async Task GetAllForGlobalAsync()
+ {
+ return await GetAllForProviderAsync(GlobalSettingValueProvider.ProviderName, null);
+ }
+
+ [Authorize(ProjectNamePermissions.ManageSettings)]
+ public virtual async Task SetCurrentTenantAsync(UpdateSettingsDto input)
+ {
+ // 增加特性检查
+ await CheckFeatureAsync();
+
+ if (CurrentTenant.IsAvailable)
+ {
+ foreach (var setting in input.Settings)
+ {
+ await SettingManager.SetForTenantAsync(CurrentTenant.GetId(), setting.Name, setting.Value);
+ }
+
+ await CurrentUnitOfWork.SaveChangesAsync();
+ }
+ }
+
+ [Authorize]
+ public virtual async Task SetCurrentUserAsync(UpdateSettingsDto input)
+ {
+ // 增加特性检查
+ await CheckFeatureAsync();
+
+ foreach (var setting in input.Settings)
+ {
+ await SettingManager.SetForCurrentUserAsync(setting.Name, setting.Value);
+ }
+
+ await CurrentUnitOfWork.SaveChangesAsync();
+ }
+
+ [Authorize(ProjectNamePermissions.ManageSettings)]
+ public virtual async Task SetGlobalAsync(UpdateSettingsDto input)
+ {
+ // 增加特性检查
+ await CheckFeatureAsync();
+
+ foreach (var setting in input.Settings)
+ {
+ await SettingManager.SetGlobalAsync(setting.Name, setting.Value);
+ }
+
+ await CurrentUnitOfWork.SaveChangesAsync();
+ }
+
+
+ protected virtual async Task CheckFeatureAsync()
+ {
+ await FeatureChecker.CheckEnabledAsync(SettingManagementFeatures.Enable);
+ }
+
+ protected virtual async Task GetAllForProviderAsync(string providerName, string providerKey)
+ {
+ var settingGroups = new SettingGroupResult();
+
+ //TODO: 当前项目所有配置项在此定义返回
+
+ await Task.CompletedTask;
+
+ return settingGroups;
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.SettingManagement/PackageName/CompanyName/ProjectName/SettingManagement/ProjectNameSettingController.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.SettingManagement/PackageName/CompanyName/ProjectName/SettingManagement/ProjectNameSettingController.cs
new file mode 100644
index 000000000..0351f10ad
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.SettingManagement/PackageName/CompanyName/ProjectName/SettingManagement/ProjectNameSettingController.cs
@@ -0,0 +1,68 @@
+using LINGYUN.Abp.SettingManagement;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using PackageName.CompanyName.ProjectName.Authorization;
+using System.Threading.Tasks;
+using Volo.Abp;
+using Volo.Abp.AspNetCore.Mvc;
+
+namespace PackageName.CompanyName.ProjectName.SettingManagement;
+
+[RemoteService(Name = ProjectNameRemoteServiceConsts.RemoteServiceName)]
+[ApiVersion("2.0")]
+[Area(ProjectNameRemoteServiceConsts.ModuleName)]
+[Route("api/ProjectName/settings")]
+public class ProjectNameSettingController : AbpController, IProjectNameSettingAppService
+{
+ private readonly IProjectNameSettingAppService _settingAppService;
+ public ProjectNameSettingController(IProjectNameSettingAppService settingAppService)
+ {
+ _settingAppService = settingAppService;
+ }
+
+ [Authorize(ProjectNamePermissions.ManageSettings)]
+ [HttpPut]
+ [Route("by-current-tenant")]
+ public virtual async Task SetCurrentTenantAsync(UpdateSettingsDto input)
+ {
+ await _settingAppService.SetCurrentTenantAsync(input);
+ }
+
+ [HttpGet]
+ [Route("by-current-tenant")]
+ public virtual async Task GetAllForCurrentTenantAsync()
+ {
+ return await _settingAppService.GetAllForCurrentTenantAsync();
+ }
+
+ [Authorize]
+ [HttpPut]
+ [Route("by-current-user")]
+ public virtual async Task SetCurrentUserAsync(UpdateSettingsDto input)
+ {
+ await _settingAppService.SetCurrentTenantAsync(input);
+ }
+
+ [Authorize]
+ [HttpGet]
+ [Route("by-current-user")]
+ public virtual async Task GetAllForCurrentUserAsync()
+ {
+ return await _settingAppService.GetAllForCurrentTenantAsync();
+ }
+
+ [Authorize(ProjectNamePermissions.ManageSettings)]
+ [HttpPut]
+ [Route("by-global")]
+ public virtual async Task SetGlobalAsync(UpdateSettingsDto input)
+ {
+ await _settingAppService.SetGlobalAsync(input);
+ }
+
+ [HttpGet]
+ [Route("by-global")]
+ public virtual async Task GetAllForGlobalAsync()
+ {
+ return await _settingAppService.GetAllForGlobalAsync();
+ }
+}
diff --git a/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.SettingManagement/PackageName/CompanyName/ProjectName/SettingManagement/ProjectNameSettingManagementModule.cs b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.SettingManagement/PackageName/CompanyName/ProjectName/SettingManagement/ProjectNameSettingManagementModule.cs
new file mode 100644
index 000000000..09eb20393
--- /dev/null
+++ b/aspnet-core/templates/content/src/PackageName.CompanyName.ProjectName.SettingManagement/PackageName/CompanyName/ProjectName/SettingManagement/ProjectNameSettingManagementModule.cs
@@ -0,0 +1,22 @@
+using LINGYUN.Abp.SettingManagement;
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.AspNetCore.Mvc;
+using Volo.Abp.Modularity;
+using Volo.Abp.SettingManagement;
+
+namespace PackageName.CompanyName.ProjectName.SettingManagement;
+
+[DependsOn(
+ typeof(AbpSettingManagementApplicationContractsModule),
+ typeof(AbpAspNetCoreMvcModule),
+ typeof(AbpSettingManagementDomainModule))]
+public class ProjectNameSettingManagementModule : AbpModule
+{
+ public override void PreConfigureServices(ServiceConfigurationContext context)
+ {
+ PreConfigure(mvcBuilder =>
+ {
+ mvcBuilder.AddApplicationPartIfNotExists(typeof(ProjectNameSettingManagementModule).Assembly);
+ });
+ }
+}
diff --git a/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName.CompanyName.ProjectName.Application.Tests.csproj b/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName.CompanyName.ProjectName.Application.Tests.csproj
new file mode 100644
index 000000000..f22579773
--- /dev/null
+++ b/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName.CompanyName.ProjectName.Application.Tests.csproj
@@ -0,0 +1,18 @@
+
+
+
+ net7.0
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName/CompanyName/ProjectName/ProjectNameApplicationTestBase.cs b/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName/CompanyName/ProjectName/ProjectNameApplicationTestBase.cs
new file mode 100644
index 000000000..81ea710fc
--- /dev/null
+++ b/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName/CompanyName/ProjectName/ProjectNameApplicationTestBase.cs
@@ -0,0 +1,6 @@
+namespace PackageName.CompanyName.ProjectName
+{
+ public abstract class ProjectNameApplicationTestBase : ProjectNameTestBase
+ {
+ }
+}
diff --git a/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName/CompanyName/ProjectName/ProjectNameApplicationTestModule.cs b/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName/CompanyName/ProjectName/ProjectNameApplicationTestModule.cs
new file mode 100644
index 000000000..6d74be333
--- /dev/null
+++ b/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.Application.Tests/PackageName/CompanyName/ProjectName/ProjectNameApplicationTestModule.cs
@@ -0,0 +1,12 @@
+using Volo.Abp.Modularity;
+
+namespace PackageName.CompanyName.ProjectName
+{
+ [DependsOn(
+ typeof(ProjectNameDomainTestModule),
+ typeof(ProjectNameApplicationModule)
+ )]
+ public class ProjectNameApplicationTestModule : AbpModule
+ {
+ }
+}
diff --git a/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.Domain.Tests/PackageName.CompanyName.ProjectName.Domain.Tests.csproj b/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.Domain.Tests/PackageName.CompanyName.ProjectName.Domain.Tests.csproj
new file mode 100644
index 000000000..45a33d2f7
--- /dev/null
+++ b/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.Domain.Tests/PackageName.CompanyName.ProjectName.Domain.Tests.csproj
@@ -0,0 +1,18 @@
+
+
+
+ net7.0
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.Domain.Tests/PackageName/CompanyName/ProjectName/ProjectNameDomainTestBase.cs b/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.Domain.Tests/PackageName/CompanyName/ProjectName/ProjectNameDomainTestBase.cs
new file mode 100644
index 000000000..f33c7a00d
--- /dev/null
+++ b/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.Domain.Tests/PackageName/CompanyName/ProjectName/ProjectNameDomainTestBase.cs
@@ -0,0 +1,6 @@
+namespace PackageName.CompanyName.ProjectName
+{
+ public abstract class ProjectNameDomainTestBase : ProjectNameTestBase
+ {
+ }
+}
diff --git a/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.Domain.Tests/PackageName/CompanyName/ProjectName/ProjectNameDomainTestModule.cs b/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.Domain.Tests/PackageName/CompanyName/ProjectName/ProjectNameDomainTestModule.cs
new file mode 100644
index 000000000..16404a73f
--- /dev/null
+++ b/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.Domain.Tests/PackageName/CompanyName/ProjectName/ProjectNameDomainTestModule.cs
@@ -0,0 +1,12 @@
+using Volo.Abp.Modularity;
+
+namespace PackageName.CompanyName.ProjectName
+{
+ [DependsOn(
+ typeof(ProjectNameTestBaseModule),
+ typeof(ProjectNameDomainModule)
+ )]
+ public class ProjectNameDomainTestModule : AbpModule
+ {
+ }
+}
diff --git a/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.EntityFrameworkCore.Tests/PackageName.CompanyName.ProjectName.EntityFrameworkCore.Tests.csproj b/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.EntityFrameworkCore.Tests/PackageName.CompanyName.ProjectName.EntityFrameworkCore.Tests.csproj
new file mode 100644
index 000000000..d402ff4e3
--- /dev/null
+++ b/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.EntityFrameworkCore.Tests/PackageName.CompanyName.ProjectName.EntityFrameworkCore.Tests.csproj
@@ -0,0 +1,19 @@
+
+
+
+ net7.0
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.EntityFrameworkCore.Tests/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameEntityFrameworkCoreTestBase.cs b/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.EntityFrameworkCore.Tests/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameEntityFrameworkCoreTestBase.cs
new file mode 100644
index 000000000..7fd73c607
--- /dev/null
+++ b/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.EntityFrameworkCore.Tests/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameEntityFrameworkCoreTestBase.cs
@@ -0,0 +1,6 @@
+namespace PackageName.CompanyName.ProjectName.EntityFrameworkCore
+{
+ public abstract class ProjectNameEntityFrameworkCoreTestBase : ProjectNameTestBase
+ {
+ }
+}
diff --git a/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.EntityFrameworkCore.Tests/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameEntityFrameworkCoreTestModule.cs b/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.EntityFrameworkCore.Tests/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameEntityFrameworkCoreTestModule.cs
new file mode 100644
index 000000000..39f7d3e43
--- /dev/null
+++ b/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.EntityFrameworkCore.Tests/PackageName/CompanyName/ProjectName/EntityFrameworkCore/ProjectNameEntityFrameworkCoreTestModule.cs
@@ -0,0 +1,39 @@
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.Modularity;
+using Volo.Abp.Uow;
+
+namespace PackageName.CompanyName.ProjectName.EntityFrameworkCore
+{
+ [DependsOn(
+ typeof(ProjectNameTestBaseModule),
+ typeof(ProjectNameEntityFrameworkCoreModule)
+ )]
+ public class ProjectNameEntityFrameworkCoreTestModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddEntityFrameworkInMemoryDatabase();
+
+ var databaseName = Guid.NewGuid().ToString();
+
+ Configure(options =>
+ {
+ options.Configure(abpDbContextConfigurationContext =>
+ {
+ abpDbContextConfigurationContext.DbContextOptions.EnableDetailedErrors();
+ abpDbContextConfigurationContext.DbContextOptions.EnableSensitiveDataLogging();
+
+ abpDbContextConfigurationContext.DbContextOptions.UseInMemoryDatabase(databaseName);
+ });
+ });
+
+ Configure(options =>
+ {
+ options.TransactionBehavior = UnitOfWorkTransactionBehavior.Disabled; //EF in-memory database does not support transactions
+ });
+ }
+ }
+}
diff --git a/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.TestBase/PackageName.CompanyName.ProjectName.TestBase.csproj b/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.TestBase/PackageName.CompanyName.ProjectName.TestBase.csproj
new file mode 100644
index 000000000..08a729680
--- /dev/null
+++ b/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.TestBase/PackageName.CompanyName.ProjectName.TestBase.csproj
@@ -0,0 +1,23 @@
+
+
+
+ net7.0
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.TestBase/PackageName/CompanyName/ProjectName/ProjectNameTestBase.cs b/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.TestBase/PackageName/CompanyName/ProjectName/ProjectNameTestBase.cs
new file mode 100644
index 000000000..825525f0a
--- /dev/null
+++ b/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.TestBase/PackageName/CompanyName/ProjectName/ProjectNameTestBase.cs
@@ -0,0 +1,59 @@
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Threading.Tasks;
+using Volo.Abp;
+using Volo.Abp.Modularity;
+using Volo.Abp.Testing;
+using Volo.Abp.Uow;
+
+namespace PackageName.CompanyName.ProjectName
+{
+ public abstract class ProjectNameTestBase : AbpIntegratedTest
+ where TStartupModule : IAbpModule
+ {
+ protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
+ {
+ options.UseAutofac();
+ }
+
+ protected virtual Task WithUnitOfWorkAsync(Func func)
+ {
+ return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func);
+ }
+
+ protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func action)
+ {
+ using (var scope = ServiceProvider.CreateScope())
+ {
+ var uowManager = scope.ServiceProvider.GetRequiredService();
+
+ using (var uow = uowManager.Begin(options))
+ {
+ await action();
+
+ await uow.CompleteAsync();
+ }
+ }
+ }
+
+ protected virtual Task WithUnitOfWorkAsync(Func> func)
+ {
+ return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func);
+ }
+
+ protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func> func)
+ {
+ using (var scope = ServiceProvider.CreateScope())
+ {
+ var uowManager = scope.ServiceProvider.GetRequiredService();
+
+ using (var uow = uowManager.Begin(options))
+ {
+ var result = await func();
+ await uow.CompleteAsync();
+ return result;
+ }
+ }
+ }
+ }
+}
diff --git a/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.TestBase/PackageName/CompanyName/ProjectName/ProjectNameTestBaseModule.cs b/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.TestBase/PackageName/CompanyName/ProjectName/ProjectNameTestBaseModule.cs
new file mode 100644
index 000000000..a24ec432c
--- /dev/null
+++ b/aspnet-core/templates/content/tests/PackageName.CompanyName.ProjectName.TestBase/PackageName/CompanyName/ProjectName/ProjectNameTestBaseModule.cs
@@ -0,0 +1,25 @@
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp;
+using Volo.Abp.Authorization;
+using Volo.Abp.Autofac;
+using Volo.Abp.Features;
+using Volo.Abp.MemoryDb;
+using Volo.Abp.Modularity;
+
+namespace PackageName.CompanyName.ProjectName
+{
+ [DependsOn(
+ typeof(AbpAutofacModule),
+ typeof(AbpTestBaseModule),
+ typeof(AbpAuthorizationModule),
+ typeof(AbpFeaturesModule),
+ typeof(AbpMemoryDbModule)
+ )]
+ public class ProjectNameTestBaseModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddAlwaysAllowAuthorization();
+ }
+ }
+}