Browse Source

Merge pull request #4 from abpframework/dev

merge
pull/2019/head
Marcelo M. M 7 years ago
committed by GitHub
parent
commit
d84bcb4253
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 82
      docs/en/Caching.md
  2. 5
      docs/en/Multi-Tenancy.md
  3. 257
      docs/en/Object-To-Object-Mapping.md
  4. 7
      docs/en/docs-nav.json
  5. 2
      docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md
  6. 4
      docs/zh-Hans/Multi-Tenancy.md
  7. 20
      framework/src/Volo.Abp.Autofac/Microsoft/Extensions/Hosting/AbpAutofacHostBuilderExtensions.cs
  8. 1
      framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj
  9. 1
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs
  10. 169
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GetSourceCommand.cs
  11. 8
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs
  12. 3
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs
  13. 12
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/AbpIoApiKeyService.cs
  14. 3
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/IApiKeyService.cs
  15. 13
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs
  16. 71
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs
  17. 19
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Analyticses/CliAnalyticsCollect.cs
  18. 11
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ModuleInfo.cs
  19. 19
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ModuleProjectBuildPipelineBuilder.cs
  20. 9
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildContext.cs
  21. 20
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectReferenceReplaceStep.cs
  22. 3
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/RenameHelper.cs
  23. 96
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ReplaceCommonPropsStep.cs
  24. 17
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SolutionRenameStep.cs
  25. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs
  26. 10
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/IModuleInfoProvider.cs
  27. 12
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/IRemoteServiceExceptionHandler.cs
  28. 3
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ISourceCodeStore.cs
  29. 58
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ModuleInfoProvider.cs
  30. 109
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ModuleProjectBuilder.cs
  31. 92
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/RemoteServiceExceptionHandler.cs
  32. 9
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/SourceCodeTypes.cs
  33. 21
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs
  34. 32
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs
  35. 1
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/EfCoreMigrationAdder.cs
  36. 1
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmPackagesUpdater.cs
  37. 1
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/PackageJsonFileFinder.cs
  38. 8
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNugetPackageAdder.cs
  39. 8
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs
  40. 19
      framework/src/Volo.Abp.Core/System/AbpStringExtensions.cs
  41. 4
      framework/src/Volo.Abp.Core/Volo/Abp/Configuration/IConfigurationAccessor.cs
  42. 15
      framework/src/Volo.Abp.Core/Volo/Abp/Internal/InternalServiceCollectionExtensions.cs
  43. 18
      framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpCommonDbProperties.cs
  44. 2
      framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo.Abp.EntityFrameworkCore.PostgreSql.csproj
  45. 12
      framework/test/Volo.Abp.Core.Tests/System/StringExtensions_Tests.cs
  46. 5
      modules/account/src/Volo.Abp.Account.Web.IdentityServer/AbpAccountWebIdentityServerModule.cs
  47. 5
      modules/account/src/Volo.Abp.Account.Web/AbpAccountWebModule.cs
  48. 12
      modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AbpAuditLoggingConsts.cs
  49. 13
      modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AbpAuditLoggingDbProperties.cs
  50. 8
      modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingDbContext.cs
  51. 27
      modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingDbContextModelBuilderExtensions.cs
  52. 18
      modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingModelBuilderConfigurationOptions.cs
  53. 4
      modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs
  54. 2
      modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/IAuditLoggingDbContext.cs
  55. 6
      modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/AbpAuditLoggingMongoDbContextExtensions.cs
  56. 9
      modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/AuditLoggingMongoDbContext.cs
  57. 5
      modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/AuditLoggingMongoModelBuilderConfigurationOptions.cs
  58. 2
      modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/IAuditLoggingMongoDbContext.cs
  59. 4
      modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs
  60. 11
      modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobsConsts.cs
  61. 13
      modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobsDbProperties.cs
  62. 12
      modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/BackgroundJobsDbContext.cs
  63. 5
      modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/BackgroundJobsDbContextModelCreatingExtensions.cs
  64. 4
      modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/BackgroundJobsModelBuilderConfigurationOptions.cs
  65. 2
      modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/IBackgroundJobsDbContext.cs
  66. 9
      modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/BackgroundJobsMongoDbContext.cs
  67. 4
      modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/BackgroundJobsMongoDbContextExtensions.cs
  68. 4
      modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/BackgroundJobsMongoModelBuilderConfigurationOptions.cs
  69. 2
      modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/IBackgroundJobsMongoDbContext.cs
  70. 9
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/BloggingConsts.cs
  71. 20
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/BloggingDbProperties.cs
  72. 11
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/BloggingDbContext.cs
  73. 6
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/BloggingDbContextModelBuilderExtensions.cs
  74. 9
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/BloggingModelBuilderConfigurationOptions.cs
  75. 2
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/IBloggingDbContext.cs
  76. 14
      modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/MongoDB/BloggingMongoDbContext.cs
  77. 6
      modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/MongoDB/BloggingMongoDbContextExtensions.cs
  78. 10
      modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/MongoDB/BloggingMongoModelBuilderConfigurationOptions.cs
  79. 2
      modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/MongoDB/IBloggingMongoDbContext.cs
  80. 5
      modules/blogging/src/Volo.Blogging.Web/BloggingWebModule.cs
  81. 5
      modules/docs/src/Volo.Docs.Admin.Web/DocsAdminWebModule.cs
  82. 11
      modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsConsts.cs
  83. 11
      modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDbProperties.cs
  84. 11
      modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContext.cs
  85. 6
      modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContextModelBuilderExtensions.cs
  86. 9
      modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsModelBuilderConfigurationOptions.cs
  87. 2
      modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/IDocsDbContext.cs
  88. 9
      modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/MongoDB/DocsMongoDbContext.cs
  89. 7
      modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/MongoDB/DocsMongoDbContextExtensions.cs
  90. 10
      modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/MongoDB/DocsMongoModelBuilderConfigurationOptions.cs
  91. 2
      modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/MongoDB/IDocsMongoDbContext.cs
  92. 5
      modules/docs/src/Volo.Docs.Web/DocsWebModule.cs
  93. 2
      modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo.Abp.FeatureManagement.Domain.Shared.csproj
  94. 2
      modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/AbpFeatureManagementDomainSharedModule.cs
  95. 2
      modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en.json
  96. 5
      modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo.Abp.FeatureManagement.Domain.csproj
  97. 12
      modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/AbpFeatureManagementDomainModule.cs
  98. 11
      modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManagementConsts.cs
  99. 13
      modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManagementDbProperties.cs
  100. 6
      modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/cs.json

82
docs/en/Caching.md

@ -1,3 +1,85 @@
# Caching # Caching
ABP framework extends ASP.NET Core's distributed caching system.
## IDistributedCache Interface
ASP.NET Core defines the `IDistributedCache` interface to get/set cache values. But it has some difficulties:
* It works with **byte arrays** rather than .NET objects. So, you need to **serialize/deserialize** the objects you need to cache.
* It provides a **single key pool** for all cache items, so;
* You need to care about the keys to distinguish **different type of objects**.
* You need to care about the cache items of **different tenants** (see [multi-tenancy](Multi-Tenancy.md)).
> `IDistributedCache` is defined in the `Microsoft.Extensions.Caching.Abstractions` package. That means it is not only usable for ASP.NET Core applications, but also available to **any type of applications**.
> Default implementation of the `IDistributedCache` interface is the `MemoryDistributedCache` which works **in-memory**. See [ASP.NET Core's documentation](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed) to see how to switch to **Redis** or another cache provider.
See [ASP.NET Core's distributed caching document](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed) for more information.
## IDistributedCache<TCacheItem> Interface
ABP framework defines the generic `IDistributedCache<TCacheItem>` interface in the [Volo.Abp.Caching](https://www.nuget.org/packages/Volo.Abp.Caching/) package. `TCacheItem` is the type of the object stored in the cache.
`IDistributedCache<TCacheItem>` solves the difficulties explained above;
* It internally **serializes/deserializes** the cached objects. Uses **JSON** serialization by default, but can be overridden by replacing the `IDistributedCacheSerializer` service in the [dependency injection](Dependency-Injection.md) system.
* It automatically adds a **cache name** prefix to the cache keys based on the object type stored in the cache. Default cache name is the full name of the cache item class (`CacheItem` postfix is removed if your cache item class ends with it). You can use the `CacheName` attribute on the cache item class to set the cache name.
* It automatically adds the **current tenant id** to the cache key to distinguish cache items for different tenants (only works if your application is [multi-tenant](Multi-Tenancy.md)). Define `IgnoreMultiTenancy` attribute on the cache item class to disable this if you want to share the cached objects among all tenants in a multi-tenant application.
* Allows to define a **global cache key prefix** per application, so different applications can use their isolated key pools in a shared distributed cache source.
### Usage
An example class to store an item in the cache:
````csharp
public class BookCacheItem
{
public string Name { get; set; }
public float Price { get; set; }
}
````
You can inject and use the `IDistributedCache<BookCacheItem>` service to get/set `BookCacheItem` objects.
Example usage:
````csharp
public class BookService : ITransientDependency
{
private readonly IDistributedCache<BookCacheItem> _cache;
public BookService(IDistributedCache<BookCacheItem> cache)
{
_cache = cache;
}
public async Task<BookCacheItem> GetAsync(Guid bookId)
{
return await _cache.GetOrAddAsync(
bookId.ToString(), //Cache key
async () => await GetBookFromDatabaseAsync(bookId),
() => new DistributedCacheEntryOptions
{
AbsoluteExpiration = DateTimeOffset.Now.AddHours(1)
}
);
}
private Task<BookCacheItem> GetBookFromDatabaseAsync(Guid bookId)
{
//TODO: get from database
}
}
````
* This sample service uses the `GetOrAddAsync()` method to get a book item from the cache.
* If the book was not found in the cache, it calls the factory method (`GetBookFromDatabaseAsync` in this case) to retrieve the book item from the original source.
* `GetOrAddAsync` optionally gets a `DistributedCacheEntryOptions` which can be used to set the lifetime of the cached item.
Other methods of the `IDistributedCache<BookCacheItem>` are same as ASP.NET Core's `IDistributedCache` interface, so you can refer [it's documentation](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed).
### DistributedCacheOptions
TODO TODO

5
docs/en/Multi-Tenancy.md

@ -307,6 +307,11 @@ Volo.Abp.AspNetCore.MultiTenancy package adds following tenant resolvers to dete
* **HeaderTenantResolver**: Tries to find current tenant id from HTTP header. Header name is "__tenant" by default. * **HeaderTenantResolver**: Tries to find current tenant id from HTTP header. Header name is "__tenant" by default.
* **CookieTenantResolver**: Tries to find current tenant id from cookie values. Cookie name is "__tenant" by default. * **CookieTenantResolver**: Tries to find current tenant id from cookie values. Cookie name is "__tenant" by default.
> If you use nginx as a reverse proxy server, please note that if `TenantKey` contains an underscore or other special characters, there may be a problem, please refer to:
http://nginx.org/en/docs/http/ngx_http_core_module.html#ignore_invalid_headers
http://nginx.org/en/docs/http/ngx_http_core_module.html#underscores_in_headers
"__tenant" parameter name can be changed using AspNetCoreMultiTenancyOptions. Example: "__tenant" parameter name can be changed using AspNetCoreMultiTenancyOptions. Example:
````C# ````C#

257
docs/en/Object-To-Object-Mapping.md

@ -1,3 +1,256 @@
## Object To Object Mapping # Object To Object Mapping
It's common to map an object to another similar object. It's also tedious and repetitive since generally both classes have the same or similar properties mapped to each other. Imagine a typical [application service](Application-Services.md) method below:
```csharp
public class UserAppService : ApplicationService
{
private readonly IRepository<User, Guid> _userRepository;
public UserAppService(IRepository<User, Guid> userRepository)
{
_userRepository = userRepository;
}
public void CreateUser(CreateUserInput input)
{
//Manually creating a User object from the CreateUserInput object
var user = new User
{
Name = input.Name,
Surname = input.Surname,
EmailAddress = input.EmailAddress,
Password = input.Password
};
_userRepository.Insert(user);
}
}
```
`CreateUserInput ` is a simple [DTO](Data-Transfer-Objects.md) class and the `User` is a simple [entity](Entities.md). The code above creates a `User` entity from the given input object. The `User` entity will have more properties in a real-world application and manually creating it will become tedious and error-prone. You also have to change the mapping code when you add new properties to `User` and `CreateUserInput` classes.
We can use a library to automatically handle these kind of mappings. ABP provides abstractions for object to object mapping and has an integration package to use [AutoMapper](http://automapper.org/) as the object mapper.
## IObjectMapper
`IObjectMapper` interface (in the [Volo.Abp.ObjectMapping](https://www.nuget.org/packages/Volo.Abp.ObjectMapping) package) defines a simple `Map` method. The example code introduced before can be re-written as shown below:
````csharp
public class UserAppService : ApplicationService
{
private readonly IRepository<User, Guid> _userRepository;
public UserAppService(IRepository<User, Guid> userRepository)
{
_userRepository = userRepository;
}
public void CreateUser(CreateUserInput input)
{
//Automatically creating a new User object using the CreateUserInput object
var user = ObjectMapper.Map<CreateUserInput, User>(input);
_userRepository.Insert(user);
}
}
````
> `ObjectMapper` is defined in the `ApplicationService` base class in this example. You can directly inject the `IObjectMapper` interface when you need it somewhere else.
Map method has two generic argument: First one is the source object type while the second one is the destination object type.
If you need to set properties of an existing object, you can use the second overload of the `Map` method:
````csharp
public class UserAppService : ApplicationService
{
private readonly IRepository<User, Guid> _userRepository;
public UserAppService(IRepository<User, Guid> userRepository)
{
_userRepository = userRepository;
}
public async Task UpdateUserAsync(Guid id, UpdateUserInput input)
{
var user = await _userRepository.GetAsync(id);
//Automatically set properties of the user object using the UpdateUserInput
ObjectMapper.Map<UpdateUserInput, User>(input, user);
await _userRepository.UpdateAsync(user);
}
}
````
You should have defined the mappings before to be able to map objects. See the AutoMapper integration section to learn how to define mappings.
## AutoMapper Integration
[AutoMapper](http://automapper.org/) is one of the most popular object to object mapping libraries. [Volo.Abp.AutoMapper](https://www.nuget.org/packages/Volo.Abp.AutoMapper) package defines the AutoMapper integration for the `IObjectMapper`.
Once you define mappings described as below, you can use the `IObjectMapper` interface just like explained before.
### Define Mappings
AutoMapper provides multiple ways of defining mapping between classes. Refer to [its own documentation](https://docs.automapper.org) for all details.
One way to define object mappings is creating a [Profile](https://docs.automapper.org/en/stable/Configuration.html#profile-instances) class. Example:
````csharp
public class MyProfile : Profile
{
public MyProfile()
{
CreateMap<User, UserDto>();
}
}
````
You should then register profiles using the `AbpAutoMapperOptions`:
````csharp
[DependsOn(typeof(AbpAutoMapperModule))]
public class MyModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpAutoMapperOptions>(options =>
{
//Add all mappings defined in the assembly of the MyModule class
options.AddMaps<MyModule>();
});
}
}
````
`AddMaps` registers all profile classes defined in the assembly of the given class, typically your module class. It also registers for the [attribute mapping](https://docs.automapper.org/en/stable/Attribute-mapping.html).
### Configuration Validation
`AddMaps` optionally takes a `bool` parameter to control the [configuration validation](https://docs.automapper.org/en/stable/Configuration-validation.html) for your [module](Module-Development-Basics.md):
````csharp
options.AddMaps<MyModule>(validate: true);
````
While this option is `false` by default, it is suggested to enable configuration validation as a best practice.
Configuration validation can be controlled per profile class using `AddProfile` instead of `AddMaps`:
````csharp
options.AddProfile<MyProfile>(validate: true);
````
> If you have multiple profiles and need to enable validation only for a few of them, first use `AddMaps` without validation, then use `AddProfile` for each profile you want to validate.
## Advanced Topics
### IObjectMapper<TContext> Interface
Assume that you have created a **reusable module** which defines AutoMapper profiles and uses `IObjectMapper` when it needs to map objects. Your module then can be used in different applications, by nature of the [modularity](Module-Development-Basics.md).
`IObjectMapper` is an abstraction and can be replaced by the final application to use another mapping library. The problem here that your reusable module is designed to use the AutoMapper library, because it only defines mappings for it. In such a case, you will want to guarantee that your module always uses AutoMapper even if the final application uses another default object mapping library.
`IObjectMapper<TContext>` is used to contextualize the object mapper, so you can use different libraries for different modules/contexts.
Example usage:
````csharp
public class UserAppService : ApplicationService
{
private readonly IRepository<User, Guid> _userRepository;
private readonly IObjectMapper<MyModule> _objectMapper;
public UserAppService(
IRepository<User, Guid> userRepository,
IObjectMapper<MyModule> objectMapper) //Inject module specific mapper
{
_userRepository = userRepository;
_objectMapper = objectMapper;
}
public async Task CreateUserAsync(CreateUserInput input)
{
//Use the module specific mapper
var user = _objectMapper.Map<CreateUserInput, User>(input);
await _userRepository.InsertAsync(user);
}
}
````
`UserAppService ` injects the `IObjectMapper<MyModule>`, the specific object mapper for this module. It's usage is exactly same of the `IObjectMapper`.
The example code above don't use the `ObjectMapper` property defined in the `ApplicationService`, but injects the `IObjectMapper<MyModule>`. However, it is still possible to use the base property since the `ApplicationService` defines an `ObjectMapperContext` property that can be set in the class constructor. So, the example about can be re-written as like below:
````csharp
public class UserAppService : ApplicationService
{
private readonly IRepository<User, Guid> _userRepository;
public UserAppService(IRepository<User, Guid> userRepository)
{
_userRepository = userRepository;
//Set the object mapper context
ObjectMapperContext = typeof(MyModule);
}
public async Task CreateUserAsync(CreateUserInput input)
{
var user = ObjectMapper.Map<CreateUserInput, User>(input);
await _userRepository.InsertAsync(user);
}
}
````
While using the contextualized object mapper is same as the normal object mapper, you should register the contextualized mapper in your module's `ConfigureServices` method:
````csharp
[DependsOn(typeof(AbpAutoMapperModule))]
public class MyModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
//Use AutoMapper for MyModule
context.Services.AddAutoMapperObjectMapper<MyModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddMaps<MyModule>(validate: true);
});
}
}
````
`IObjectMapper<MyModule>` is an essential feature for a reusable module where it can be used in multiple applications each may use a different library for object to object mapping. All pre-built ABP modules are using it. But, for the final application, you can ignore this interface and always use the default `IObjectMapper` interface.
### IObjectMapper<TSource, TDestination> Interface
ABP allows you to customize the mapping code for specific classes. Assume that you want to create a custom class to map from `User` to `UserDto`. In this case, you can create a class that implements the `IObjectMapper<User, UserDto>`:
````csharp
public class MyCustomUserMapper : IObjectMapper<User, UserDto>, ITransientDependency
{
public UserDto Map(User source)
{
//TODO: Create a new UserDto
}
public UserDto Map(User source, UserDto destination)
{
//TODO: Set properties of an existing UserDto
return destination;
}
}
````
ABP automatically discovers and registers the `MyCustomUserMapper` and it is automatically used whenever you use the `IObjectMapper` to map `User` to `UserDto`.
A single class may implement more than one `IObjectMapper<TSource, TDestination>` each for a different object pairs.
> This approach is powerful since `MyCustomUserMapper` can inject any other service and use in the `Map` methods.
TODO

7
docs/en/docs-nav.json

@ -86,7 +86,8 @@
"path": "Authorization.md" "path": "Authorization.md"
}, },
{ {
"text": "Caching" "text": "Caching",
"path": "Caching.md"
}, },
{ {
"text": "Auditing" "text": "Auditing"
@ -115,6 +116,10 @@
{ {
"text": "Services", "text": "Services",
"items": [ "items": [
{
"text": "Object to object mapping",
"path": "Object-To-Object-Mapping.md"
},
{ {
"text": "Object Serialization" "text": "Object Serialization"
}, },

2
docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md

@ -49,7 +49,7 @@ abp new Acme.BookStore
} }
```` ````
解决方案使用 **Entity Framework Core** 和 **MS SQL Server**. EF Core支持[各种](https://docs.microsoft.com/en-us/ef/core/providers/)数据库提供程序,因此你可以根据实际需要使用其他DBMS. 如果需要,请更改连接字符串. 解决方案使用 **Entity Framework Core** 和 **MS SQL Server**. EF Core支持[各种](https://docs.microsoft.com/zh-cn/ef/core/providers/)数据库提供程序,因此你可以根据实际需要使用其他DBMS. 如果需要,请更改连接字符串.
### 创建数据库并应用数据库迁移 ### 创建数据库并应用数据库迁移

4
docs/zh-Hans/Multi-Tenancy.md

@ -308,6 +308,10 @@ Volo.Abp.AspNetCore.MultiTenancy 添加了下面这些租户解析器,从当前W
* **HeaderTenantResolver**: 尝试从HTTP header中获取当前租户,默认的header名称是"__tenant". * **HeaderTenantResolver**: 尝试从HTTP header中获取当前租户,默认的header名称是"__tenant".
* **CookieTenantResolver**: 尝试从当前cookie中获取当前租户.默认的Cookie名称是"__tenant". * **CookieTenantResolver**: 尝试从当前cookie中获取当前租户.默认的Cookie名称是"__tenant".
> 如果你使用nginx作为反向代理服务器,请注意如果`TenantKey`包含下划线或其他特殊字符可能存在问题, 请参考:
http://nginx.org/en/docs/http/ngx_http_core_module.html#ignore_invalid_headers
http://nginx.org/en/docs/http/ngx_http_core_module.html#underscores_in_headers
可以使用AspNetCoreMultiTenancyOptions修改默认的参数名"__tenant".例如: 可以使用AspNetCoreMultiTenancyOptions修改默认的参数名"__tenant".例如:
````C# ````C#

20
framework/src/Volo.Abp.Autofac/Microsoft/Extensions/Hosting/AbpAutofacHostBuilderExtensions.cs

@ -0,0 +1,20 @@
using Autofac;
using Volo.Abp.Autofac;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.Extensions.Hosting
{
public static class AbpAutofacHostBuilderExtensions
{
public static IHostBuilder UseAutofac(this IHostBuilder hostBuilder)
{
var containerBuilder = new ContainerBuilder();
return hostBuilder.ConfigureServices((_, services) =>
{
services.AddObjectAccessor(containerBuilder);
})
.UseServiceProviderFactory(new AbpAutofacServiceProviderFactory(containerBuilder));
}
}
}

1
framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj

@ -16,6 +16,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Autofac.Extras.DynamicProxy" Version="4.5.0" /> <PackageReference Include="Autofac.Extras.DynamicProxy" Version="4.5.0" />
<PackageReference Include="Autofac" Version="4.9.4" /> <PackageReference Include="Autofac" Version="4.9.4" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

1
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs

@ -27,6 +27,7 @@ namespace Volo.Abp.Cli
{ {
options.Commands["help"] = typeof(HelpCommand); options.Commands["help"] = typeof(HelpCommand);
options.Commands["new"] = typeof(NewCommand); options.Commands["new"] = typeof(NewCommand);
options.Commands["get-source"] = typeof(GetSourceCommand);
options.Commands["update"] = typeof(UpdateCommand); options.Commands["update"] = typeof(UpdateCommand);
options.Commands["add-package"] = typeof(AddPackageCommand); options.Commands["add-package"] = typeof(AddPackageCommand);
options.Commands["add-module"] = typeof(AddModuleCommand); options.Commands["add-module"] = typeof(AddModuleCommand);

169
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GetSourceCommand.cs

@ -0,0 +1,169 @@
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.Zip;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Cli.Args;
using Volo.Abp.Cli.ProjectBuilding;
using Volo.Abp.Cli.ProjectBuilding.Building;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.Commands
{
public class GetSourceCommand : IConsoleCommand, ITransientDependency
{
public ModuleProjectBuilder ModuleProjectBuilder { get; }
public ILogger<NewCommand> Logger { get; set; }
public GetSourceCommand(ModuleProjectBuilder moduleProjectBuilder)
{
ModuleProjectBuilder = moduleProjectBuilder;
Logger = NullLogger<NewCommand>.Instance;
}
public async Task ExecuteAsync(CommandLineArgs commandLineArgs)
{
if (commandLineArgs.Target == null)
{
throw new CliUsageException(
"Module name is missing!" +
Environment.NewLine + Environment.NewLine +
GetUsageInfo()
);
}
Logger.LogInformation("Downloading source code of " + commandLineArgs.Target);
var version = commandLineArgs.Options.GetOrNull(Options.Version.Short, Options.Version.Long);
if (version != null)
{
Logger.LogInformation("Version: " + version);
}
var outputFolder = commandLineArgs.Options.GetOrNull(Options.OutputFolder.Short, Options.OutputFolder.Long);
if (outputFolder != null)
{
if (!Directory.Exists(outputFolder))
{
Directory.CreateDirectory(outputFolder);
}
outputFolder = Path.GetFullPath(outputFolder);
}
else
{
outputFolder = Directory.GetCurrentDirectory();
}
Logger.LogInformation("Output folder: " + outputFolder);
var gitHubLocalRepositoryPath = commandLineArgs.Options.GetOrNull(Options.GitHubLocalRepositoryPath.Long);
if (gitHubLocalRepositoryPath != null)
{
Logger.LogInformation("GitHub Local Repository Path: " + gitHubLocalRepositoryPath);
}
commandLineArgs.Options.Add(CliConsts.Command, commandLineArgs.Command);
var result = await ModuleProjectBuilder.BuildAsync(
new ProjectBuildArgs(
SolutionName.Parse(commandLineArgs.Target),
commandLineArgs.Target,
version,
DatabaseProvider.NotSpecified,
UiFramework.NotSpecified,
gitHubLocalRepositoryPath,
commandLineArgs.Options
)
);
using (var templateFileStream = new MemoryStream(result.ZipContent))
{
using (var zipInputStream = new ZipInputStream(templateFileStream))
{
var zipEntry = zipInputStream.GetNextEntry();
while (zipEntry != null)
{
var fullZipToPath = Path.Combine(outputFolder, zipEntry.Name);
var directoryName = Path.GetDirectoryName(fullZipToPath);
if (!string.IsNullOrEmpty(directoryName))
{
Directory.CreateDirectory(directoryName);
}
var fileName = Path.GetFileName(fullZipToPath);
if (fileName.Length == 0)
{
zipEntry = zipInputStream.GetNextEntry();
continue;
}
var buffer = new byte[4096]; // 4K is optimum
using (var streamWriter = File.Create(fullZipToPath))
{
StreamUtils.Copy(zipInputStream, streamWriter, buffer);
}
zipEntry = zipInputStream.GetNextEntry();
}
}
}
Logger.LogInformation($"'{commandLineArgs.Target}' has been successfully downloaded to '{outputFolder}'");
}
public string GetUsageInfo()
{
var sb = new StringBuilder();
sb.AppendLine("");
sb.AppendLine("Usage:");
sb.AppendLine("");
sb.AppendLine(" abp get-source <module-name> [options]");
sb.AppendLine("");
sb.AppendLine("Options:");
sb.AppendLine("");
sb.AppendLine("-o|--output-folder <output-folder> (default: current folder)");
sb.AppendLine("-v|--version <version> (default: latest version)");
sb.AppendLine("");
sb.AppendLine("Examples:");
sb.AppendLine("");
sb.AppendLine(" abp get-source Volo.Blogging");
sb.AppendLine(" abp get-source Volo.Blogging -o d:\\my-project");
sb.AppendLine("");
sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI");
return sb.ToString();
}
public string GetShortDescription()
{
return "Downloads the source code of the specified module.";
}
public static class Options
{
public static class OutputFolder
{
public const string Short = "o";
public const string Long = "output-folder";
}
public static class GitHubLocalRepositoryPath
{
public const string Long = "abp-path";
}
public static class Version
{
public const string Short = "v";
public const string Long = "version";
}
}
}
}

8
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs

@ -17,11 +17,11 @@ namespace Volo.Abp.Cli.Commands
{ {
public ILogger<NewCommand> Logger { get; set; } public ILogger<NewCommand> Logger { get; set; }
protected ProjectBuilder ProjectBuilder { get; } protected TemplateProjectBuilder TemplateProjectBuilder { get; }
public NewCommand(ProjectBuilder projectBuilder) public NewCommand(TemplateProjectBuilder templateProjectBuilder)
{ {
ProjectBuilder = projectBuilder; TemplateProjectBuilder = templateProjectBuilder;
Logger = NullLogger<NewCommand>.Instance; Logger = NullLogger<NewCommand>.Instance;
} }
@ -89,7 +89,7 @@ namespace Volo.Abp.Cli.Commands
commandLineArgs.Options.Add(CliConsts.Command, commandLineArgs.Command); commandLineArgs.Options.Add(CliConsts.Command, commandLineArgs.Command);
var result = await ProjectBuilder.BuildAsync( var result = await TemplateProjectBuilder.BuildAsync(
new ProjectBuildArgs( new ProjectBuildArgs(
SolutionName.Parse(commandLineArgs.Target), SolutionName.Parse(commandLineArgs.Target),
template, template,

3
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs

@ -1,5 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -7,13 +6,11 @@ using System.Threading.Tasks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Volo.Abp.Cli.Args; using Volo.Abp.Cli.Args;
using Volo.Abp.Cli.ProjectBuilding.Analyticses; using Volo.Abp.Cli.ProjectBuilding.Analyticses;
using Volo.Abp.Cli.ProjectModification; using Volo.Abp.Cli.ProjectModification;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Json; using Volo.Abp.Json;
using Volo.Abp.Threading;
namespace Volo.Abp.Cli.Commands namespace Volo.Abp.Cli.Commands
{ {

12
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/AbpIoApiKeyService.cs

@ -1,6 +1,7 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Cli.Http; using Volo.Abp.Cli.Http;
using Volo.Abp.Cli.ProjectBuilding;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Json; using Volo.Abp.Json;
@ -8,13 +9,16 @@ namespace Volo.Abp.Cli.Licensing
{ {
public class AbpIoApiKeyService : IApiKeyService, ITransientDependency public class AbpIoApiKeyService : IApiKeyService, ITransientDependency
{ {
public AbpIoApiKeyService(IJsonSerializer jsonSerializer) protected IJsonSerializer JsonSerializer { get; }
protected IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; }
public AbpIoApiKeyService(IJsonSerializer jsonSerializer, IRemoteServiceExceptionHandler remoteServiceExceptionHandler)
{ {
JsonSerializer = jsonSerializer; JsonSerializer = jsonSerializer;
RemoteServiceExceptionHandler = remoteServiceExceptionHandler;
} }
protected IJsonSerializer JsonSerializer { get; }
public async Task<DeveloperApiKeyResult> GetApiKeyOrNullAsync() public async Task<DeveloperApiKeyResult> GetApiKeyOrNullAsync()
{ {
using (var client = new CliHttpClient()) using (var client = new CliHttpClient())
@ -28,6 +32,8 @@ namespace Volo.Abp.Cli.Licensing
throw new Exception($"ERROR: Remote server returns '{response.StatusCode}'"); throw new Exception($"ERROR: Remote server returns '{response.StatusCode}'");
} }
await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response);
var responseContent = await response.Content.ReadAsStringAsync(); var responseContent = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<DeveloperApiKeyResult>(responseContent); return JsonSerializer.Deserialize<DeveloperApiKeyResult>(responseContent);
} }

3
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/IApiKeyService.cs

@ -1,5 +1,4 @@
using System.Net; using System.Threading.Tasks;
using System.Threading.Tasks;
namespace Volo.Abp.Cli.Licensing namespace Volo.Abp.Cli.Licensing
{ {

13
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs

@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Cli.Http; using Volo.Abp.Cli.Http;
using Volo.Abp.Cli.ProjectBuilding;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Json; using Volo.Abp.Json;
using Volo.Abp.Threading; using Volo.Abp.Threading;
@ -17,11 +18,15 @@ namespace Volo.Abp.Cli.NuGet
protected ICancellationTokenProvider CancellationTokenProvider { get; } protected ICancellationTokenProvider CancellationTokenProvider { get; }
protected IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; }
public NuGetService( public NuGetService(
IJsonSerializer jsonSerializer, IJsonSerializer jsonSerializer,
IRemoteServiceExceptionHandler remoteServiceExceptionHandler,
ICancellationTokenProvider cancellationTokenProvider) ICancellationTokenProvider cancellationTokenProvider)
{ {
JsonSerializer = jsonSerializer; JsonSerializer = jsonSerializer;
RemoteServiceExceptionHandler = remoteServiceExceptionHandler;
CancellationTokenProvider = cancellationTokenProvider; CancellationTokenProvider = cancellationTokenProvider;
} }
@ -35,10 +40,7 @@ namespace Volo.Abp.Cli.NuGet
var responseMessage = await client.GetAsync(url, CancellationTokenProvider.Token); var responseMessage = await client.GetAsync(url, CancellationTokenProvider.Token);
if (!responseMessage.IsSuccessStatusCode) await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage);
{
throw new Exception("Remote server returns error! HTTP status code: " + responseMessage.StatusCode);
}
var result = await responseMessage.Content.ReadAsStringAsync(); var result = await responseMessage.Content.ReadAsStringAsync();
@ -49,7 +51,8 @@ namespace Volo.Abp.Cli.NuGet
versions = versions.Where(x => !x.IsPrerelease); versions = versions.Where(x => !x.IsPrerelease);
} }
return versions.Any() ? versions.Max() : null; var semanticVersions = versions.ToList();
return semanticVersions.Any() ? semanticVersions.Max() : null;
} }
} }

71
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoTemplateStore.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs

@ -2,7 +2,9 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -15,33 +17,39 @@ using Volo.Abp.Threading;
namespace Volo.Abp.Cli.ProjectBuilding namespace Volo.Abp.Cli.ProjectBuilding
{ {
public class AbpIoTemplateStore : ITemplateStore, ITransientDependency public class AbpIoSourceCodeStore : ISourceCodeStore, ITransientDependency
{ {
public ILogger<AbpIoTemplateStore> Logger { get; set; } public ILogger<AbpIoSourceCodeStore> Logger { get; set; }
protected CliOptions Options { get; } protected CliOptions Options { get; }
protected IJsonSerializer JsonSerializer { get; } protected IJsonSerializer JsonSerializer { get; }
protected IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; }
protected ICancellationTokenProvider CancellationTokenProvider { get; } protected ICancellationTokenProvider CancellationTokenProvider { get; }
public AbpIoTemplateStore( public AbpIoSourceCodeStore(
IOptions<CliOptions> options, IOptions<CliOptions> options,
IJsonSerializer jsonSerializer, IJsonSerializer jsonSerializer,
IRemoteServiceExceptionHandler remoteServiceExceptionHandler,
ICancellationTokenProvider cancellationTokenProvider) ICancellationTokenProvider cancellationTokenProvider)
{ {
JsonSerializer = jsonSerializer; JsonSerializer = jsonSerializer;
RemoteServiceExceptionHandler = remoteServiceExceptionHandler;
CancellationTokenProvider = cancellationTokenProvider; CancellationTokenProvider = cancellationTokenProvider;
Options = options.Value; Options = options.Value;
Logger = NullLogger<AbpIoTemplateStore>.Instance; Logger = NullLogger<AbpIoSourceCodeStore>.Instance;
} }
public async Task<TemplateFile> GetAsync( public async Task<TemplateFile> GetAsync(
string name, string name,
string type,
string version = null) string version = null)
{ {
var latestVersion = await GetLatestTemplateVersionAsync(name);
var latestVersion = await GetLatestSourceCodeVersionAsync(name, type);
if (version == null) if (version == null)
{ {
version = latestVersion; version = latestVersion;
@ -52,16 +60,17 @@ namespace Volo.Abp.Cli.ProjectBuilding
var localCacheFile = Path.Combine(CliPaths.TemplateCache, name + "-" + version + ".zip"); var localCacheFile = Path.Combine(CliPaths.TemplateCache, name + "-" + version + ".zip");
if (Options.CacheTemplates && File.Exists(localCacheFile)) if (Options.CacheTemplates && File.Exists(localCacheFile))
{ {
Logger.LogInformation("Using cached template: " + name + ", version: " + version); Logger.LogInformation("Using cached " + type + ": " + name + ", version: " + version);
return new TemplateFile(File.ReadAllBytes(localCacheFile), version, latestVersion); return new TemplateFile(File.ReadAllBytes(localCacheFile), version, latestVersion);
} }
Logger.LogInformation("Downloading template: " + name + ", version: " + version); Logger.LogInformation("Downloading " + type + ": " + name + ", version: " + version);
var fileContent = await DownloadTemplateFileContentAsync( var fileContent = await DownloadSourceCodeContentAsync(
new TemplateDownloadInputDto new SourceCodeDownloadInputDto
{ {
Name = name, Name = name,
Type = type,
Version = version Version = version
} }
); );
@ -72,64 +81,66 @@ namespace Volo.Abp.Cli.ProjectBuilding
} }
return new TemplateFile(fileContent, version, latestVersion); return new TemplateFile(fileContent, version, latestVersion);
} }
private async Task<string> GetLatestTemplateVersionAsync(string name) private async Task<string> GetLatestSourceCodeVersionAsync(string name, string type)
{ {
var postData = JsonSerializer.Serialize(new GetLatestTemplateVersionDto { Name = name });
using (var client = new CliHttpClient()) using (var client = new CliHttpClient())
{ {
var responseMessage = await client.PostAsync( var response = await client.PostAsync(
$"{CliUrls.WwwAbpIo}api/download/template/get-version/", $"{CliUrls.WwwAbpIo}api/download/{type}/get-version/",
new StringContent(postData, Encoding.UTF8, MimeTypes.Application.Json), new StringContent(
JsonSerializer.Serialize(
new GetLatestSourceCodeVersionDto { Name = name }
),
Encoding.UTF8,
MimeTypes.Application.Json
),
CancellationTokenProvider.Token CancellationTokenProvider.Token
); );
if (!responseMessage.IsSuccessStatusCode) await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response);
{
throw new Exception("Remote server returns error! HTTP status code: " + responseMessage.StatusCode); var result = await response.Content.ReadAsStringAsync();
}
var result = await responseMessage.Content.ReadAsStringAsync(); return JsonSerializer.Deserialize<GetLatestSourceCodeVersionResultDto>(result).Version;
return JsonSerializer.Deserialize<GetLatestTemplateVersionResultDto>(result).Version;
} }
} }
private async Task<byte[]> DownloadTemplateFileContentAsync(TemplateDownloadInputDto input) private async Task<byte[]> DownloadSourceCodeContentAsync(SourceCodeDownloadInputDto input)
{ {
var postData = JsonSerializer.Serialize(input); var postData = JsonSerializer.Serialize(input);
using (var client = new CliHttpClient(TimeSpan.FromMinutes(10))) using (var client = new CliHttpClient(TimeSpan.FromMinutes(10)))
{ {
var responseMessage = await client.PostAsync( var responseMessage = await client.PostAsync(
$"{CliUrls.WwwAbpIo}api/download/template/", $"{CliUrls.WwwAbpIo}api/download/{input.Type}/",
new StringContent(postData, Encoding.UTF8, MimeTypes.Application.Json), new StringContent(postData, Encoding.UTF8, MimeTypes.Application.Json),
CancellationTokenProvider.Token CancellationTokenProvider.Token
); );
if (!responseMessage.IsSuccessStatusCode) await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage);
{
throw new Exception("Remote server returns error! HTTP status code: " + responseMessage.StatusCode);
}
return await responseMessage.Content.ReadAsByteArrayAsync(); return await responseMessage.Content.ReadAsByteArrayAsync();
} }
} }
public class TemplateDownloadInputDto public class SourceCodeDownloadInputDto
{ {
public string Name { get; set; } public string Name { get; set; }
public string Version { get; set; } public string Version { get; set; }
public string Type { get; set; }
} }
public class GetLatestTemplateVersionDto public class GetLatestSourceCodeVersionDto
{ {
public string Name { get; set; } public string Name { get; set; }
} }
public class GetLatestTemplateVersionResultDto public class GetLatestSourceCodeVersionResultDto
{ {
public string Version { get; set; } public string Version { get; set; }
} }

19
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Analyticses/CliAnalyticsCollect.cs

@ -16,12 +16,16 @@ namespace Volo.Abp.Cli.ProjectBuilding.Analyticses
private readonly ICancellationTokenProvider _cancellationTokenProvider; private readonly ICancellationTokenProvider _cancellationTokenProvider;
private readonly IJsonSerializer _jsonSerializer; private readonly IJsonSerializer _jsonSerializer;
private readonly ILogger<CliAnalyticsCollect> _logger; private readonly ILogger<CliAnalyticsCollect> _logger;
private readonly IRemoteServiceExceptionHandler _remoteServiceExceptionHandler;
public CliAnalyticsCollect(ICancellationTokenProvider cancellationTokenProvider, public CliAnalyticsCollect(
IJsonSerializer jsonSerializer) ICancellationTokenProvider cancellationTokenProvider,
IJsonSerializer jsonSerializer,
IRemoteServiceExceptionHandler remoteServiceExceptionHandler)
{ {
_cancellationTokenProvider = cancellationTokenProvider; _cancellationTokenProvider = cancellationTokenProvider;
_jsonSerializer = jsonSerializer; _jsonSerializer = jsonSerializer;
_remoteServiceExceptionHandler = remoteServiceExceptionHandler;
_logger = NullLogger<CliAnalyticsCollect>.Instance; _logger = NullLogger<CliAnalyticsCollect>.Instance;
} }
@ -38,8 +42,15 @@ namespace Volo.Abp.Cli.ProjectBuilding.Analyticses
if (!responseMessage.IsSuccessStatusCode) if (!responseMessage.IsSuccessStatusCode)
{ {
_logger.LogInformation("Remote server returns error! HTTP status code: " + var exceptionMessage = "Remote server returns '" + (int)responseMessage.StatusCode + "-" + responseMessage.ReasonPhrase + "'. ";
responseMessage.StatusCode); var remoteServiceErrorMessage = await _remoteServiceExceptionHandler.GetAbpRemoteServiceErrorAsync(responseMessage);
if (remoteServiceErrorMessage != null)
{
exceptionMessage += remoteServiceErrorMessage;
}
_logger.LogInformation(exceptionMessage);
} }
} }
} }

11
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ModuleInfo.cs

@ -0,0 +1,11 @@
namespace Volo.Abp.Cli.ProjectBuilding.Building
{
public class ModuleInfo
{
public string Name { get; set; }
public string Namespace { get; set; }
public string DocumentUrl { get; set; }
}
}

19
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ModuleProjectBuildPipelineBuilder.cs

@ -0,0 +1,19 @@
using Volo.Abp.Cli.ProjectBuilding.Building.Steps;
namespace Volo.Abp.Cli.ProjectBuilding.Building
{
public static class ModuleProjectBuildPipelineBuilder
{
public static ProjectBuildPipeline Build(ProjectBuildContext context)
{
var pipeline = new ProjectBuildPipeline(context);
pipeline.Steps.Add(new FileEntryListReadStep());
pipeline.Steps.Add(new ProjectReferenceReplaceStep());
pipeline.Steps.Add(new ReplaceCommonPropsStep());
pipeline.Steps.Add(new CreateProjectResultZipStep());
return pipeline;
}
}
}

9
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildContext.cs

@ -11,19 +11,22 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building
[NotNull] [NotNull]
public ProjectBuildArgs BuildArgs { get; } public ProjectBuildArgs BuildArgs { get; }
[NotNull]
public TemplateInfo Template { get; } public TemplateInfo Template { get; }
public ModuleInfo Module { get; }
public FileEntryList Files { get; set; } public FileEntryList Files { get; set; }
public ProjectResult Result { get; set; } public ProjectResult Result { get; set; }
public ProjectBuildContext( public ProjectBuildContext(
[NotNull] TemplateInfo template, TemplateInfo template,
ModuleInfo module,
[NotNull] TemplateFile templateFile, [NotNull] TemplateFile templateFile,
[NotNull] ProjectBuildArgs buildArgs) [NotNull] ProjectBuildArgs buildArgs)
{ {
Template = Check.NotNull(template, nameof(template)); Template = template;
Module = module;
TemplateFile = Check.NotNull(templateFile, nameof(templateFile)); TemplateFile = Check.NotNull(templateFile, nameof(templateFile));
BuildArgs = Check.NotNull(buildArgs, nameof(buildArgs)); BuildArgs = Check.NotNull(buildArgs, nameof(buildArgs));

20
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectReferenceReplaceStep.cs

@ -22,7 +22,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
new ProjectReferenceReplacer.LocalProjectPathReferenceReplacer( new ProjectReferenceReplacer.LocalProjectPathReferenceReplacer(
context.Files, context.Files,
"MyCompanyName.MyProjectName", context.Module?.Namespace ?? "MyCompanyName.MyProjectName",
localAbpRepoPath localAbpRepoPath
).Run(); ).Run();
} }
@ -37,7 +37,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
new ProjectReferenceReplacer.NugetReferenceReplacer( new ProjectReferenceReplacer.NugetReferenceReplacer(
context.Files, context.Files,
"MyCompanyName.MyProjectName", context.Module?.Namespace ?? "MyCompanyName.MyProjectName",
nugetPackageVersion nugetPackageVersion
).Run(); ).Run();
} }
@ -65,14 +65,14 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
private abstract class ProjectReferenceReplacer private abstract class ProjectReferenceReplacer
{ {
private readonly List<FileEntry> _entries; private readonly List<FileEntry> _entries;
private readonly string _companyAndProjectNamePlaceHolder; private readonly string _projectName;
protected ProjectReferenceReplacer( protected ProjectReferenceReplacer(
List<FileEntry> entries, List<FileEntry> entries,
string companyAndProjectNamePlaceHolder) string projectName)
{ {
_entries = entries; _entries = entries;
_companyAndProjectNamePlaceHolder = companyAndProjectNamePlaceHolder; _projectName = projectName;
} }
public void Run() public void Run()
@ -108,7 +108,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
var oldNodeIncludeValue = oldNode.Attributes["Include"].Value; var oldNodeIncludeValue = oldNode.Attributes["Include"].Value;
// ReSharper disable once PossibleNullReferenceException : Can not be null because nodes are selected with include attribute filter in previous method // ReSharper disable once PossibleNullReferenceException : Can not be null because nodes are selected with include attribute filter in previous method
if (oldNodeIncludeValue.Contains($"{_companyAndProjectNamePlaceHolder}")) if (oldNodeIncludeValue.Contains(_projectName))
{ {
continue; continue;
} }
@ -140,8 +140,8 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{ {
private readonly string _nugetPackageVersion; private readonly string _nugetPackageVersion;
public NugetReferenceReplacer(List<FileEntry> entries, string companyAndProjectNamePlaceHolder, string nugetPackageVersion) public NugetReferenceReplacer(List<FileEntry> entries, string projectName, string nugetPackageVersion)
: base(entries, companyAndProjectNamePlaceHolder) : base(entries, projectName)
{ {
_nugetPackageVersion = nugetPackageVersion; _nugetPackageVersion = nugetPackageVersion;
} }
@ -177,8 +177,8 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{ {
private readonly string _gitHubLocalRepositoryPath; private readonly string _gitHubLocalRepositoryPath;
public LocalProjectPathReferenceReplacer(List<FileEntry> entries, string companyAndProjectNamePlaceHolder, string gitHubLocalRepositoryPath) public LocalProjectPathReferenceReplacer(List<FileEntry> entries, string projectName, string gitHubLocalRepositoryPath)
: base(entries, companyAndProjectNamePlaceHolder) : base(entries, projectName)
{ {
_gitHubLocalRepositoryPath = gitHubLocalRepositoryPath; _gitHubLocalRepositoryPath = gitHubLocalRepositoryPath;
} }

3
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/RenameHelper.cs

@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using Volo.Abp.Cli.ProjectBuilding.Files; using Volo.Abp.Cli.ProjectBuilding.Files;

96
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ReplaceCommonPropsStep.cs

@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Xml;
using Volo.Abp.Cli.ProjectBuilding.Files;
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
public class ReplaceCommonPropsStep : ProjectBuildPipelineStep
{
public override void Execute(ProjectBuildContext context)
{
new CommonPropsReplacer(context.Files).Run();
}
private class CommonPropsReplacer
{
private readonly List<FileEntry> _entries;
public CommonPropsReplacer(
List<FileEntry> entries)
{
_entries = entries;
}
public void Run()
{
foreach (var fileEntry in _entries)
{
if (fileEntry.Name.EndsWith(".csproj"))
{
fileEntry.SetContent(ProcessFileContent(fileEntry.Content));
}
}
}
private string ProcessFileContent(string content)
{
Check.NotNull(content, nameof(content));
var doc = new XmlDocument() { PreserveWhitespace = true };
doc.Load(GenerateStreamFromString(content));
return ProcessReferenceNodes(doc, content);
}
private string ProcessReferenceNodes(XmlDocument doc, string content)
{
Check.NotNull(content, nameof(content));
var importNodes = doc.SelectNodes("/Project/Import[@Project]");
if (importNodes == null)
{
return doc.OuterXml;
}
foreach (XmlNode node in importNodes)
{
if (!(node.Attributes?["Project"]?.Value?.EndsWith("\\common.props") ?? false))
{
continue;
}
node.ParentNode?.RemoveChild(node);
}
var propertyGroupNodes = doc.SelectNodes("/Project/PropertyGroup");
if (propertyGroupNodes == null || propertyGroupNodes.Count < 1)
{
return doc.OuterXml;
}
var firstPropertyGroupNode = propertyGroupNodes.Item(0);
var langNode = doc.CreateElement("LangVersion");
langNode.InnerText = "latest";
firstPropertyGroupNode?.PrependChild(langNode);
return doc.OuterXml;
}
private static Stream GenerateStreamFromString(string s)
{
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
}
}
}

17
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SolutionRenameStep.cs

@ -49,16 +49,21 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
public void Run() public void Run()
{ {
if (_companyNamePlaceHolder != null && _companyName != null) if (_companyNamePlaceHolder != null)
{ {
RenameHelper.RenameAll(_entries, _companyNamePlaceHolder, _companyName); if (_companyName != null)
} {
else if (_companyNamePlaceHolder != null) RenameHelper.RenameAll(_entries, _companyNamePlaceHolder, _companyName);
{ }
RenameHelper.RenameAll(_entries, _companyNamePlaceHolder + "." + _projectNamePlaceHolder, _projectNamePlaceHolder); else
{
RenameHelper.RenameAll(_entries, _companyNamePlaceHolder + "." + _projectNamePlaceHolder, _projectNamePlaceHolder);
}
} }
RenameHelper.RenameAll(_entries, _projectNamePlaceHolder, _projectName); RenameHelper.RenameAll(_entries, _projectNamePlaceHolder, _projectName);
RenameHelper.RenameAll(_entries, _projectNamePlaceHolder.ToCamelCase(), _projectName.ToCamelCase());
RenameHelper.RenameAll(_entries, _projectNamePlaceHolder.ToKebabCase(), _projectName.ToKebabCase());
} }
} }
} }

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildPipelineBuilder.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs

@ -4,7 +4,7 @@ using Volo.Abp.Cli.ProjectBuilding.Templates.App;
namespace Volo.Abp.Cli.ProjectBuilding.Building namespace Volo.Abp.Cli.ProjectBuilding.Building
{ {
public static class ProjectBuildPipelineBuilder public static class TemplateProjectBuildPipelineBuilder
{ {
public static ProjectBuildPipeline Build(ProjectBuildContext context) public static ProjectBuildPipeline Build(ProjectBuildContext context)
{ {

10
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/IModuleInfoProvider.cs

@ -0,0 +1,10 @@
using System.Threading.Tasks;
using Volo.Abp.Cli.ProjectBuilding.Building;
namespace Volo.Abp.Cli.ProjectBuilding
{
public interface IModuleInfoProvider
{
Task<ModuleInfo> GetAsync(string name);
}
}

12
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/IRemoteServiceExceptionHandler.cs

@ -0,0 +1,12 @@
using System.Net.Http;
using System.Threading.Tasks;
namespace Volo.Abp.Cli.ProjectBuilding
{
public interface IRemoteServiceExceptionHandler
{
Task EnsureSuccessfulHttpResponseAsync(HttpResponseMessage responseMessage);
Task<string> GetAbpRemoteServiceErrorAsync(HttpResponseMessage responseMessage);
}
}

3
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ITemplateStore.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ISourceCodeStore.cs

@ -3,10 +3,11 @@ using JetBrains.Annotations;
namespace Volo.Abp.Cli.ProjectBuilding namespace Volo.Abp.Cli.ProjectBuilding
{ {
public interface ITemplateStore public interface ISourceCodeStore
{ {
Task<TemplateFile> GetAsync( Task<TemplateFile> GetAsync(
string name, string name,
string type,
[CanBeNull] string version = null [CanBeNull] string version = null
); );
} }

58
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ModuleInfoProvider.cs

@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Json;
using Volo.Abp.Cli.Http;
using Volo.Abp.Cli.ProjectBuilding.Building;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Threading;
namespace Volo.Abp.Cli.ProjectBuilding
{
public class ModuleInfoProvider : IModuleInfoProvider, ITransientDependency
{
public IJsonSerializer JsonSerializer { get; }
public ICancellationTokenProvider CancellationTokenProvider { get; }
public IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; }
public ModuleInfoProvider(
IJsonSerializer jsonSerializer,
ICancellationTokenProvider cancellationTokenProvider,
IRemoteServiceExceptionHandler remoteServiceExceptionHandler)
{
JsonSerializer = jsonSerializer;
CancellationTokenProvider = cancellationTokenProvider;
RemoteServiceExceptionHandler = remoteServiceExceptionHandler;
}
public async Task<ModuleInfo> GetAsync(string name)
{
var moduleList = await GetModuleListAsync();
var module = moduleList.FirstOrDefault(m => m.Name == name);
if (module == null)
{
throw new Exception("Module not found!");
}
return module;
}
private async Task<List<ModuleInfo>> GetModuleListAsync()
{
using (var client = new CliHttpClient())
{
var responseMessage = await client.GetAsync(
$"{CliUrls.WwwAbpIo}api/download/modules/",
CancellationTokenProvider.Token
);
await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage);
var result = await responseMessage.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<List<ModuleInfo>>(result);
}
}
}
}

109
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ModuleProjectBuilder.cs

@ -0,0 +1,109 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using System;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Cli.Commands;
using Volo.Abp.Cli.Licensing;
using Volo.Abp.Cli.ProjectBuilding.Analyticses;
using Volo.Abp.Cli.ProjectBuilding.Building;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Json;
namespace Volo.Abp.Cli.ProjectBuilding
{
public class ModuleProjectBuilder : IProjectBuilder, ITransientDependency
{
public ILogger<ModuleProjectBuilder> Logger { get; set; }
protected ISourceCodeStore SourceCodeStore { get; }
protected IModuleInfoProvider ModuleInfoProvider { get; }
protected ICliAnalyticsCollect CliAnalyticsCollect { get; }
protected CliOptions Options { get; }
protected IJsonSerializer JsonSerializer { get; }
protected IApiKeyService ApiKeyService { get; }
public ModuleProjectBuilder(ISourceCodeStore sourceCodeStore,
IModuleInfoProvider moduleInfoProvider,
ICliAnalyticsCollect cliAnalyticsCollect,
IOptions<CliOptions> options,
IJsonSerializer jsonSerializer,
IApiKeyService apiKeyService)
{
SourceCodeStore = sourceCodeStore;
ModuleInfoProvider = moduleInfoProvider;
CliAnalyticsCollect = cliAnalyticsCollect;
Options = options.Value;
JsonSerializer = jsonSerializer;
ApiKeyService = apiKeyService;
Logger = NullLogger<ModuleProjectBuilder>.Instance;
}
public async Task<ProjectBuildResult> BuildAsync(ProjectBuildArgs args)
{
var moduleInfo = await GetModuleInfoAsync(args);
var templateFile = await SourceCodeStore.GetAsync(
args.TemplateName,
SourceCodeTypes.Module,
args.Version
);
var apiKeyResult = await ApiKeyService.GetApiKeyOrNullAsync();
if (apiKeyResult?.ApiKey != null)
{
args.ExtraProperties["api-key"] = apiKeyResult.ApiKey;
}
if (apiKeyResult?.LicenseCode != null)
{
args.ExtraProperties["license-code"] = apiKeyResult.LicenseCode;
}
var context = new ProjectBuildContext(
null,
moduleInfo,
templateFile,
args
);
ModuleProjectBuildPipelineBuilder.Build(context).Execute();
if (!moduleInfo.DocumentUrl.IsNullOrEmpty())
{
Logger.LogInformation("Check out the documents at " + moduleInfo.DocumentUrl);
}
// Exclude unwanted or known options.
var options = args.ExtraProperties
.Where(x => !x.Key.Equals(CliConsts.Command, StringComparison.InvariantCultureIgnoreCase))
.Where(x => !x.Key.Equals(NewCommand.Options.OutputFolder.Long, StringComparison.InvariantCultureIgnoreCase) &&
!x.Key.Equals(NewCommand.Options.OutputFolder.Short, StringComparison.InvariantCultureIgnoreCase))
.Where(x => !x.Key.Equals(NewCommand.Options.Version.Long, StringComparison.InvariantCultureIgnoreCase) &&
!x.Key.Equals(NewCommand.Options.Version.Short, StringComparison.InvariantCultureIgnoreCase))
.Select(x => x.Key).ToList();
await CliAnalyticsCollect.CollectAsync(new CliAnalyticsCollectInputDto
{
Tool = Options.ToolName,
Command = args.ExtraProperties.ContainsKey(CliConsts.Command) ? args.ExtraProperties[CliConsts.Command] : "",
DatabaseProvider = null,
IsTiered = null,
UiFramework = null,
Options = JsonSerializer.Serialize(options),
ProjectName = null,
TemplateName = args.TemplateName,
TemplateVersion = templateFile.Version
});
return new ProjectBuildResult(context.Result.ZipContent, args.TemplateName);
}
private async Task<ModuleInfo> GetModuleInfoAsync(ProjectBuildArgs args)
{
return await ModuleInfoProvider.GetAsync(args.TemplateName);
}
}
}

92
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/RemoteServiceExceptionHandler.cs

@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http;
using Volo.Abp.Json;
namespace Volo.Abp.Cli.ProjectBuilding
{
public class RemoteServiceExceptionHandler : IRemoteServiceExceptionHandler, ITransientDependency
{
private readonly IJsonSerializer _jsonSerializer;
public RemoteServiceExceptionHandler(IJsonSerializer jsonSerializer)
{
_jsonSerializer = jsonSerializer;
}
public async Task EnsureSuccessfulHttpResponseAsync(HttpResponseMessage responseMessage)
{
if (responseMessage == null)
{
return;
}
if (responseMessage.IsSuccessStatusCode)
{
return;
}
var exceptionMessage = "Remote server returns '" + (int)responseMessage.StatusCode + "-" + responseMessage.ReasonPhrase + "'. ";
var remoteServiceErrorMessage = await GetAbpRemoteServiceErrorAsync(responseMessage);
if (remoteServiceErrorMessage != null)
{
exceptionMessage += remoteServiceErrorMessage;
}
throw new Exception(exceptionMessage);
}
public async Task<string> GetAbpRemoteServiceErrorAsync(HttpResponseMessage responseMessage)
{
var errorResult = _jsonSerializer.Deserialize<RemoteServiceErrorResponse>
(
await responseMessage.Content.ReadAsStringAsync()
);
if (errorResult?.Error == null)
{
return null;
}
var sbError = new StringBuilder();
if (!string.IsNullOrWhiteSpace(errorResult.Error.Code))
{
sbError.Append("Code: " + errorResult.Error.Code);
}
if (!string.IsNullOrWhiteSpace(errorResult.Error.Message))
{
if (sbError.Length > 0)
{
sbError.Append(" - ");
}
sbError.Append("Message: " + errorResult.Error.Message);
}
if (errorResult.Error.ValidationErrors != null && errorResult.Error.ValidationErrors.Any())
{
if (sbError.Length > 0)
{
sbError.Append(" - ");
}
sbError.AppendLine("Validation Errors: ");
for (var i = 0; i < errorResult.Error.ValidationErrors.Length; i++)
{
var validationError = errorResult.Error.ValidationErrors[i];
sbError.AppendLine("Validation error #" + i + ": " + validationError.Message + " - Members: " + validationError.Members.JoinAsString(", ") + ".");
}
}
return sbError.ToString();
}
}
}

9
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/SourceCodeTypes.cs

@ -0,0 +1,9 @@
namespace Volo.Abp.Cli.ProjectBuilding
{
public static class SourceCodeTypes
{
public const string Template = "template";
public const string Module = "module";
}
}

21
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuilder.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs

@ -2,7 +2,6 @@
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Cli.Commands; using Volo.Abp.Cli.Commands;
@ -14,32 +13,32 @@ using Volo.Abp.Json;
namespace Volo.Abp.Cli.ProjectBuilding namespace Volo.Abp.Cli.ProjectBuilding
{ {
public class ProjectBuilder : IProjectBuilder, ITransientDependency public class TemplateProjectBuilder : IProjectBuilder, ITransientDependency
{ {
public ILogger<ProjectBuilder> Logger { get; set; } public ILogger<TemplateProjectBuilder> Logger { get; set; }
protected ITemplateStore TemplateStore { get; } protected ISourceCodeStore SourceCodeStore { get; }
protected ITemplateInfoProvider TemplateInfoProvider { get; } protected ITemplateInfoProvider TemplateInfoProvider { get; }
protected ICliAnalyticsCollect CliAnalyticsCollect { get; } protected ICliAnalyticsCollect CliAnalyticsCollect { get; }
protected CliOptions Options { get; } protected CliOptions Options { get; }
protected IJsonSerializer JsonSerializer { get; } protected IJsonSerializer JsonSerializer { get; }
protected IApiKeyService ApiKeyService { get; } protected IApiKeyService ApiKeyService { get; }
public ProjectBuilder(ITemplateStore templateStore, public TemplateProjectBuilder(ISourceCodeStore sourceCodeStore,
ITemplateInfoProvider templateInfoProvider, ITemplateInfoProvider templateInfoProvider,
ICliAnalyticsCollect cliAnalyticsCollect, ICliAnalyticsCollect cliAnalyticsCollect,
IOptions<CliOptions> options, IOptions<CliOptions> options,
IJsonSerializer jsonSerializer, IJsonSerializer jsonSerializer,
IApiKeyService apiKeyService) IApiKeyService apiKeyService)
{ {
TemplateStore = templateStore; SourceCodeStore = sourceCodeStore;
TemplateInfoProvider = templateInfoProvider; TemplateInfoProvider = templateInfoProvider;
CliAnalyticsCollect = cliAnalyticsCollect; CliAnalyticsCollect = cliAnalyticsCollect;
Options = options.Value; Options = options.Value;
JsonSerializer = jsonSerializer; JsonSerializer = jsonSerializer;
ApiKeyService = apiKeyService; ApiKeyService = apiKeyService;
Logger = NullLogger<ProjectBuilder>.Instance; Logger = NullLogger<TemplateProjectBuilder>.Instance;
} }
public async Task<ProjectBuildResult> BuildAsync(ProjectBuildArgs args) public async Task<ProjectBuildResult> BuildAsync(ProjectBuildArgs args)
@ -48,11 +47,12 @@ namespace Volo.Abp.Cli.ProjectBuilding
NormalizeArgs(args, templateInfo); NormalizeArgs(args, templateInfo);
var templateFile = await TemplateStore.GetAsync( var templateFile = await SourceCodeStore.GetAsync(
args.TemplateName, args.TemplateName,
SourceCodeTypes.Template,
args.Version args.Version
); );
var apiKeyResult = await ApiKeyService.GetApiKeyOrNullAsync(); var apiKeyResult = await ApiKeyService.GetApiKeyOrNullAsync();
if (apiKeyResult?.ApiKey != null) if (apiKeyResult?.ApiKey != null)
{ {
@ -66,11 +66,12 @@ namespace Volo.Abp.Cli.ProjectBuilding
var context = new ProjectBuildContext( var context = new ProjectBuildContext(
templateInfo, templateInfo,
null,
templateFile, templateFile,
args args
); );
ProjectBuildPipelineBuilder.Build(context).Execute(); TemplateProjectBuildPipelineBuilder.Build(context).Execute();
if (!templateInfo.DocumentUrl.IsNullOrEmpty()) if (!templateInfo.DocumentUrl.IsNullOrEmpty())
{ {

32
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs

@ -1,6 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Text;
using JetBrains.Annotations; using JetBrains.Annotations;
using Volo.Abp.Cli.ProjectBuilding.Building; using Volo.Abp.Cli.ProjectBuilding.Building;
using Volo.Abp.Cli.ProjectBuilding.Building.Steps; using Volo.Abp.Cli.ProjectBuilding.Building.Steps;
@ -27,22 +25,24 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.Module
private void DeleteUnrelatedProjects(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps) private void DeleteUnrelatedProjects(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)
{ {
if (context.BuildArgs.ExtraProperties.ContainsKey("no-ui")) if (!context.BuildArgs.ExtraProperties.ContainsKey("no-ui"))
{ {
steps.Add(new RemoveProjectFromSolutionStep( return;
"MyCompanyName.MyProjectName.Web" }
));
steps.Add(new RemoveProjectFromSolutionStep( steps.Add(new RemoveProjectFromSolutionStep(
"MyCompanyName.MyProjectName.Web.Host", "MyCompanyName.MyProjectName.Web"
projectFolderPath: "/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host" ));
));
steps.Add(new RemoveProjectFromSolutionStep( steps.Add(new RemoveProjectFromSolutionStep(
"MyCompanyName.MyProjectName.Web.Unified", "MyCompanyName.MyProjectName.Web.Host",
projectFolderPath: "/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified" projectFolderPath: "/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host"
)); ));
}
steps.Add(new RemoveProjectFromSolutionStep(
"MyCompanyName.MyProjectName.Web.Unified",
projectFolderPath: "/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified"
));
} }
private void RandomizeSslPorts(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps) private void RandomizeSslPorts(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)

1
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/EfCoreMigrationAdder.cs

@ -1,5 +1,4 @@
using System; using System;
using System.Diagnostics;
using System.IO; using System.IO;
using Volo.Abp.Cli.Utils; using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;

1
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmPackagesUpdater.cs

@ -2,7 +2,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading; using System.Threading;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;

1
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/PackageJsonFileFinder.cs

@ -2,7 +2,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.ProjectModification namespace Volo.Abp.Cli.ProjectModification

8
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNugetPackageAdder.cs

@ -7,6 +7,7 @@ using System.Threading.Tasks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Cli.Http; using Volo.Abp.Cli.Http;
using Volo.Abp.Cli.ProjectBuilding;
using Volo.Abp.Cli.Utils; using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.IO; using Volo.Abp.IO;
@ -22,17 +23,20 @@ namespace Volo.Abp.Cli.ProjectModification
protected ProjectNpmPackageAdder NpmPackageAdder { get; } protected ProjectNpmPackageAdder NpmPackageAdder { get; }
protected DerivedClassFinder ModuleClassFinder { get; } protected DerivedClassFinder ModuleClassFinder { get; }
protected ModuleClassDependcyAdder ModuleClassDependcyAdder { get; } protected ModuleClassDependcyAdder ModuleClassDependcyAdder { get; }
protected IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; }
public ProjectNugetPackageAdder( public ProjectNugetPackageAdder(
IJsonSerializer jsonSerializer, IJsonSerializer jsonSerializer,
ProjectNpmPackageAdder npmPackageAdder, ProjectNpmPackageAdder npmPackageAdder,
DerivedClassFinder moduleClassFinder, DerivedClassFinder moduleClassFinder,
ModuleClassDependcyAdder moduleClassDependcyAdder) ModuleClassDependcyAdder moduleClassDependcyAdder,
IRemoteServiceExceptionHandler remoteServiceExceptionHandler)
{ {
JsonSerializer = jsonSerializer; JsonSerializer = jsonSerializer;
NpmPackageAdder = npmPackageAdder; NpmPackageAdder = npmPackageAdder;
ModuleClassFinder = moduleClassFinder; ModuleClassFinder = moduleClassFinder;
ModuleClassDependcyAdder = moduleClassDependcyAdder; ModuleClassDependcyAdder = moduleClassDependcyAdder;
RemoteServiceExceptionHandler = remoteServiceExceptionHandler;
Logger = NullLogger<ProjectNugetPackageAdder>.Instance; Logger = NullLogger<ProjectNugetPackageAdder>.Instance;
} }
@ -84,7 +88,7 @@ namespace Volo.Abp.Cli.ProjectModification
throw new CliUsageException($"'{moduleName}' nuget package could not be found!"); throw new CliUsageException($"'{moduleName}' nuget package could not be found!");
} }
throw new Exception($"ERROR: Remote server returns '{response.StatusCode}'"); await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response);
} }
var responseContent = await response.Content.ReadAsStringAsync(); var responseContent = await response.Content.ReadAsStringAsync();

8
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs

@ -8,6 +8,7 @@ using System.Linq;
using System.Net; using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Cli.Http; using Volo.Abp.Cli.Http;
using Volo.Abp.Cli.ProjectBuilding;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Json; using Volo.Abp.Json;
@ -24,6 +25,7 @@ namespace Volo.Abp.Cli.ProjectModification
protected DerivedClassFinder DerivedClassFinder { get; } protected DerivedClassFinder DerivedClassFinder { get; }
protected ProjectNpmPackageAdder ProjectNpmPackageAdder { get; } protected ProjectNpmPackageAdder ProjectNpmPackageAdder { get; }
protected NpmGlobalPackagesChecker NpmGlobalPackagesChecker { get; } protected NpmGlobalPackagesChecker NpmGlobalPackagesChecker { get; }
protected IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; }
public SolutionModuleAdder( public SolutionModuleAdder(
IJsonSerializer jsonSerializer, IJsonSerializer jsonSerializer,
@ -32,7 +34,8 @@ namespace Volo.Abp.Cli.ProjectModification
EfCoreMigrationAdder efCoreMigrationAdder, EfCoreMigrationAdder efCoreMigrationAdder,
DerivedClassFinder derivedClassFinder, DerivedClassFinder derivedClassFinder,
ProjectNpmPackageAdder projectNpmPackageAdder, ProjectNpmPackageAdder projectNpmPackageAdder,
NpmGlobalPackagesChecker npmGlobalPackagesChecker) NpmGlobalPackagesChecker npmGlobalPackagesChecker,
IRemoteServiceExceptionHandler remoteServiceExceptionHandler)
{ {
JsonSerializer = jsonSerializer; JsonSerializer = jsonSerializer;
ProjectNugetPackageAdder = projectNugetPackageAdder; ProjectNugetPackageAdder = projectNugetPackageAdder;
@ -41,6 +44,7 @@ namespace Volo.Abp.Cli.ProjectModification
DerivedClassFinder = derivedClassFinder; DerivedClassFinder = derivedClassFinder;
ProjectNpmPackageAdder = projectNpmPackageAdder; ProjectNpmPackageAdder = projectNpmPackageAdder;
NpmGlobalPackagesChecker = npmGlobalPackagesChecker; NpmGlobalPackagesChecker = npmGlobalPackagesChecker;
RemoteServiceExceptionHandler = remoteServiceExceptionHandler;
Logger = NullLogger<SolutionModuleAdder>.Instance; Logger = NullLogger<SolutionModuleAdder>.Instance;
} }
@ -142,7 +146,7 @@ namespace Volo.Abp.Cli.ProjectModification
throw new CliUsageException($"ERROR: '{moduleName}' module could not be found!"); throw new CliUsageException($"ERROR: '{moduleName}' module could not be found!");
} }
throw new Exception($"ERROR: Remote server returns '{response.StatusCode}'"); await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response);
} }
var responseContent = await response.Content.ReadAsStringAsync(); var responseContent = await response.Content.ReadAsStringAsync();

19
framework/src/Volo.Abp.Core/System/AbpStringExtensions.cs

@ -293,6 +293,25 @@ namespace System
: Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + " " + char.ToLowerInvariant(m.Value[1])); : Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + " " + char.ToLowerInvariant(m.Value[1]));
} }
/// <summary>
/// Converts given PascalCase/camelCase string to kebab-case.
/// </summary>
/// <param name="str">String to convert.</param>
/// <param name="useCurrentCulture">set true to use current culture. Otherwise, invariant culture will be used.</param>
public static string ToKebabCase(this string str, bool useCurrentCulture = false)
{
if (string.IsNullOrWhiteSpace(str))
{
return str;
}
str = str.ToCamelCase();
return useCurrentCulture
? Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + "-" + char.ToLower(m.Value[1]))
: Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + "-" + char.ToLowerInvariant(m.Value[1]));
}
/// <summary> /// <summary>
/// Converts string to enum value. /// Converts string to enum value.
/// </summary> /// </summary>

4
framework/src/Volo.Abp.Core/Volo/Abp/Configuration/IConfigurationAccessor.cs

@ -1,7 +1,9 @@
using Microsoft.Extensions.Configuration; using System;
using Microsoft.Extensions.Configuration;
namespace Volo.Abp.Configuration namespace Volo.Abp.Configuration
{ {
[Obsolete("IConfigurationAccessor will be removed in v1.0. Use IConfiguration instead (be use that you are using generic host just like the startup templates).")]
public interface IConfigurationAccessor public interface IConfigurationAccessor
{ {
IConfigurationRoot Configuration { get; } IConfigurationRoot Configuration { get; }

15
framework/src/Volo.Abp.Core/Volo/Abp/Internal/InternalServiceCollectionExtensions.cs

@ -24,14 +24,19 @@ namespace Volo.Abp.Internal
var assemblyFinder = new AssemblyFinder(abpApplication); var assemblyFinder = new AssemblyFinder(abpApplication);
var typeFinder = new TypeFinder(assemblyFinder); var typeFinder = new TypeFinder(assemblyFinder);
services.TryAddSingleton<IConfigurationAccessor>( var configurationAccessor = new DefaultConfigurationAccessor(
new DefaultConfigurationAccessor( ConfigurationHelper.BuildConfiguration(
ConfigurationHelper.BuildConfiguration( applicationCreationOptions.Configuration
applicationCreationOptions.Configuration
)
) )
); );
services.TryAddSingleton<IConfigurationAccessor>(configurationAccessor);
if (!services.IsAdded<IConfiguration>())
{
services.AddSingleton<IConfiguration>(configurationAccessor.Configuration);
}
services.TryAddSingleton<IModuleLoader>(moduleLoader); services.TryAddSingleton<IModuleLoader>(moduleLoader);
services.TryAddSingleton<IAssemblyFinder>(assemblyFinder); services.TryAddSingleton<IAssemblyFinder>(assemblyFinder);
services.TryAddSingleton<ITypeFinder>(typeFinder); services.TryAddSingleton<ITypeFinder>(typeFinder);

18
framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpCommonDbProperties.cs

@ -0,0 +1,18 @@
namespace Volo.Abp.Data
{
public static class AbpCommonDbProperties
{
/// <summary>
/// This table prefix is shared by most of the ABP modules.
/// You can change it to set table prefix for all modules using this.
///
/// Default value: "Abp".
/// </summary>
public static string DbTablePrefix { get; set; } = "Abp";
/// <summary>
/// Default value: null.
/// </summary>
public static string DbSchema { get; set; } = null;
}
}

2
framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo.Abp.EntityFrameworkCore.PostgreSql.csproj

@ -18,7 +18,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.0.0-preview9" /> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.0.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>

12
framework/test/Volo.Abp.Core.Tests/System/StringExtensions_Tests.cs

@ -73,12 +73,24 @@ namespace System
"Istanbul".ToCamelCase().ShouldBe("istanbul"); "Istanbul".ToCamelCase().ShouldBe("istanbul");
} }
[Fact]
public void ToKebabCase_Test()
{
(null as string).ToKebabCase().ShouldBe(null);
"helloMoon".ToKebabCase().ShouldBe("hello-moon");
"HelloWorld".ToKebabCase().ShouldBe("hello-world");
"HelloIsparta".ToKebabCase().ShouldBe("hello-isparta");
"ThisIsSampleText".ToKebabCase().ShouldBe("this-is-sample-text");
}
[Fact] [Fact]
public void ToSentenceCase_Test() public void ToSentenceCase_Test()
{ {
(null as string).ToSentenceCase().ShouldBe(null); (null as string).ToSentenceCase().ShouldBe(null);
"HelloWorld".ToSentenceCase().ShouldBe("Hello world"); "HelloWorld".ToSentenceCase().ShouldBe("Hello world");
"HelloIsparta".ToSentenceCase().ShouldBe("Hello isparta"); "HelloIsparta".ToSentenceCase().ShouldBe("Hello isparta");
"ThisIsSampleSentence".ToSentenceCase().ShouldBe("This is sample sentence");
"thisIsSampleSentence".ToSentenceCase().ShouldBe("this is sample sentence");
} }
[Fact] [Fact]

5
modules/account/src/Volo.Abp.Account.Web.IdentityServer/AbpAccountWebIdentityServerModule.cs

@ -19,6 +19,11 @@ namespace Volo.Abp.Account.Web
{ {
options.ConfigureAuthentication = false; options.ConfigureAuthentication = false;
}); });
PreConfigure<IMvcBuilder>(mvcBuilder =>
{
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpAccountWebIdentityServerModule).Assembly);
});
} }
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)

5
modules/account/src/Volo.Abp.Account.Web/AbpAccountWebModule.cs

@ -26,6 +26,11 @@ namespace Volo.Abp.Account.Web
{ {
options.AddAssemblyResource(typeof(AccountResource), typeof(AbpAccountWebModule).Assembly); options.AddAssemblyResource(typeof(AccountResource), typeof(AbpAccountWebModule).Assembly);
}); });
PreConfigure<IMvcBuilder>(mvcBuilder =>
{
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpAccountWebModule).Assembly);
});
} }
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)

12
modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AbpAuditLoggingConsts.cs

@ -1,12 +0,0 @@

namespace Volo.Abp.AuditLogging
{
public static class AbpAuditLoggingConsts
{
public const string DefaultDbTablePrefix = "Abp";
public const string DefaultDbSchema = null;
public const string ConnectionStringName = "AbpAuditLogging";
}
}

13
modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AbpAuditLoggingDbProperties.cs

@ -0,0 +1,13 @@
using Volo.Abp.Data;
namespace Volo.Abp.AuditLogging
{
public static class AbpAuditLoggingDbProperties
{
public static string DbTablePrefix { get; set; } = AbpCommonDbProperties.DbTablePrefix;
public static string DbSchema { get; set; } = AbpCommonDbProperties.DbSchema;
public const string ConnectionStringName = "AbpAuditLogging";
}
}

8
modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingDbContext.cs

@ -4,13 +4,9 @@ using Volo.Abp.EntityFrameworkCore;
namespace Volo.Abp.AuditLogging.EntityFrameworkCore namespace Volo.Abp.AuditLogging.EntityFrameworkCore
{ {
[ConnectionStringName(AbpAuditLoggingConsts.ConnectionStringName)] [ConnectionStringName(AbpAuditLoggingDbProperties.ConnectionStringName)]
public class AbpAuditLoggingDbContext : AbpDbContext<AbpAuditLoggingDbContext>, IAuditLoggingDbContext public class AbpAuditLoggingDbContext : AbpDbContext<AbpAuditLoggingDbContext>, IAuditLoggingDbContext
{ {
public static string TablePrefix { get; set; } = AbpAuditLoggingConsts.DefaultDbTablePrefix;
public static string Schema { get; set; } = AbpAuditLoggingConsts.DefaultDbSchema;
public DbSet<AuditLog> AuditLogs { get; set; } public DbSet<AuditLog> AuditLogs { get; set; }
public AbpAuditLoggingDbContext(DbContextOptions<AbpAuditLoggingDbContext> options) public AbpAuditLoggingDbContext(DbContextOptions<AbpAuditLoggingDbContext> options)
@ -23,7 +19,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
{ {
base.OnModelCreating(builder); base.OnModelCreating(builder);
builder.ConfigureAuditLogging(TablePrefix, Schema); builder.ConfigureAuditLogging();
} }
} }
} }

27
modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingtDbContextModelBuilderExtensions.cs → modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingDbContextModelBuilderExtensions.cs

@ -1,26 +1,29 @@
using JetBrains.Annotations; using System;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.Modeling; using Volo.Abp.EntityFrameworkCore.Modeling;
using Volo.Abp.Identity.EntityFrameworkCore;
namespace Volo.Abp.AuditLogging.EntityFrameworkCore namespace Volo.Abp.AuditLogging.EntityFrameworkCore
{ {
public static class AbpAuditLoggingtDbContextModelBuilderExtensions public static class AbpAuditLoggingDbContextModelBuilderExtensions
{ {
public static void ConfigureAuditLogging( public static void ConfigureAuditLogging(
[NotNull] this ModelBuilder builder, [NotNull] this ModelBuilder builder,
[CanBeNull] string tablePrefix = AbpAuditLoggingConsts.DefaultDbTablePrefix, Action<AbpAuditLoggingModelBuilderConfigurationOptions> optionsAction = null)
[CanBeNull] string schema = AbpAuditLoggingConsts.DefaultDbSchema)
{ {
Check.NotNull(builder, nameof(builder)); Check.NotNull(builder, nameof(builder));
if (tablePrefix == null) var options = new AbpAuditLoggingModelBuilderConfigurationOptions(
{ AbpAuditLoggingDbProperties.DbTablePrefix,
tablePrefix = ""; AbpAuditLoggingDbProperties.DbSchema
} );
optionsAction?.Invoke(options);
builder.Entity<AuditLog>(b => builder.Entity<AuditLog>(b =>
{ {
b.ToTable(tablePrefix + "AuditLogs", schema); b.ToTable(options.TablePrefix + "AuditLogs", options.Schema);
b.ConfigureExtraProperties(); b.ConfigureExtraProperties();
@ -51,7 +54,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
builder.Entity<AuditLogAction>(b => builder.Entity<AuditLogAction>(b =>
{ {
b.ToTable(tablePrefix + "AuditLogActions", schema); b.ToTable(options.TablePrefix + "AuditLogActions", options.Schema);
b.ConfigureExtraProperties(); b.ConfigureExtraProperties();
@ -68,7 +71,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
builder.Entity<EntityChange>(b => builder.Entity<EntityChange>(b =>
{ {
b.ToTable(tablePrefix + "EntityChanges", schema); b.ToTable(options.TablePrefix + "EntityChanges", options.Schema);
b.ConfigureExtraProperties(); b.ConfigureExtraProperties();
@ -87,7 +90,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
builder.Entity<EntityPropertyChange>(b => builder.Entity<EntityPropertyChange>(b =>
{ {
b.ToTable(tablePrefix + "EntityPropertyChanges", schema); b.ToTable(options.TablePrefix + "EntityPropertyChanges", options.Schema);
b.Property(x => x.NewValue).HasMaxLength(EntityPropertyChangeConsts.MaxNewValueLength).HasColumnName(nameof(EntityPropertyChange.NewValue)); b.Property(x => x.NewValue).HasMaxLength(EntityPropertyChangeConsts.MaxNewValueLength).HasColumnName(nameof(EntityPropertyChange.NewValue));
b.Property(x => x.PropertyName).HasMaxLength(EntityPropertyChangeConsts.MaxPropertyNameLength).IsRequired().HasColumnName(nameof(EntityPropertyChange.PropertyName)); b.Property(x => x.PropertyName).HasMaxLength(EntityPropertyChangeConsts.MaxPropertyNameLength).IsRequired().HasColumnName(nameof(EntityPropertyChange.PropertyName));

18
modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingModelBuilderConfigurationOptions.cs

@ -0,0 +1,18 @@
using JetBrains.Annotations;
using Volo.Abp.EntityFrameworkCore.Modeling;
namespace Volo.Abp.Identity.EntityFrameworkCore
{
public class AbpAuditLoggingModelBuilderConfigurationOptions : ModelBuilderConfigurationOptions
{
public AbpAuditLoggingModelBuilderConfigurationOptions(
[NotNull] string tablePrefix,
[CanBeNull] string schema)
: base(
tablePrefix,
schema)
{
}
}
}

4
modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs

@ -110,8 +110,8 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
.IncludeDetails(includeDetails) .IncludeDetails(includeDetails)
.WhereIf(startTime.HasValue, auditLog => auditLog.ExecutionTime >= startTime) .WhereIf(startTime.HasValue, auditLog => auditLog.ExecutionTime >= startTime)
.WhereIf(endTime.HasValue, auditLog => auditLog.ExecutionTime <= endTime) .WhereIf(endTime.HasValue, auditLog => auditLog.ExecutionTime <= endTime)
.WhereIf(hasException.HasValue && hasException.Value, auditLog => auditLog.Exceptions != null) .WhereIf(hasException.HasValue && hasException.Value, auditLog => auditLog.Exceptions != null && auditLog.Exceptions != "")
.WhereIf(hasException.HasValue && !hasException.Value, auditLog => auditLog.Exceptions == null) .WhereIf(hasException.HasValue && !hasException.Value, auditLog => auditLog.Exceptions == null || auditLog.Exceptions == "")
.WhereIf(httpMethod != null, auditLog => auditLog.HttpMethod == httpMethod) .WhereIf(httpMethod != null, auditLog => auditLog.HttpMethod == httpMethod)
.WhereIf(url != null, auditLog => auditLog.Url != null && auditLog.Url.Contains(url)) .WhereIf(url != null, auditLog => auditLog.Url != null && auditLog.Url.Contains(url))
.WhereIf(userName != null, auditLog => auditLog.UserName == userName) .WhereIf(userName != null, auditLog => auditLog.UserName == userName)

2
modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/IAuditLoggingDbContext.cs

@ -4,7 +4,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace Volo.Abp.AuditLogging.EntityFrameworkCore namespace Volo.Abp.AuditLogging.EntityFrameworkCore
{ {
[ConnectionStringName(AbpAuditLoggingConsts.ConnectionStringName)] [ConnectionStringName(AbpAuditLoggingDbProperties.ConnectionStringName)]
public interface IAuditLoggingDbContext : IEfCoreDbContext public interface IAuditLoggingDbContext : IEfCoreDbContext
{ {
DbSet<AuditLog> AuditLogs { get; set; } DbSet<AuditLog> AuditLogs { get; set; }

6
modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/AbpAuditLoggingMongoDbContextExtensions.cs

@ -7,11 +7,13 @@ namespace Volo.Abp.AuditLogging.MongoDB
{ {
public static void ConfigureAuditLogging( public static void ConfigureAuditLogging(
this IMongoModelBuilder builder, this IMongoModelBuilder builder,
Action<MongoModelBuilderConfigurationOptions> optionsAction = null) Action<AuditLoggingMongoModelBuilderConfigurationOptions> optionsAction = null)
{ {
Check.NotNull(builder, nameof(builder)); Check.NotNull(builder, nameof(builder));
var options = new AuditLoggingMongoModelBuilderConfigurationOptions(); var options = new AuditLoggingMongoModelBuilderConfigurationOptions(
AbpAuditLoggingDbProperties.DbTablePrefix
);
optionsAction?.Invoke(options); optionsAction?.Invoke(options);

9
modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/AuditLoggingMongoDbContext.cs

@ -4,21 +4,16 @@ using Volo.Abp.MongoDB;
namespace Volo.Abp.AuditLogging.MongoDB namespace Volo.Abp.AuditLogging.MongoDB
{ {
[ConnectionStringName(AbpAuditLoggingConsts.ConnectionStringName)] [ConnectionStringName(AbpAuditLoggingDbProperties.ConnectionStringName)]
public class AuditLoggingMongoDbContext : AbpMongoDbContext, IAuditLoggingMongoDbContext public class AuditLoggingMongoDbContext : AbpMongoDbContext, IAuditLoggingMongoDbContext
{ {
public static string CollectionPrefix { get; set; } = AbpAuditLoggingConsts.DefaultDbTablePrefix;
public IMongoCollection<AuditLog> AuditLogs => Collection<AuditLog>(); public IMongoCollection<AuditLog> AuditLogs => Collection<AuditLog>();
protected override void CreateModel(IMongoModelBuilder modelBuilder) protected override void CreateModel(IMongoModelBuilder modelBuilder)
{ {
base.CreateModel(modelBuilder); base.CreateModel(modelBuilder);
modelBuilder.ConfigureAuditLogging(options => modelBuilder.ConfigureAuditLogging();
{
options.CollectionPrefix = CollectionPrefix;
});
} }
} }
} }

5
modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/AuditLoggingMongoModelBuilderConfigurationOptions.cs

@ -5,8 +5,9 @@ namespace Volo.Abp.AuditLogging.MongoDB
{ {
public class AuditLoggingMongoModelBuilderConfigurationOptions : MongoModelBuilderConfigurationOptions public class AuditLoggingMongoModelBuilderConfigurationOptions : MongoModelBuilderConfigurationOptions
{ {
public AuditLoggingMongoModelBuilderConfigurationOptions([NotNull] string tablePrefix = AbpAuditLoggingConsts.DefaultDbTablePrefix) public AuditLoggingMongoModelBuilderConfigurationOptions(
: base(tablePrefix) [NotNull] string collectionPrefix = "")
: base(collectionPrefix)
{ {
} }
} }

2
modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/IAuditLoggingMongoDbContext.cs

@ -4,7 +4,7 @@ using Volo.Abp.MongoDB;
namespace Volo.Abp.AuditLogging.MongoDB namespace Volo.Abp.AuditLogging.MongoDB
{ {
[ConnectionStringName(AbpAuditLoggingConsts.ConnectionStringName)] [ConnectionStringName(AbpAuditLoggingDbProperties.ConnectionStringName)]
public interface IAuditLoggingMongoDbContext : IAbpMongoDbContext public interface IAuditLoggingMongoDbContext : IAbpMongoDbContext
{ {
IMongoCollection<AuditLog> AuditLogs { get; } IMongoCollection<AuditLog> AuditLogs { get; }

4
modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs

@ -109,8 +109,8 @@ namespace Volo.Abp.AuditLogging.MongoDB
return GetMongoQueryable() return GetMongoQueryable()
.WhereIf(startTime.HasValue, auditLog => auditLog.ExecutionTime >= startTime) .WhereIf(startTime.HasValue, auditLog => auditLog.ExecutionTime >= startTime)
.WhereIf(endTime.HasValue, auditLog => auditLog.ExecutionTime <= endTime) .WhereIf(endTime.HasValue, auditLog => auditLog.ExecutionTime <= endTime)
.WhereIf(hasException.HasValue && hasException.Value, auditLog => auditLog.Exceptions != null) .WhereIf(hasException.HasValue && hasException.Value, auditLog => auditLog.Exceptions != null && auditLog.Exceptions != "")
.WhereIf(hasException.HasValue && !hasException.Value, auditLog => auditLog.Exceptions == null) .WhereIf(hasException.HasValue && !hasException.Value, auditLog => auditLog.Exceptions == null || auditLog.Exceptions == "")
.WhereIf(httpMethod != null, auditLog => auditLog.HttpMethod == httpMethod) .WhereIf(httpMethod != null, auditLog => auditLog.HttpMethod == httpMethod)
.WhereIf(url != null, auditLog => auditLog.Url != null && auditLog.Url.Contains(url)) .WhereIf(url != null, auditLog => auditLog.Url != null && auditLog.Url.Contains(url))
.WhereIf(userName != null, auditLog => auditLog.UserName == userName) .WhereIf(userName != null, auditLog => auditLog.UserName == userName)

11
modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobsConsts.cs

@ -1,11 +0,0 @@
namespace Volo.Abp.BackgroundJobs
{
public static class BackgroundJobsConsts
{
public const string DefaultDbTablePrefix = "Abp";
public const string DefaultDbSchema = null;
public const string ConnectionStringName = "AbpBackgroundJobs";
}
}

13
modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobsDbProperties.cs

@ -0,0 +1,13 @@
using Volo.Abp.Data;
namespace Volo.Abp.BackgroundJobs
{
public static class BackgroundJobsDbProperties
{
public static string DbTablePrefix { get; set; } = AbpCommonDbProperties.DbTablePrefix;
public static string DbSchema { get; set; } = AbpCommonDbProperties.DbSchema;
public const string ConnectionStringName = "AbpBackgroundJobs";
}
}

12
modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/BackgroundJobsDbContext.cs

@ -4,13 +4,9 @@ using Volo.Abp.EntityFrameworkCore;
namespace Volo.Abp.BackgroundJobs.EntityFrameworkCore namespace Volo.Abp.BackgroundJobs.EntityFrameworkCore
{ {
[ConnectionStringName(BackgroundJobsConsts.ConnectionStringName)] [ConnectionStringName(BackgroundJobsDbProperties.ConnectionStringName)]
public class BackgroundJobsDbContext : AbpDbContext<BackgroundJobsDbContext>, IBackgroundJobsDbContext public class BackgroundJobsDbContext : AbpDbContext<BackgroundJobsDbContext>, IBackgroundJobsDbContext
{ {
public static string TablePrefix { get; set; } = BackgroundJobsConsts.DefaultDbTablePrefix;
public static string Schema { get; set; } = BackgroundJobsConsts.DefaultDbSchema;
public DbSet<BackgroundJobRecord> BackgroundJobs { get; set; } public DbSet<BackgroundJobRecord> BackgroundJobs { get; set; }
public BackgroundJobsDbContext(DbContextOptions<BackgroundJobsDbContext> options) public BackgroundJobsDbContext(DbContextOptions<BackgroundJobsDbContext> options)
@ -23,11 +19,7 @@ namespace Volo.Abp.BackgroundJobs.EntityFrameworkCore
{ {
base.OnModelCreating(builder); base.OnModelCreating(builder);
builder.ConfigureBackgroundJobs(options => builder.ConfigureBackgroundJobs();
{
options.TablePrefix = TablePrefix;
options.Schema = Schema;
});
} }
} }
} }

5
modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/BackgroundJobsDbContextModelCreatingExtensions.cs

@ -12,7 +12,10 @@ namespace Volo.Abp.BackgroundJobs.EntityFrameworkCore
{ {
Check.NotNull(builder, nameof(builder)); Check.NotNull(builder, nameof(builder));
var options = new BackgroundJobsModelBuilderConfigurationOptions(); var options = new BackgroundJobsModelBuilderConfigurationOptions(
BackgroundJobsDbProperties.DbTablePrefix,
BackgroundJobsDbProperties.DbSchema
);
optionsAction?.Invoke(options); optionsAction?.Invoke(options);

4
modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/BackgroundJobsModelBuilderConfigurationOptions.cs

@ -6,8 +6,8 @@ namespace Volo.Abp.BackgroundJobs.EntityFrameworkCore
public class BackgroundJobsModelBuilderConfigurationOptions : ModelBuilderConfigurationOptions public class BackgroundJobsModelBuilderConfigurationOptions : ModelBuilderConfigurationOptions
{ {
public BackgroundJobsModelBuilderConfigurationOptions( public BackgroundJobsModelBuilderConfigurationOptions(
[NotNull] string tablePrefix = BackgroundJobsConsts.DefaultDbTablePrefix, [NotNull] string tablePrefix = "",
[CanBeNull] string schema = BackgroundJobsConsts.DefaultDbSchema) [CanBeNull] string schema = null)
: base( : base(
tablePrefix, tablePrefix,
schema) schema)

2
modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/IBackgroundJobsDbContext.cs

@ -4,7 +4,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace Volo.Abp.BackgroundJobs.EntityFrameworkCore namespace Volo.Abp.BackgroundJobs.EntityFrameworkCore
{ {
[ConnectionStringName(BackgroundJobsConsts.ConnectionStringName)] [ConnectionStringName(BackgroundJobsDbProperties.ConnectionStringName)]
public interface IBackgroundJobsDbContext : IEfCoreDbContext public interface IBackgroundJobsDbContext : IEfCoreDbContext
{ {
DbSet<BackgroundJobRecord> BackgroundJobs { get; } DbSet<BackgroundJobRecord> BackgroundJobs { get; }

9
modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/BackgroundJobsMongoDbContext.cs

@ -4,21 +4,16 @@ using Volo.Abp.MongoDB;
namespace Volo.Abp.BackgroundJobs.MongoDB namespace Volo.Abp.BackgroundJobs.MongoDB
{ {
[ConnectionStringName(BackgroundJobsConsts.ConnectionStringName)] [ConnectionStringName(BackgroundJobsDbProperties.ConnectionStringName)]
public class BackgroundJobsMongoDbContext : AbpMongoDbContext, IBackgroundJobsMongoDbContext public class BackgroundJobsMongoDbContext : AbpMongoDbContext, IBackgroundJobsMongoDbContext
{ {
public static string CollectionPrefix { get; set; } = BackgroundJobsConsts.DefaultDbTablePrefix;
public IMongoCollection<BackgroundJobRecord> BackgroundJobs { get; set; } public IMongoCollection<BackgroundJobRecord> BackgroundJobs { get; set; }
protected override void CreateModel(IMongoModelBuilder modelBuilder) protected override void CreateModel(IMongoModelBuilder modelBuilder)
{ {
base.CreateModel(modelBuilder); base.CreateModel(modelBuilder);
modelBuilder.ConfigureBackgroundJobs(options => modelBuilder.ConfigureBackgroundJobs();
{
options.CollectionPrefix = CollectionPrefix;
});
} }
} }
} }

4
modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/BackgroundJobsMongoDbContextExtensions.cs

@ -11,7 +11,9 @@ namespace Volo.Abp.BackgroundJobs.MongoDB
{ {
Check.NotNull(builder, nameof(builder)); Check.NotNull(builder, nameof(builder));
var options = new BackgroundJobsMongoModelBuilderConfigurationOptions(); var options = new BackgroundJobsMongoModelBuilderConfigurationOptions(
BackgroundJobsDbProperties.DbTablePrefix
);
optionsAction?.Invoke(options); optionsAction?.Invoke(options);

4
modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/BackgroundJobsMongoModelBuilderConfigurationOptions.cs

@ -6,8 +6,8 @@ namespace Volo.Abp.BackgroundJobs.MongoDB
public class BackgroundJobsMongoModelBuilderConfigurationOptions : MongoModelBuilderConfigurationOptions public class BackgroundJobsMongoModelBuilderConfigurationOptions : MongoModelBuilderConfigurationOptions
{ {
public BackgroundJobsMongoModelBuilderConfigurationOptions( public BackgroundJobsMongoModelBuilderConfigurationOptions(
[NotNull] string tablePrefix = BackgroundJobsConsts.DefaultDbTablePrefix) [NotNull] string collectionPrefix = "")
: base(tablePrefix) : base(collectionPrefix)
{ {
} }
} }

2
modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/IBackgroundJobsMongoDbContext.cs

@ -4,7 +4,7 @@ using Volo.Abp.MongoDB;
namespace Volo.Abp.BackgroundJobs.MongoDB namespace Volo.Abp.BackgroundJobs.MongoDB
{ {
[ConnectionStringName(BackgroundJobsConsts.ConnectionStringName)] [ConnectionStringName(BackgroundJobsDbProperties.ConnectionStringName)]
public interface IBackgroundJobsMongoDbContext : IAbpMongoDbContext public interface IBackgroundJobsMongoDbContext : IAbpMongoDbContext
{ {
IMongoCollection<BackgroundJobRecord> BackgroundJobs { get; } IMongoCollection<BackgroundJobRecord> BackgroundJobs { get; }

9
modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/BloggingConsts.cs

@ -1,9 +0,0 @@
namespace Volo.Blogging
{
public static class BloggingConsts
{
public const string DefaultDbTablePrefix = "Blg";
public const string DefaultDbSchema = null;
public const string ConnectionStringName = "Blogging";
}
}

20
modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/BloggingDbProperties.cs

@ -0,0 +1,20 @@
namespace Volo.Blogging
{
public static class BloggingDbProperties
{
/// <summary>
/// Default value: "Blg".
/// </summary>
public static string DbTablePrefix { get; set; } = "Blg";
/// <summary>
/// Default value: "null".
/// </summary>
public static string DbSchema { get; set; } = null;
/// <summary>
/// "Blogging".
/// </summary>
public const string ConnectionStringName = "Blogging";
}
}

11
modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/BloggingDbContext.cs

@ -9,12 +9,9 @@ using Volo.Blogging.Users;
namespace Volo.Blogging.EntityFrameworkCore namespace Volo.Blogging.EntityFrameworkCore
{ {
[ConnectionStringName(BloggingConsts.ConnectionStringName)] [ConnectionStringName(BloggingDbProperties.ConnectionStringName)]
public class BloggingDbContext : AbpDbContext<BloggingDbContext>, IBloggingDbContext public class BloggingDbContext : AbpDbContext<BloggingDbContext>, IBloggingDbContext
{ {
public static string TablePrefix { get; set; } = BloggingConsts.DefaultDbTablePrefix;
public static string Schema { get; set; } = BloggingConsts.DefaultDbSchema;
public DbSet<BlogUser> Users { get; set; } public DbSet<BlogUser> Users { get; set; }
public DbSet<Blog> Blogs { get; set; } public DbSet<Blog> Blogs { get; set; }
@ -37,11 +34,7 @@ namespace Volo.Blogging.EntityFrameworkCore
{ {
base.OnModelCreating(builder); base.OnModelCreating(builder);
builder.ConfigureBlogging(options => builder.ConfigureBlogging();
{
options.TablePrefix = TablePrefix;
options.Schema = Schema;
});
} }
} }
} }

6
modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/BloggingDbContextModelBuilderExtensions.cs

@ -20,7 +20,11 @@ namespace Volo.Blogging.EntityFrameworkCore
{ {
Check.NotNull(builder, nameof(builder)); Check.NotNull(builder, nameof(builder));
var options = new BloggingModelBuilderConfigurationOptions(); var options = new BloggingModelBuilderConfigurationOptions(
BloggingDbProperties.DbTablePrefix,
BloggingDbProperties.DbSchema
);
optionsAction?.Invoke(options); optionsAction?.Invoke(options);
builder.Entity<BlogUser>(b => builder.Entity<BlogUser>(b =>

9
modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/BloggingModelBuilderConfigurationOptions.cs

@ -1,11 +1,14 @@
using Volo.Abp.EntityFrameworkCore.Modeling; using JetBrains.Annotations;
using Volo.Abp.EntityFrameworkCore.Modeling;
namespace Volo.Blogging.EntityFrameworkCore namespace Volo.Blogging.EntityFrameworkCore
{ {
public class BloggingModelBuilderConfigurationOptions : ModelBuilderConfigurationOptions public class BloggingModelBuilderConfigurationOptions : ModelBuilderConfigurationOptions
{ {
public BloggingModelBuilderConfigurationOptions() public BloggingModelBuilderConfigurationOptions(
: base(BloggingConsts.DefaultDbTablePrefix, BloggingConsts.DefaultDbSchema) [NotNull] string tablePrefix = "",
[CanBeNull] string schema = null)
: base(tablePrefix, schema)
{ {
} }
} }

2
modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/IBloggingDbContext.cs

@ -9,7 +9,7 @@ using Volo.Blogging.Users;
namespace Volo.Blogging.EntityFrameworkCore namespace Volo.Blogging.EntityFrameworkCore
{ {
[ConnectionStringName(BloggingConsts.ConnectionStringName)] [ConnectionStringName(BloggingDbProperties.ConnectionStringName)]
public interface IBloggingDbContext : IEfCoreDbContext public interface IBloggingDbContext : IEfCoreDbContext
{ {
DbSet<BlogUser> Users { get; } DbSet<BlogUser> Users { get; }

14
modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/MongoDB/BloggingMongoDbContext.cs

@ -1,7 +1,4 @@
using System; using MongoDB.Driver;
using System.Collections.Generic;
using System.Text;
using MongoDB.Driver;
using Volo.Abp.Data; using Volo.Abp.Data;
using Volo.Abp.MongoDB; using Volo.Abp.MongoDB;
using Volo.Blogging.Blogs; using Volo.Blogging.Blogs;
@ -11,11 +8,9 @@ using Volo.Blogging.Users;
namespace Volo.Blogging.MongoDB namespace Volo.Blogging.MongoDB
{ {
[ConnectionStringName(BloggingConsts.ConnectionStringName)] [ConnectionStringName(BloggingDbProperties.ConnectionStringName)]
public class BloggingMongoDbContext : AbpMongoDbContext, IBloggingMongoDbContext public class BloggingMongoDbContext : AbpMongoDbContext, IBloggingMongoDbContext
{ {
public static string CollectionPrefix { get; set; } = BloggingConsts.DefaultDbTablePrefix;
public IMongoCollection<BlogUser> Users => Collection<BlogUser>(); public IMongoCollection<BlogUser> Users => Collection<BlogUser>();
public IMongoCollection<Blog> Blogs => Collection<Blog>(); public IMongoCollection<Blog> Blogs => Collection<Blog>();
@ -30,10 +25,7 @@ namespace Volo.Blogging.MongoDB
{ {
base.CreateModel(modelBuilder); base.CreateModel(modelBuilder);
modelBuilder.ConfigureBlogging(options => modelBuilder.ConfigureBlogging();
{
options.CollectionPrefix = CollectionPrefix;
});
} }
} }
} }

6
modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/MongoDB/BloggingMongoDbContextExtensions.cs

@ -1,6 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.MongoDB; using Volo.Abp.MongoDB;
using Volo.Blogging.Blogs; using Volo.Blogging.Blogs;
@ -18,7 +16,9 @@ namespace Volo.Blogging.MongoDB
{ {
Check.NotNull(builder, nameof(builder)); Check.NotNull(builder, nameof(builder));
var options = new BloggingMongoModelBuilderConfigurationOptions(); var options = new BloggingMongoModelBuilderConfigurationOptions(
BloggingDbProperties.DbTablePrefix
);
optionsAction?.Invoke(options); optionsAction?.Invoke(options);

10
modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/MongoDB/BloggingMongoModelBuilderConfigurationOptions.cs

@ -1,15 +1,13 @@
using System; using JetBrains.Annotations;
using System.Collections.Generic;
using System.Text;
using JetBrains.Annotations;
using Volo.Abp.MongoDB; using Volo.Abp.MongoDB;
namespace Volo.Blogging.MongoDB namespace Volo.Blogging.MongoDB
{ {
public class BloggingMongoModelBuilderConfigurationOptions : MongoModelBuilderConfigurationOptions public class BloggingMongoModelBuilderConfigurationOptions : MongoModelBuilderConfigurationOptions
{ {
public BloggingMongoModelBuilderConfigurationOptions([NotNull] string tablePrefix = BloggingConsts.DefaultDbTablePrefix) public BloggingMongoModelBuilderConfigurationOptions(
: base(tablePrefix) [NotNull] string collectionPrefix = "")
: base(collectionPrefix)
{ {
} }
} }

2
modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/MongoDB/IBloggingMongoDbContext.cs

@ -8,7 +8,7 @@ using Volo.Blogging.Users;
namespace Volo.Blogging.MongoDB namespace Volo.Blogging.MongoDB
{ {
[ConnectionStringName(BloggingConsts.ConnectionStringName)] [ConnectionStringName(BloggingDbProperties.ConnectionStringName)]
public interface IBloggingMongoDbContext : IAbpMongoDbContext public interface IBloggingMongoDbContext : IAbpMongoDbContext
{ {
IMongoCollection<BlogUser> Users { get; } IMongoCollection<BlogUser> Users { get; }

5
modules/blogging/src/Volo.Blogging.Web/BloggingWebModule.cs

@ -26,6 +26,11 @@ namespace Volo.Blogging
{ {
options.AddAssemblyResource(typeof(BloggingResource), typeof(BloggingWebModule).Assembly); options.AddAssemblyResource(typeof(BloggingResource), typeof(BloggingWebModule).Assembly);
}); });
PreConfigure<IMvcBuilder>(mvcBuilder =>
{
mvcBuilder.AddApplicationPartIfNotExists(typeof(BloggingWebModule).Assembly);
});
} }
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)

5
modules/docs/src/Volo.Docs.Admin.Web/DocsAdminWebModule.cs

@ -26,6 +26,11 @@ namespace Volo.Docs.Admin
{ {
options.AddAssemblyResource(typeof(DocsResource), typeof(DocsAdminWebModule).Assembly); options.AddAssemblyResource(typeof(DocsResource), typeof(DocsAdminWebModule).Assembly);
}); });
PreConfigure<IMvcBuilder>(mvcBuilder =>
{
mvcBuilder.AddApplicationPartIfNotExists(typeof(DocsAdminWebModule).Assembly);
});
} }
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)

11
modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsConsts.cs

@ -1,11 +0,0 @@
namespace Volo.Docs
{
public static class DocsConsts
{
public const string DefaultDbTablePrefix = "Docs";
public const string DefaultDbSchema = null;
public const string ConnectionStringName = "Docs";
}
}

11
modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDbProperties.cs

@ -0,0 +1,11 @@
namespace Volo.Docs
{
public static class DocsDbProperties
{
public static string DbTablePrefix { get; set; } = "Docs";
public static string DbSchema { get; set; } = null;
public const string ConnectionStringName = "Docs";
}
}

11
modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContext.cs

@ -5,12 +5,9 @@ using Volo.Docs.Projects;
namespace Volo.Docs.EntityFrameworkCore namespace Volo.Docs.EntityFrameworkCore
{ {
[ConnectionStringName(DocsConsts.ConnectionStringName)] [ConnectionStringName(DocsDbProperties.ConnectionStringName)]
public class DocsDbContext: AbpDbContext<DocsDbContext>, IDocsDbContext public class DocsDbContext: AbpDbContext<DocsDbContext>, IDocsDbContext
{ {
public static string TablePrefix { get; set; } = DocsConsts.DefaultDbTablePrefix;
public static string Schema { get; set; } = DocsConsts.DefaultDbSchema;
public DbSet<Project> Projects { get; set; } public DbSet<Project> Projects { get; set; }
public DocsDbContext(DbContextOptions<DocsDbContext> options) public DocsDbContext(DbContextOptions<DocsDbContext> options)
@ -23,11 +20,7 @@ namespace Volo.Docs.EntityFrameworkCore
{ {
base.OnModelCreating(builder); base.OnModelCreating(builder);
builder.ConfigureDocs(options => builder.ConfigureDocs();
{
options.TablePrefix = TablePrefix;
options.Schema = Schema;
});
} }
} }
} }

6
modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContextModelBuilderExtensions.cs

@ -15,7 +15,11 @@ namespace Volo.Docs.EntityFrameworkCore
{ {
Check.NotNull(builder, nameof(builder)); Check.NotNull(builder, nameof(builder));
var options = new DocsModelBuilderConfigurationOptions(); var options = new DocsModelBuilderConfigurationOptions(
DocsDbProperties.DbTablePrefix,
DocsDbProperties.DbSchema
);
optionsAction?.Invoke(options); optionsAction?.Invoke(options);
builder.Entity<Project>(b => builder.Entity<Project>(b =>

9
modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsModelBuilderConfigurationOptions.cs

@ -1,11 +1,14 @@
using Volo.Abp.EntityFrameworkCore.Modeling; using JetBrains.Annotations;
using Volo.Abp.EntityFrameworkCore.Modeling;
namespace Volo.Docs.EntityFrameworkCore namespace Volo.Docs.EntityFrameworkCore
{ {
public class DocsModelBuilderConfigurationOptions : ModelBuilderConfigurationOptions public class DocsModelBuilderConfigurationOptions : ModelBuilderConfigurationOptions
{ {
public DocsModelBuilderConfigurationOptions() public DocsModelBuilderConfigurationOptions(
: base(DocsConsts.DefaultDbTablePrefix, DocsConsts.DefaultDbSchema) [NotNull] string tablePrefix,
[CanBeNull] string schema)
: base(tablePrefix, schema)
{ {
} }
} }

2
modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/IDocsDbContext.cs

@ -5,7 +5,7 @@ using Volo.Docs.Projects;
namespace Volo.Docs.EntityFrameworkCore namespace Volo.Docs.EntityFrameworkCore
{ {
[ConnectionStringName(DocsConsts.ConnectionStringName)] [ConnectionStringName(DocsDbProperties.ConnectionStringName)]
public interface IDocsDbContext : IEfCoreDbContext public interface IDocsDbContext : IEfCoreDbContext
{ {
DbSet<Project> Projects { get; set; } DbSet<Project> Projects { get; set; }

9
modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/MongoDB/DocsMongoDbContext.cs

@ -5,21 +5,16 @@ using Volo.Abp.MongoDB;
namespace Volo.Docs.MongoDB namespace Volo.Docs.MongoDB
{ {
[ConnectionStringName(DocsConsts.ConnectionStringName)] [ConnectionStringName(DocsDbProperties.ConnectionStringName)]
public class DocsMongoDbContext : AbpMongoDbContext, IDocsMongoDbContext public class DocsMongoDbContext : AbpMongoDbContext, IDocsMongoDbContext
{ {
public static string CollectionPrefix { get; set; } = DocsConsts.DefaultDbTablePrefix;
public IMongoCollection<Project> Projects => Collection<Project>(); public IMongoCollection<Project> Projects => Collection<Project>();
protected override void CreateModel(IMongoModelBuilder modelBuilder) protected override void CreateModel(IMongoModelBuilder modelBuilder)
{ {
base.CreateModel(modelBuilder); base.CreateModel(modelBuilder);
modelBuilder.ConfigureDocs(options => modelBuilder.ConfigureDocs();
{
options.CollectionPrefix = CollectionPrefix;
});
} }
} }
} }

7
modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/MongoDB/DocsMongoDbContextExtensions.cs

@ -1,5 +1,4 @@
 using System;
using System;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.MongoDB; using Volo.Abp.MongoDB;
using Volo.Docs.Projects; using Volo.Docs.Projects;
@ -14,7 +13,9 @@ namespace Volo.Docs.MongoDB
{ {
Check.NotNull(builder, nameof(builder)); Check.NotNull(builder, nameof(builder));
var options = new DocsMongoModelBuilderConfigurationOptions(); var options = new DocsMongoModelBuilderConfigurationOptions(
DocsDbProperties.DbTablePrefix
);
optionsAction?.Invoke(options); optionsAction?.Invoke(options);

10
modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/MongoDB/DocsMongoModelBuilderConfigurationOptions.cs

@ -1,15 +1,13 @@
using System; using JetBrains.Annotations;
using System.Collections.Generic;
using System.Text;
using JetBrains.Annotations;
using Volo.Abp.MongoDB; using Volo.Abp.MongoDB;
namespace Volo.Docs.MongoDB namespace Volo.Docs.MongoDB
{ {
public class DocsMongoModelBuilderConfigurationOptions : MongoModelBuilderConfigurationOptions public class DocsMongoModelBuilderConfigurationOptions : MongoModelBuilderConfigurationOptions
{ {
public DocsMongoModelBuilderConfigurationOptions([NotNull] string tablePrefix = DocsConsts.DefaultDbTablePrefix) public DocsMongoModelBuilderConfigurationOptions(
: base(tablePrefix) [NotNull] string collectionPrefix)
: base(collectionPrefix)
{ {
} }
} }

2
modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/MongoDB/IDocsMongoDbContext.cs

@ -5,7 +5,7 @@ using Volo.Docs.Projects;
namespace Volo.Docs.MongoDB namespace Volo.Docs.MongoDB
{ {
[ConnectionStringName(DocsConsts.ConnectionStringName)] [ConnectionStringName(DocsDbProperties.ConnectionStringName)]
public interface IDocsMongoDbContext : IAbpMongoDbContext public interface IDocsMongoDbContext : IAbpMongoDbContext
{ {

5
modules/docs/src/Volo.Docs.Web/DocsWebModule.cs

@ -28,6 +28,11 @@ namespace Volo.Docs
{ {
options.AddAssemblyResource(typeof(DocsResource), typeof(DocsWebModule).Assembly); options.AddAssemblyResource(typeof(DocsResource), typeof(DocsWebModule).Assembly);
}); });
PreConfigure<IMvcBuilder>(mvcBuilder =>
{
mvcBuilder.AddApplicationPartIfNotExists(typeof(DocsWebModule).Assembly);
});
} }
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)

2
modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo.Abp.FeatureManagement.Domain.Shared.csproj

@ -8,8 +8,8 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<content Remove="Volo\Abp\FeatureManagement\Localization\Domain\*.json" />
<EmbeddedResource Include="Volo\Abp\FeatureManagement\Localization\Domain\*.json" /> <EmbeddedResource Include="Volo\Abp\FeatureManagement\Localization\Domain\*.json" />
<content Remove="Volo\Abp\FeatureManagement\Localization\Domain\*.json" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

2
modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/AbpFeatureManagementDomainSharedModule.cs

@ -24,7 +24,7 @@ namespace Volo.Abp.FeatureManagement
.Add<AbpFeatureManagementResource>("en") .Add<AbpFeatureManagementResource>("en")
.AddBaseTypes( .AddBaseTypes(
typeof(AbpValidationResource) typeof(AbpValidationResource)
).AddVirtualJson("Volo/Abp/FeatureManagement/Localization/Resources/Domain"); ).AddVirtualJson("Volo/Abp/FeatureManagement/Localization/Domain");
}); });
} }
} }

2
modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en.json

@ -2,6 +2,6 @@
"culture": "en", "culture": "en",
"texts": { "texts": {
"Features": "Features", "Features": "Features",
"NoFeatureFoundMessage": "There is't any available feature." "NoFeatureFoundMessage": "There isn't any available feature."
} }
} }

5
modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo.Abp.FeatureManagement.Domain.csproj

@ -13,11 +13,6 @@
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Caching\Volo.Abp.Caching.csproj" /> <ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Caching\Volo.Abp.Caching.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Volo\Abp\FeatureManagement\Localization\Domain\*.json" />
<Content Remove="Volo\Abp\FeatureManagement\Localization\Domain\*.json" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Volo.Abp.FeatureManagement.Domain.Shared\Volo.Abp.FeatureManagement.Domain.Shared.csproj" /> <ProjectReference Include="..\Volo.Abp.FeatureManagement.Domain.Shared\Volo.Abp.FeatureManagement.Domain.Shared.csproj" />
</ItemGroup> </ItemGroup>

12
modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/AbpFeatureManagementDomainModule.cs

@ -27,18 +27,6 @@ namespace Volo.Abp.FeatureManagement
options.ProviderPolicies[TenantFeatureValueProvider.ProviderName] = "AbpTenantManagement.Tenants.ManageFeatures"; options.ProviderPolicies[TenantFeatureValueProvider.ProviderName] = "AbpTenantManagement.Tenants.ManageFeatures";
}); });
Configure<VirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpFeatureManagementDomainModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Get<AbpFeatureManagementResource>()
.AddVirtualJson("/Volo/Abp/FeatureManagement/Localization/Domain");
});
Configure<ExceptionLocalizationOptions>(options => Configure<ExceptionLocalizationOptions>(options =>
{ {
options.MapCodeNamespace("AbpFeatureManagement", typeof(AbpFeatureManagementResource)); options.MapCodeNamespace("AbpFeatureManagement", typeof(AbpFeatureManagementResource));

11
modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManagementConsts.cs

@ -1,11 +0,0 @@
namespace Volo.Abp.FeatureManagement
{
public static class FeatureManagementConsts
{
public const string DefaultDbTablePrefix = "Abp";
public const string DefaultDbSchema = null;
public const string ConnectionStringName = "AbpFeatureManagement";
}
}

13
modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManagementDbProperties.cs

@ -0,0 +1,13 @@
using Volo.Abp.Data;
namespace Volo.Abp.FeatureManagement
{
public static class FeatureManagementDbProperties
{
public static string DbTablePrefix { get; set; } = AbpCommonDbProperties.DbTablePrefix;
public static string DbSchema { get; set; } = AbpCommonDbProperties.DbSchema;
public const string ConnectionStringName = "AbpFeatureManagement";
}
}

6
modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/cs.json

@ -1,6 +0,0 @@
{
"culture": "cs",
"texts": {
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save