Browse Source

Merge remote-tracking branch 'abpframework/dev' into docs

pull/4366/head
liangshiwei 6 years ago
parent
commit
3975ca253a
  1. 5
      apiSpec/Microsoft_AspNetCore_Routing_AbpEndpointRouterOptions.md
  2. 357
      docs/en/Unit-Of-Work.md
  3. 3
      docs/en/docs-nav.json
  4. 6
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationConfigurationDto.cs
  5. 31
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundleConfigurationContext.cs
  6. 5
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperResourceService.cs
  7. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Resources/IWebRequestResources.cs
  8. 28
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Resources/WebRequestResources.cs
  9. 14
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/AbpAspNetCoreMvcUiPackagesModule.cs
  10. 21
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/BootstrapDatepicker/BootstrapDatepickerScriptContributor.cs
  11. 15
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/JQueryValidation/JQueryValidationScriptContributor.cs
  12. 1
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Select2/Select2ScriptContributor.cs
  13. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Pages/Shared/Components/AbpPageSearchBox/Default.cshtml
  14. 30
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/dom-event-handlers.js
  15. 5
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs
  16. 3
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs
  17. 70
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateRemoveMongodbCollectionFixtureStep.cs
  18. 55
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateSwitchEntityFrameworkCoreToMongoDbStep.cs
  19. 6
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
  20. 323
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/EfCoreAsyncQueryableProvider.cs
  21. 5
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Uow/EntityFrameworkCore/EfCoreDatabaseApi.cs
  22. 14
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Uow/EntityFrameworkCore/EfCoreTransactionApi.cs
  23. 23
      framework/src/Volo.Abp.Http.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionDynamicHttpClientProxyExtensions.cs
  24. 23
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientModule.cs
  25. 6
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientOptions.cs
  26. 15
      framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs
  27. 10
      framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelHttpRequestMessageOptions.cs
  28. 6
      framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpLocalizationOptions.cs
  29. 58
      framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpLocalizationOptionsExtensions.cs
  30. 329
      framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider.cs
  31. 5
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs
  32. 1
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfoExtensions.cs
  33. 523
      framework/src/Volo.Abp.Threading/Volo/Abp/Linq/AsyncQueryableExecuter.cs
  34. 395
      framework/src/Volo.Abp.Threading/Volo/Abp/Linq/IAsyncQueryableExecuter.cs
  35. 394
      framework/src/Volo.Abp.Threading/Volo/Abp/Linq/IAsyncQueryableProvider.cs
  36. 6
      framework/src/Volo.Abp.Uow/Volo/Abp/Uow/AbpUnitOfWorkDefaultOptions.cs
  37. 11
      framework/src/Volo.Abp.Uow/Volo/Abp/Uow/AbpUnitOfWorkOptions.cs
  38. 7
      framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IAbpUnitOfWorkOptions.cs
  39. 2
      framework/src/Volo.Abp.Uow/Volo/Abp/Uow/ISupportsSavingChanges.cs
  40. 2
      framework/src/Volo.Abp.Uow/Volo/Abp/Uow/ITransactionApi.cs
  41. 10
      framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWork.cs
  42. 6
      framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkAttribute.cs
  43. 8
      framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkManagerExtensions.cs
  44. 62
      modules/blogging/Volo.Blogging.sln
  45. 15
      modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs
  46. 2
      modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.csproj
  47. 3
      modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/FodyWeavers.xml
  48. 30
      modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/FodyWeavers.xsd
  49. 31
      modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo.Blogging.Admin.Application.Contracts.csproj
  50. 25
      modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/BloggingAdminApplicationContractsModule.cs
  51. 25
      modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/BloggingAdminPermissionDefinitionProvider.cs
  52. 23
      modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/BloggingAdminPermissions.cs
  53. 7
      modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/BloggingAdminRemoteServiceConsts.cs
  54. 14
      modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Blogs/BlogDto.cs
  55. 4
      modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Blogs/CreateBlogDto.cs
  56. 20
      modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Blogs/IBlogManagementAppService.cs
  57. 4
      modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Blogs/UpdateBlogDto.cs
  58. 11
      modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Localization/Resources/Blogging/Admin/ApplicationContracts/cs.json
  59. 11
      modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Localization/Resources/Blogging/Admin/ApplicationContracts/de.json
  60. 11
      modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Localization/Resources/Blogging/Admin/ApplicationContracts/en.json
  61. 11
      modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Localization/Resources/Blogging/Admin/ApplicationContracts/nl.json
  62. 11
      modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Localization/Resources/Blogging/Admin/ApplicationContracts/pl-PL.json
  63. 11
      modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Localization/Resources/Blogging/Admin/ApplicationContracts/pt-BR.json
  64. 11
      modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Localization/Resources/Blogging/Admin/ApplicationContracts/sl.json
  65. 11
      modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Localization/Resources/Blogging/Admin/ApplicationContracts/tr.json
  66. 11
      modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Localization/Resources/Blogging/Admin/ApplicationContracts/vi.json
  67. 11
      modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Localization/Resources/Blogging/Admin/ApplicationContracts/zh-Hans.json
  68. 11
      modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Localization/Resources/Blogging/Admin/ApplicationContracts/zh-Hant.json
  69. 3
      modules/blogging/src/Volo.Blogging.Admin.Application/FodyWeavers.xml
  70. 30
      modules/blogging/src/Volo.Blogging.Admin.Application/FodyWeavers.xsd
  71. 20
      modules/blogging/src/Volo.Blogging.Admin.Application/Volo.Blogging.Admin.Application.csproj
  72. 14
      modules/blogging/src/Volo.Blogging.Admin.Application/Volo/Blogging/Admin/BloggingAdminAppServiceBase.cs
  73. 14
      modules/blogging/src/Volo.Blogging.Admin.Application/Volo/Blogging/Admin/BloggingAdminApplicationAutoMapperProfile.cs
  74. 27
      modules/blogging/src/Volo.Blogging.Admin.Application/Volo/Blogging/Admin/BloggingAdminApplicationModule.cs
  75. 64
      modules/blogging/src/Volo.Blogging.Admin.Application/Volo/Blogging/Admin/Blogs/BlogManagementAppService.cs
  76. 3
      modules/blogging/src/Volo.Blogging.Admin.HttpApi.Client/FodyWeavers.xml
  77. 30
      modules/blogging/src/Volo.Blogging.Admin.HttpApi.Client/FodyWeavers.xsd
  78. 18
      modules/blogging/src/Volo.Blogging.Admin.HttpApi.Client/Volo.Blogging.Admin.HttpApi.Client.csproj
  79. 19
      modules/blogging/src/Volo.Blogging.Admin.HttpApi.Client/Volo/Blogging/Admin/BloggingAdminHttpApiClientModule.cs
  80. 3
      modules/blogging/src/Volo.Blogging.Admin.HttpApi/FodyWeavers.xml
  81. 30
      modules/blogging/src/Volo.Blogging.Admin.HttpApi/FodyWeavers.xsd
  82. 18
      modules/blogging/src/Volo.Blogging.Admin.HttpApi/Volo.Blogging.Admin.HttpApi.csproj
  83. 56
      modules/blogging/src/Volo.Blogging.Admin.HttpApi/Volo/Blogging/Admin/BlogManagementController.cs
  84. 33
      modules/blogging/src/Volo.Blogging.Admin.HttpApi/Volo/Blogging/Admin/BloggingAdminHttpApiModule.cs
  85. 16
      modules/blogging/src/Volo.Blogging.Admin.Web/AbpBloggingAdminWebAutoMapperProfile.cs
  86. 17
      modules/blogging/src/Volo.Blogging.Admin.Web/BloggingAdminMenuContributor.cs
  87. 53
      modules/blogging/src/Volo.Blogging.Admin.Web/BloggingAdminWebModule.cs
  88. 3
      modules/blogging/src/Volo.Blogging.Admin.Web/FodyWeavers.xml
  89. 30
      modules/blogging/src/Volo.Blogging.Admin.Web/FodyWeavers.xsd
  90. 6
      modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/Create.cshtml
  91. 19
      modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/Create.cshtml.cs
  92. 7
      modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/Edit.cshtml
  93. 22
      modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/Edit.cshtml.cs
  94. 16
      modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/Index.cshtml
  95. 10
      modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/Index.cshtml.cs
  96. 0
      modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/create.js
  97. 0
      modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/edit.js
  98. 14
      modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/index.js
  99. 17
      modules/blogging/src/Volo.Blogging.Admin.Web/Pages/BloggingAdminPage.cs
  100. 12
      modules/blogging/src/Volo.Blogging.Admin.Web/Pages/BloggingAdminPageModel.cs

5
apiSpec/Microsoft_AspNetCore_Routing_AbpEndpointRouterOptions.md

@ -0,0 +1,5 @@
uid: Microsoft.AspNetCore.Routing.AbpEndpointRouterOptions
summary: '*Summary test'
*Information Test*

357
docs/en/Unit-Of-Work.md

@ -1,3 +1,356 @@
## Unit of Work
# Unit of Work
ABP Framework's Unit Of Work (UOW) implementation provides an abstraction and control on a **database connection and transaction** scope in an application.
Once a new UOW started, it creates an **ambient scope** that is participated by **all the database operations** performed in the current scope and considered as a **single transaction boundary**. The operations are **committed** (on success) or **rolled back** (on exception) all together.
ABP's UOW system is;
* **Works conventional**, so most of the times you don't deal with UOW at all.
* **Database provider independent**.
* **Web independent**, that means you can create unit of work scopes in any type of applications beside web applications/services.
## Conventions
The following method types are considered as a unit of work:
* ASP.NET Core MVC **Controller Actions**.
* ASP.NET Core Razor **Page Handlers**.
* **Application service** methods.
* **Repository methods**.
A UOW automatically begins for these methods **except** if there is already a **surrounding (ambient)** UOW in action. Examples;
* If you call a [repository](Repositories.md) method and there is no UOW started yet, it automatically **begins a new transactional UOW** that involves all the operations done in the repository method and **commits the transaction** if the repository method **doesn't throw any exception.** The repository method doesn't know about UOW or transaction at all. It just works on a regular database objects (`DbContext` for [EF Core](Entity-Framework-Core.md), for example) and the UOW is handled by the ABP Framework.
* If you call an [application service](Application-Services.md) method, the same UOW system works just as explained above. If the application service method uses some repositories, the repositories **don't begin a new UOW**, but **participates to the current unit of work** started by the ABP Framework for the application service method.
* The same is true for an ASP.NET Core controller action. If the operation has started with a controller action, then the **UOW scope is the controller action's method body**.
All of these are automatically handled by the ABP Framework.
### Database Transaction Behavior
While the section above explains the UOW as it is database transaction, actually a UOW doesn't have to be transactional. By default;
* **HTTP GET** requests don't start a transactional UOW. They still starts a UOW, but **doesn't create a database transaction**.
* All other HTTP request types start a UOW with a database transaction, if database level transactions are supported by the underlying database provider.
This is because an HTTP GET request doesn't (and shouldn't) make any change in the database. You can change this behavior using the options explained below.
## Default Options
`AbpUnitOfWorkDefaultOptions` is used to configure the default options for the unit of work system. Configure the options in the `ConfigureServices` method of your [module](Module-Development-Basics.md).
**Example: Completely disable the database transactions**
````csharp
Configure<AbpUnitOfWorkDefaultOptions>(options =>
{
options.TransactionBehavior = UnitOfWorkTransactionBehavior.Disabled;
});
````
### Option Properties
* `TransactionBehavior` (`enum`: `UnitOfWorkTransactionBehavior`). A global point to configure the transaction behavior. Default value is `Auto` and work as explained in the "*Database Transaction Behavior*" section above. You can enable (even for HTTP GET requests) or disable transactions with this option.
* `TimeOut` (`TimeSpan?`): Used to set the timeout value for UOWs. **Default value is `null`** and uses to the default of the underlying database provider.
* `IsolationLevel` (`IsolationLevel?`): Used to set the [isolation level](https://docs.microsoft.com/en-us/dotnet/api/system.data.isolationlevel) of the database transaction, if the UOW is transactional.
## Controlling the Unit Of Work
In some cases, you may want to change the conventional transaction scope, create inner scopes or fine control the transaction behavior. The following sections cover these possibilities.
### IUnitOfWorkEnabled Interface
This is an easy way to enable UOW for a class (or a hierarchy of classes) that is not unit of work by the conventions explained above.
**Example: Implement `IUnitOfWorkEnabled` for an arbitrary service**
````csharp
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Uow;
namespace AbpDemo
{
public class MyService : ITransientDependency, IUnitOfWorkEnabled
{
public virtual async Task FooAsync()
{
//this is a method with a UOW scope
}
}
}
````
Then `MyService` (and any class derived from it) methods will be UOW.
However, there are **some rules should be followed** in order to make it working;
* If you are **not injecting** the service over an interface (like `IMyService`), then the methods of the service must be `virtual` (otherwise, [dynamic proxy / interception](Dynamic-Proxying-Interceptors.md) system can not work).
* Only `async` methods (methods returning a `Task` or `Task<T>`) are intercepted. So, sync methods can not start a UOW.
> Notice that if `FooAsync` is called inside a UOW scope, then it already participates to the UOW without needing to the `IUnitOfWorkEnabled` or any other configuration.
### UnitOfWorkAttribute
`UnitOfWork` attribute provides much more possibility like enabling or disabling UOW and controlling the transaction behavior.
`UnitOfWork` attribute can be used for a **class** or a **method** level.
**Example: Enable UOW for a specific method of a class**
````csharp
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Uow;
namespace AbpDemo
{
public class MyService : ITransientDependency
{
[UnitOfWork]
public virtual async Task FooAsync()
{
//this is a method with a UOW scope
}
public virtual async Task BarAsync()
{
//this is a method without UOW
}
}
}
````
**Example: Enable UOW for all the methods of a class**
````csharp
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Uow;
namespace AbpDemo
{
[UnitOfWork]
public class MyService : ITransientDependency
{
public virtual async Task FooAsync()
{
//this is a method with a UOW scope
}
public virtual async Task BarAsync()
{
//this is a method with a UOW scope
}
}
}
````
Again, the **same rules** are valid here:
* If you are **not injecting** the service over an interface (like `IMyService`), then the methods of the service must be `virtual` (otherwise, [dynamic proxy / interception](Dynamic-Proxying-Interceptors.md) system can not work).
* Only `async` methods (methods returning a `Task` or `Task<T>`) are intercepted. So, sync methods can not start a UOW.
#### UnitOfWorkAttribute Properties
* `IsTransactional` (`bool?`): Used to set whether the UOW should be transactional or not. **Default value is `null`**. if you leave it `null`, it is determined automatically based on the conventions and the configuration.
* `TimeOut` (`int?`): Used to set the timeout value for this UOW. **Default value is `null`** and fallbacks to the default configured value.
* `IsolationLevel` (`IsolationLevel?`): Used to set the [isolation level](https://docs.microsoft.com/en-us/dotnet/api/system.data.isolationlevel) of the database transaction, if the UOW is transactional. If not set, uses the default configured value.
* `IsDisabled` (`bool`): Used to disable the UOW for the current method/class.
> If a method is called in an ambient UOW scope, then the `UnitOfWork` attribute is ignored and the method participates to the surrounding transaction in any way.
**Example: Disable UOW for a controller action**
````csharp
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Uow;
namespace AbpDemo.Web
{
public class MyController : AbpController
{
[UnitOfWork(IsDisabled = true)]
public virtual async Task FooAsync()
{
//...
}
}
}
````
## IUnitOfWorkManager
`IUnitOfWorkManager` is the main service that is used to control the unit of work system. The following sections explains how to directly work with this service (while most of the times you won't need).
### Begin a New Unit Of Work
`IUnitOfWorkManager.Begin` method is used to create a new UOW scope.
**Example: Create a new non-transactional UOW scope**
````csharp
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Uow;
namespace AbpDemo
{
public class MyService : ITransientDependency
{
private readonly IUnitOfWorkManager _unitOfWorkManager;
public MyService(IUnitOfWorkManager unitOfWorkManager)
{
_unitOfWorkManager = unitOfWorkManager;
}
public virtual async Task FooAsync()
{
using (var uow = _unitOfWorkManager.Begin(
requiresNew: true, isTransactional: false
))
{
//...
await uow.CompleteAsync();
}
}
}
}
````
`Begin` method gets the following optional parameters:
* `requiresNew` (`bool`): Set `true` to ignore the surrounding unit of work and start a new UOW with the provided options. **Default value is `false`. If it is `false` and there is a surrounding UOW, `Begin` method doesn't actually begin a new UOW, but silently participates to the existing UOW.**
* `isTransactional` (`bool`). Default value is `false`.
* `isolationLevel` (`IsolationLevel?`): Used to set the [isolation level](https://docs.microsoft.com/en-us/dotnet/api/system.data.isolationlevel) of the database transaction, if the UOW is transactional. If not set, uses the default configured value.
* `TimeOut` (`TimeSpan?`): Used to set the timeout value for this UOW. **Default value is `null`** and fallbacks to the default configured value.
### The Current Unit Of Work
UOW is ambient, as explained before. If you need to access to the current unit of work, you can use the `IUnitOfWorkManager.Current` property.
**Example: Get the current UOW**
````csharp
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Uow;
namespace AbpDemo
{
public class MyProductService : ITransientDependency
{
private readonly IUnitOfWorkManager _unitOfWorkManager;
public MyProductService(IUnitOfWorkManager unitOfWorkManager)
{
_unitOfWorkManager = unitOfWorkManager;
}
public async Task FooAsync()
{
var uow = _unitOfWorkManager.Current;
//...
}
}
}
````
`Current` property returns a `IUnitOfWork` object.
> **Current Unit Of Work can be `null`** if there is no surrounding unit of work. It won't be `null` if your class is a conventional UOW class, you manually made it UOW or it was called inside a UOW scope, as explained before.
#### SaveChangesAsync
`IUnitOfWork.SaveChangesAsync()` method can be needed to save all the changes until now to the database. If you are using EF Core, it behaves exactly same. If the current UOW is transactional, even saved changes can be rolled back on an error (for the supporting database providers).
**Example: Save changes after inserting an entity to get its auto-increment id**
````csharp
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
namespace AbpDemo
{
public class CategoryAppService : ApplicationService, ICategoryAppService
{
private readonly IRepository<Category, int> _categoryRepository;
public CategoryAppService(IRepository<Category, int> categoryRepository)
{
_categoryRepository = categoryRepository;
}
public async Task<int> CreateAsync(string name)
{
var category = new Category {Name = name};
await _categoryRepository.InsertAsync(category);
//Saving changes to be able to get the auto increment id
await UnitOfWorkManager.Current.SaveChangesAsync();
return category.Id;
}
}
}
````
This example uses auto-increment `int` primary key for the `Category` [entity](Entities.md). Auto-increment PKs require to save the entity to the database to get the id of the new entity.
This example is an [application service](Application-Services.md) derived from the base `ApplicationService` class, which already has the `IUnitOfWorkManager` service injected as the `UnitOfWorkManager` property. So, no need to inject it manually.
Since getting the current UOW is pretty common, there is also a `CurrentUnitOfWork` property as a shortcut to the `UnitOfWorkManager.Current`. So, the example above can be changed to use it:
````csharp
await CurrentUnitOfWork.SaveChangesAsync();
````
##### Alternative to the SaveChanges()
Since saving changes after inserting, updating or deleting an entity can be frequently needed, corresponding [repository](Repositories.md) methods has an optional `autoSave` parameter. So, the `CreateAsync` method above could be re-written as shown below:
````csharp
public async Task<int> CreateAsync(string name)
{
var category = new Category {Name = name};
await _categoryRepository.InsertAsync(category, autoSave: true);
return category.Id;
}
````
If your intent is just to save the changes after creating/updating/deleting an entity, it is suggested to use the `autoSave` option instead of manually using the `CurrentUnitOfWork.SaveChangesAsync()`.
> **Note-1**: All changes are automatically saved when a unit of work ends without any error. So, don't call `SaveChangesAsync()` unless you really need it.
>
> **Note-2**: If you use `Guid` as the primary key, you never need to save changes on insert to just get the generated id, because `Guid` keys are set in the application and are immediately available once you create a new entity.
#### Other IUnitOfWork Properties/Methods
* `OnCompleted` method gets a callback action which is called when the unit of work successfully completed (where you can be sure that all changes are saved).
* `Failed` and `Disposed` events can be used to be notified if the UOW fails or when it is disposed.
* `Complete` and `Rollback` methods are used to complete (commit) or roll backs the current UOW, which are normally used internally by the ABP Framework but can be used if you manually start a transaction using the `IUnitOfWorkManager.Begin` method.
* `Options` can be used to get options that was used while starting the UOW.
* `Items` dictionary can be used to store and get arbitrary objects inside the same unit of work, which can be a point to implement custom logics.
## ASP.NET Core Integration
Unit of work system is fully integrated to the ASP.NET Core. It properly works when you use ASP.NET Core MVC Controllers or Razor Pages. It defines action filters and page filters for the UOW system.
> You typically do nothing to configure the UOW when you use ASP.NET Core.
### Unit Of Work Middleware
`AbpUnitOfWorkMiddleware` is a middleware that can enable UOW in the ASP.NET Core request pipeline. This might be needed if you need to enlarge the UOW scope to cover some other middleware(s).
**Example:**
````csharp
app.UseUnitOfWork();
app.UseConfiguredEndpoints();
````
TODO

3
docs/en/docs-nav.json

@ -285,7 +285,8 @@
"path": "Data-Transfer-Objects.md"
},
{
"text": "Unit Of Work"
"text": "Unit Of Work",
"path": "Unit-Of-Work.md"
}
]
}

6
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationConfigurationDto.cs

@ -16,10 +16,14 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
public string DefaultResourceName { get; set; }
public Dictionary<string, List<NameValue>> LanguagesMap { get; set; }
public Dictionary<string, List<NameValue>> LanguageFilesMap { get; set; }
public ApplicationLocalizationConfigurationDto()
{
Values = new Dictionary<string, Dictionary<string, string>>();
Languages = new List<LanguageInfo>();
}
}
}
}

31
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundleConfigurationContext.cs

@ -1,6 +1,9 @@
using System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Options;
using Volo.Abp.Localization;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling
{
@ -8,8 +11,6 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling
{
public List<string> Files { get; }
public IServiceProvider ServiceProvider { get; }
public IFileProvider FileProvider { get; }
public BundleConfigurationContext(IServiceProvider serviceProvider, IFileProvider fileProvider)
@ -18,5 +19,29 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling
ServiceProvider = serviceProvider;
FileProvider = fileProvider;
}
public IServiceProvider ServiceProvider { get; }
private readonly object _serviceProviderLock = new object();
private TRef LazyGetRequiredService<TRef>(Type serviceType, ref TRef reference)
{
if (reference == null)
{
lock (_serviceProviderLock)
{
if (reference == null)
{
reference = (TRef)ServiceProvider.GetRequiredService(serviceType);
}
}
}
return reference;
}
private IOptions<AbpLocalizationOptions> _abpLocalizationOptions;
public AbpLocalizationOptions LocalizationOptions =>
LazyGetRequiredService(typeof(IOptions<AbpLocalizationOptions>), ref _abpLocalizationOptions).Value;
}
}
}

5
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperResourceService.cs

@ -73,7 +73,10 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
throw new AbpException($"Could not find the bundle file '{bundleFile}' from {nameof(IWebContentFileProvider)}");
}
AddHtmlTag(viewContext, context, output, bundleFile + "?_v=" + file.LastModified.UtcTicks);
if (file.Length > 0)
{
AddHtmlTag(viewContext, context, output, bundleFile + "?_v=" + file.LastModified.UtcTicks);
}
}
stopwatch.Stop();

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Resources/IWebRequestResources.cs

@ -4,6 +4,6 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Resources
{
public interface IWebRequestResources
{
List<string> TryAdd(IEnumerable<string> resources);
List<string> TryAdd(List<string> resources);
}
}

28
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Resources/WebRequestResources.cs

@ -1,23 +1,35 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Http;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Mvc.UI.Resources
{
public class WebRequestResources : IWebRequestResources, IScopedDependency
{
protected List<string> Resources { get; }
protected Dictionary<string, List<string>> Resources { get; }
public WebRequestResources()
protected IHttpContextAccessor HttpContextAccessor{ get; }
public WebRequestResources(IHttpContextAccessor httpContextAccessor)
{
Resources = new List<string>();
HttpContextAccessor = httpContextAccessor;
Resources = new Dictionary<string, List<string>>();
}
public List<string> TryAdd(IEnumerable<string> resources)
public List<string> TryAdd(List<string> resources)
{
var resourceToBeAdded = resources.Except(Resources).ToList();
Resources.AddRange(resourceToBeAdded);
return resourceToBeAdded;
var path = HttpContextAccessor.HttpContext?.Request?.Path ?? "";
if (Resources.TryGetValue(path, out var res))
{
var resourceToBeAdded = resources.Except(res).ToList();
res.AddRange(resourceToBeAdded);
return resourceToBeAdded;
}
Resources.Add(path, resources);
return resources;
}
}
}
}

14
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/AbpAspNetCoreMvcUiPackagesModule.cs

@ -1,4 +1,6 @@
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.BootstrapDatepicker;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
namespace Volo.Abp.AspNetCore.Mvc.UI.Packages
@ -6,6 +8,18 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages
[DependsOn(typeof(AbpAspNetCoreMvcUiBundlingModule))]
public class AbpAspNetCoreMvcUiPackagesModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpLocalizationOptions>(options =>
{
options.AddLanguagesMapOrUpdate(BootstrapDatepickerScriptContributor.PackageName,
new NameValue("zh-Hans", "zh-CN"),
new NameValue("zh-Hant", "zh-TW"));
options.AddLanguageFilesMapOrUpdate(BootstrapDatepickerScriptContributor.PackageName,
new NameValue("zh-Hans", "zh-CN"),
new NameValue("zh-Hant", "zh-TW"));
});
}
}
}

21
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/BootstrapDatepicker/BootstrapDatepickerScriptContributor.cs

@ -1,7 +1,8 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Globalization;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.JQuery;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.BootstrapDatepicker
@ -9,11 +10,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.BootstrapDatepicker
[DependsOn(typeof(JQueryScriptContributor))]
public class BootstrapDatepickerScriptContributor : BundleContributor
{
public static readonly Dictionary<string, string> CultureMap = new Dictionary<string, string>
{
{"zh-Hans", "zh-CN"}
};
public const string PackageName = "bootstrap-datepicker";
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.AddIfNotContains("/libs/bootstrap-datepicker/bootstrap-datepicker.min.js");
@ -26,12 +24,13 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.BootstrapDatepicker
? "en"
: CultureInfo.CurrentUICulture.Name;
TryAddCultureFile(context, MapCultureName(cultureName));
TryAddCultureFile(context, cultureName);
}
protected virtual bool TryAddCultureFile(BundleConfigurationContext context, string cultureName)
{
var filePath = $"/libs/bootstrap-datepicker/locales/bootstrap-datepicker.{cultureName}.min.js";
var fileName = context.LocalizationOptions.GetLanguageFilesMap(PackageName, cultureName);
var filePath = $"/libs/bootstrap-datepicker/locales/bootstrap-datepicker.{fileName}.min.js";
if (!context.FileProvider.GetFileInfo(filePath).Exists)
{
@ -41,11 +40,5 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.BootstrapDatepicker
context.Files.AddIfNotContains(filePath);
return true;
}
protected virtual string MapCultureName(string cultureName)
{
return CultureMap.GetOrDefault(cultureName) ??
cultureName;
}
}
}

15
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/JQueryValidation/JQueryValidationScriptContributor.cs

@ -2,6 +2,7 @@
using System.Globalization;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.JQuery;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.JQueryValidation
@ -11,6 +12,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.JQueryValidation
{
public const string DefaultLocalizationFolder = "/libs/jquery-validation/localization/";
public const string PackageName = "jquery-validation";
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.AddIfNotContains("/libs/jquery-validation/jquery.validate.js");
@ -25,7 +28,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.JQueryValidation
var cultureName = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName.Replace('-', '_');
if (TryAddCultureFile(context, MapCultureName(cultureName)))
var fileName = context.LocalizationOptions.GetLanguageFilesMap(PackageName, cultureName);
if (TryAddCultureFile(context, fileName))
{
return;
}
@ -35,7 +39,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.JQueryValidation
return;
}
TryAddCultureFile(context, MapCultureName(cultureName.Substring(0, cultureName.IndexOf('_'))));
fileName = context.LocalizationOptions.GetLanguageFilesMap(PackageName,
cultureName.Substring(0, cultureName.IndexOf('_')));
TryAddCultureFile(context, fileName);
}
protected virtual bool TryAddCultureFile(BundleConfigurationContext context, string cultureName)
@ -51,10 +57,5 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.JQueryValidation
context.Files.AddIfNotContains(filePath);
return true;
}
protected virtual string MapCultureName(string cultureName)
{
return cultureName;
}
}
}

1
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Select2/Select2ScriptContributor.cs

@ -12,7 +12,6 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.Select2
{
//TODO: Add select2.full.min.js or localize!
context.Files.AddIfNotContains("/libs/select2/js/select2.min.js");
context.Files.AddIfNotContains("/libs/select2/js/select2-bootstrap-modal-patch.js");
}
}
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Pages/Shared/Components/AbpPageSearchBox/Default.cshtml

@ -6,7 +6,7 @@
<input class="form-control page-search-filter-text" placeholder="@L["Search"].Value">
<div class="input-group-append">
<abp-button button-type="Primary" type="submit">
<i class="fa fa-search" aria-hidden="true"></i>
<i class="fa fa-search" aria-hidden="true" style="margin-left: 10%; margin-top:50%;" ></i>
</abp-button>
</div>
</div>

30
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/dom-event-handlers.js

@ -1,4 +1,4 @@
(function ($) {
(function ($) {
abp.dom = abp.dom || {};
@ -73,25 +73,12 @@
abp.libs = abp.libs = abp.libs || {};
abp.libs.bootstrapDatepicker = {
languageMap: {
'zh-Hans': 'zh-CN'
},
mapLanguageName: function (name) {
return abp.libs.bootstrapDatepicker.languageMap[abp.localization.currentCulture.name] || name;
},
isLanguageMapped: function (name) {
return abp.libs.bootstrapDatepicker.languageMap[abp.localization.currentCulture.name] !== undefined;
},
getCurrentLanguageConfig: function () {
var mappedName = abp.libs.bootstrapDatepicker.mapLanguageName(abp.localization.currentCulture.name);
return $.fn.datepicker.dates[mappedName];
},
packageName: "bootstrap-datepicker",
normalizeLanguageConfig: function () {
var languageConfig = abp.libs.bootstrapDatepicker.getCurrentLanguageConfig();
if (languageConfig) {
if (!languageConfig.format || abp.libs.bootstrapDatepicker.isLanguageMapped(abp.localization.currentCulture.name)) {
languageConfig.format = abp.localization.currentCulture.dateTimeFormat.shortDatePattern.toLowerCase();
}
var language = abp.localization.getLanguagesMap(this.packageName);
var languageConfig = $.fn.datepicker.dates[language];
if (languageConfig && (!languageConfig.format || language !== abp.localization.currentCulture.name)) {
languageConfig.format = abp.localization.currentCulture.dateTimeFormat.shortDatePattern.toLowerCase();
}
},
getFormattedValue: function (isoFormattedValue) {
@ -108,7 +95,7 @@
return {
todayBtn: "linked",
autoclose: true,
language: abp.libs.bootstrapDatepicker.mapLanguageName(abp.localization.currentCulture.cultureName)
language: abp.localization.getLanguagesMap(this.packageName)
};
}
};
@ -132,7 +119,6 @@
abp.dom.initializers.initializeToolTips(args.$el.findWithSelf('[data-toggle="tooltip"]'));
abp.dom.initializers.initializePopovers(args.$el.findWithSelf('[data-toggle="popover"]'));
abp.dom.initializers.initializeTimeAgos(args.$el.findWithSelf('.timeago'));
abp.dom.initializers.initializeDatepickers(args.$el);
abp.dom.initializers.initializeForms(args.$el.findWithSelf('form'), true);
abp.dom.initializers.initializeScript(args.$el);
});
@ -156,4 +142,4 @@
$('[data-auto-focus="true"]').first().findWithSelf('input,select').focus();
});
})(jQuery);
})(jQuery);

5
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs

@ -171,6 +171,9 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
);
}
localizationConfig.LanguagesMap = _localizationOptions.LanguagesMap;
localizationConfig.LanguageFilesMap = _localizationOptions.LanguageFilesMap;
return localizationConfig;
}
@ -267,4 +270,4 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
};
}
}
}
}

3
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs

@ -47,6 +47,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App
if (context.BuildArgs.DatabaseProvider != DatabaseProvider.MongoDb)
{
steps.Add(new AppTemplateRemoveMongodbCollectionFixtureStep());
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.MongoDB"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.MongoDB.Tests", projectFolderPath: "/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests"));
}
@ -167,4 +168,4 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App
}
}
}
}
}

70
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateRemoveMongodbCollectionFixtureStep.cs

@ -0,0 +1,70 @@
using System.Collections.Generic;
using System.Linq;
using Volo.Abp.Cli.ProjectBuilding.Building;
namespace Volo.Abp.Cli.ProjectBuilding.Templates.App
{
public class AppTemplateRemoveMongodbCollectionFixtureStep : ProjectBuildPipelineStep
{
public override void Execute(ProjectBuildContext context)
{
//MyCompanyName.MyProjectName.Application.Tests
RemoveFile(context, "/aspnet-core/test/MyCompanyName.MyProjectName.Application.Tests/MyProjectNameApplicationCollection.cs");
RemoveKeyword(context,
"/aspnet-core/test/MyCompanyName.MyProjectName.Application.Tests/Samples/SampleAppServiceTests.cs",
"[Collection(MyProjectNameTestConsts.CollectionDefinitionName)]");
//MyCompanyName.MyProjectName.Domain.Tests
RemoveFile(context, "/aspnet-core/test/MyCompanyName.MyProjectName.Domain.Tests/MyProjectNameDomainCollection.cs");
RemoveKeyword(context,
"/aspnet-core/test/MyCompanyName.MyProjectName.Domain.Tests/Samples/SampleDomainTests.cs",
"[Collection(MyProjectNameTestConsts.CollectionDefinitionName)]");
//MyCompanyName.MyProjectName.EntityFrameworkCore.Tests
RemoveFile(context, "/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/EntityFrameworkCore/MyProjectNameEntityFrameworkCoreCollection.cs");
RemoveFile(context, "/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/EntityFrameworkCore/MyProjectNameEntityFrameworkCoreCollectionFixtureBase.cs");
RemoveFile(context, "/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/EntityFrameworkCore/MyProjectNameEntityFrameworkCoreFixture.cs");
RemoveKeyword(context,
"/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs",
"[Collection(MyProjectNameTestConsts.CollectionDefinitionName)]");
//MyCompanyName.MyProjectName.Web.Tests
RemoveFile(context, "/aspnet-core/test/MyCompanyName.MyProjectName.Web.Tests/MyProjectNameWebCollection.cs");
RemoveKeyword(context,
"/aspnet-core/test/MyCompanyName.MyProjectName.Web.Tests/Pages/Index_Tests.cs",
"[Collection(MyProjectNameTestConsts.CollectionDefinitionName)]");
//MyCompanyName.MyProjectName.TestBase
RemoveFile(context, "/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyProjectNameTestConsts.cs");
}
private static void RemoveFile(ProjectBuildContext context, string targetModuleFilePath)
{
var file = context.Files.FirstOrDefault(x => x.Name == targetModuleFilePath);
if (file != null)
{
context.Files.Remove(file);
}
}
private static void RemoveKeyword(ProjectBuildContext context, string targetModuleFilePath, string keyword)
{
var file = context.GetFile(targetModuleFilePath);
file.NormalizeLineEndings();
var lines = file.GetLines();
var newLines = new List<string>();
for (var i = 0; i < lines.Length; i++)
{
if (!lines[i].Contains(keyword))
{
newLines.Add(lines[i]);
}
}
file.SetLines(newLines);
}
}
}

55
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateSwitchEntityFrameworkCoreToMongoDbStep.cs

@ -16,7 +16,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App
"MongoDB"
);
ChangeModuleDependency(
ChangeNamespaceAndKeyword(
context,
"/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs",
"MyCompanyName.MyProjectName.EntityFrameworkCore",
@ -39,7 +39,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App
"MongoDB"
);
ChangeModuleDependency(
ChangeNamespaceAndKeyword(
context,
"/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs",
"MyCompanyName.MyProjectName.EntityFrameworkCore",
@ -62,7 +62,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App
"MongoDB"
);
ChangeModuleDependency(
ChangeNamespaceAndKeyword(
context,
"/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs",
"MyCompanyName.MyProjectName.EntityFrameworkCore",
@ -85,7 +85,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App
"MongoDB"
);
ChangeModuleDependency(
ChangeNamespaceAndKeyword(
context,
"/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs",
"MyCompanyName.MyProjectName.EntityFrameworkCore",
@ -108,7 +108,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App
"MongoDB"
);
ChangeModuleDependency(
ChangeNamespaceAndKeyword(
context,
"/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyProjectNameDbMigratorModule.cs",
"MyCompanyName.MyProjectName.EntityFrameworkCore",
@ -131,7 +131,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App
"MongoDB.Tests"
);
ChangeModuleDependency(
ChangeNamespaceAndKeyword(
context,
"/aspnet-core/test/MyCompanyName.MyProjectName.Domain.Tests/MyProjectNameDomainTestModule.cs",
"MyCompanyName.MyProjectName.EntityFrameworkCore",
@ -139,6 +139,37 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App
"MyProjectNameEntityFrameworkCoreTestModule",
"MyProjectNameMongoDbTestModule"
);
ChangeNamespaceAndKeyword(
context,
"/aspnet-core/test/MyCompanyName.MyProjectName.Domain.Tests/MyProjectNameDomainCollection.cs",
"MyCompanyName.MyProjectName.EntityFrameworkCore",
"MyCompanyName.MyProjectName.MongoDB",
"MyProjectNameEntityFrameworkCoreCollectionFixtureBase",
"MyProjectNameMongoDbCollectionFixtureBase"
);
//MyCompanyName.MyProjectName.Application.Tests
ChangeNamespaceAndKeyword(
context,
"/aspnet-core/test/MyCompanyName.MyProjectName.Application.Tests/MyProjectNameApplicationCollection.cs",
"MyCompanyName.MyProjectName.EntityFrameworkCore",
"MyCompanyName.MyProjectName.MongoDB",
"MyProjectNameEntityFrameworkCoreCollectionFixtureBase",
"MyProjectNameMongoDbCollectionFixtureBase"
);
//MyCompanyName.MyProjectName.Web.Tests
ChangeNamespaceAndKeyword(
context,
"/aspnet-core/test/MyCompanyName.MyProjectName.Web.Tests/MyProjectNameWebCollection.cs",
"MyCompanyName.MyProjectName.EntityFrameworkCore",
"MyCompanyName.MyProjectName.MongoDB",
"MyProjectNameEntityFrameworkCoreCollectionFixtureBase",
"MyProjectNameMongoDbCollectionFixtureBase"
);
}
private void ChangeProjectReference(
@ -165,13 +196,13 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App
throw new ApplicationException($"Could not find the '{oldReference}' reference in the project '{targetProjectFilePath}'!");
}
private void ChangeModuleDependency(
private void ChangeNamespaceAndKeyword(
ProjectBuildContext context,
string targetModuleFilePath,
string oldNamespace,
string newNamespace,
string oldModuleName,
string newModuleName)
string oldKeyword,
string newKeyword)
{
var file = context.GetFile(targetModuleFilePath);
@ -185,9 +216,9 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App
{
lines[i] = $"using {newNamespace};";
}
else if (lines[i].Contains(oldModuleName))
else if (lines[i].Contains(oldKeyword))
{
lines[i] = lines[i].Replace(oldModuleName, newModuleName);
lines[i] = lines[i].Replace(oldKeyword, newKeyword);
}
}
@ -216,4 +247,4 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App
throw new ApplicationException("Could not find the 'Default' connection string in appsettings.json file!");
}
}
}
}

6
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs

@ -118,7 +118,7 @@ namespace Volo.Abp.EntityFrameworkCore
modelBuilder.SetDatabaseProvider(provider.Value);
}
}
protected virtual EfCoreDatabaseProvider? GetDatabaseProviderOrNull(ModelBuilder modelBuilder)
{
switch (Database.ProviderName)
@ -187,7 +187,7 @@ namespace Volo.Abp.EntityFrameworkCore
Database.IsRelational() &&
!Database.GetCommandTimeout().HasValue)
{
Database.SetCommandTimeout(initializationContext.UnitOfWork.Options.Timeout.Value.TotalSeconds.To<int>());
Database.SetCommandTimeout(TimeSpan.FromMilliseconds(initializationContext.UnitOfWork.Options.Timeout.Value));
}
ChangeTracker.CascadeDeleteTiming = CascadeTiming.OnSaveChanges;
@ -627,4 +627,4 @@ namespace Volo.Abp.EntityFrameworkCore
}
}
}
}
}

323
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/EfCoreAsyncQueryableProvider.cs

@ -1,5 +1,7 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
@ -16,19 +18,332 @@ namespace Volo.Abp.EntityFrameworkCore
return queryable.Provider is EntityQueryProvider;
}
public Task<bool> ContainsAsync<T>(IQueryable<T> queryable, T item, CancellationToken cancellationToken = default)
{
return queryable.ContainsAsync(item, cancellationToken);
}
public Task<bool> AnyAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
return queryable.AnyAsync(predicate, cancellationToken);
}
public Task<bool> AllAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
return queryable.AllAsync(predicate, cancellationToken);
}
public Task<int> CountAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.CountAsync(cancellationToken);
}
public Task<List<T>> ToListAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
public Task<int> CountAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
return queryable.ToListAsync(cancellationToken);
return queryable.CountAsync(predicate, cancellationToken);
}
public Task<long> LongCountAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.LongCountAsync(cancellationToken);
}
public Task<long> LongCountAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
return queryable.LongCountAsync(predicate, cancellationToken);
}
public Task<T> FirstAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.FirstAsync(cancellationToken);
}
public Task<T> FirstAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
return queryable.FirstAsync(predicate, cancellationToken);
}
public Task<T> FirstOrDefaultAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.FirstOrDefaultAsync(cancellationToken);
}
public Task<T> FirstOrDefaultAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default)
{
return queryable.FirstOrDefaultAsync(predicate, cancellationToken);
}
public Task<T> LastAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.LastAsync(cancellationToken);
}
public Task<T> LastAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
return queryable.LastAsync(predicate, cancellationToken);
}
public Task<T> LastOrDefaultAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.LastOrDefaultAsync(cancellationToken);
}
public Task<T> LastOrDefaultAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default)
{
return queryable.LastOrDefaultAsync(predicate, cancellationToken);
}
public Task<T> SingleAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.SingleAsync(cancellationToken);
}
public Task<T> SingleAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
return queryable.SingleAsync(predicate, cancellationToken);
}
public Task<T> SingleOrDefaultAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.SingleOrDefaultAsync(cancellationToken);
}
public Task<T> SingleOrDefaultAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default)
{
return queryable.SingleOrDefaultAsync(predicate, cancellationToken);
}
public Task<T> MinAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.MinAsync(cancellationToken);
}
public Task<TResult> MinAsync<T, TResult>(IQueryable<T> queryable, Expression<Func<T, TResult>> selector, CancellationToken cancellationToken = default)
{
return queryable.MinAsync(selector, cancellationToken);
}
public Task<T> MaxAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.MaxAsync(cancellationToken);
}
public Task<TResult> MaxAsync<T, TResult>(IQueryable<T> queryable, Expression<Func<T, TResult>> selector, CancellationToken cancellationToken = default)
{
return queryable.MaxAsync(selector, cancellationToken);
}
public Task<decimal> SumAsync(IQueryable<decimal> queryable, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(cancellationToken);
}
public Task<decimal?> SumAsync(IQueryable<decimal?> queryable, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(cancellationToken);
}
public Task<decimal> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, decimal>> selector, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(selector, cancellationToken);
}
public Task<decimal?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, decimal?>> selector, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(selector, cancellationToken);
}
public Task<int> SumAsync(IQueryable<int> queryable, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(cancellationToken);
}
public Task<int?> SumAsync(IQueryable<int?> queryable, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(cancellationToken);
}
public Task<int> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, int>> selector, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(selector, cancellationToken);
}
public Task<int?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, int?>> selector, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(selector, cancellationToken);
}
public Task<long> SumAsync(IQueryable<long> queryable, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(cancellationToken);
}
public Task<long?> SumAsync(IQueryable<long?> queryable, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(cancellationToken);
}
public Task<long> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, long>> selector, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(selector, cancellationToken);
}
public Task<long?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, long?>> selector, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(selector, cancellationToken);
}
public Task<double> SumAsync(IQueryable<double> queryable, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(cancellationToken);
}
public Task<double?> SumAsync(IQueryable<double?> queryable, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(cancellationToken);
}
public Task<double> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, double>> selector, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(selector, cancellationToken);
}
public Task<double?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, double?>> selector, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(selector, cancellationToken);
}
public Task<float> SumAsync(IQueryable<float> queryable, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(cancellationToken);
}
public Task<float?> SumAsync(IQueryable<float?> queryable, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(cancellationToken);
}
public Task<float> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, float>> selector, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(selector, cancellationToken);
}
public Task<float?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, float?>> selector, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(selector, cancellationToken);
}
public Task<decimal> AverageAsync(IQueryable<decimal> queryable, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(cancellationToken);
}
public Task<decimal?> AverageAsync(IQueryable<decimal?> queryable, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(cancellationToken);
}
public Task<decimal> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, decimal>> selector, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(selector, cancellationToken);
}
public Task<decimal?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, decimal?>> selector, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(selector, cancellationToken);
}
public Task<double> AverageAsync(IQueryable<int> queryable, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(cancellationToken);
}
public Task<double?> AverageAsync(IQueryable<int?> queryable, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(cancellationToken);
}
public Task<double> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, int>> selector, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(selector, cancellationToken);
}
public Task<double?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, int?>> selector, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(selector, cancellationToken);
}
public Task<double> AverageAsync(IQueryable<long> queryable, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(cancellationToken);
}
public Task<double?> AverageAsync(IQueryable<long?> queryable, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(cancellationToken);
}
public Task<double> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, long>> selector, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(selector, cancellationToken);
}
public Task<double?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, long?>> selector, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(selector, cancellationToken);
}
public Task<double> AverageAsync(IQueryable<double> queryable, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(cancellationToken);
}
public Task<double?> AverageAsync(IQueryable<double?> queryable, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(cancellationToken);
}
public Task<double> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, double>> selector, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(selector, cancellationToken);
}
public Task<double?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, double?>> selector, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(selector, cancellationToken);
}
public Task<float> AverageAsync(IQueryable<float> queryable, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(cancellationToken);
}
public Task<float?> AverageAsync(IQueryable<float?> queryable, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(cancellationToken);
}
public Task<float> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, float>> selector, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(selector, cancellationToken);
}
public Task<float?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, float?>> selector, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(selector, cancellationToken);
}
public Task<List<T>> ToListAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.ToListAsync(cancellationToken);
}
public Task<T[]> ToArrayAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.ToArrayAsync(cancellationToken);
}
}
}
}

5
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Uow/EntityFrameworkCore/EfCoreDatabaseApi.cs

@ -18,10 +18,5 @@ namespace Volo.Abp.Uow.EntityFrameworkCore
{
return DbContext.SaveChangesAsync(cancellationToken);
}
public void SaveChanges()
{
DbContext.SaveChanges();
}
}
}

14
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Uow/EntityFrameworkCore/EfCoreTransactionApi.cs

@ -21,7 +21,13 @@ namespace Volo.Abp.Uow.EntityFrameworkCore
AttendedDbContexts = new List<IEfCoreDbContext>();
}
public void Commit()
public Task CommitAsync()
{
Commit();
return Task.CompletedTask;
}
protected void Commit()
{
DbContextTransaction.Commit();
@ -36,12 +42,6 @@ namespace Volo.Abp.Uow.EntityFrameworkCore
}
}
public Task CommitAsync()
{
Commit();
return Task.CompletedTask;
}
public void Dispose()
{
DbContextTransaction.Dispose();

23
framework/src/Volo.Abp.Http.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionDynamicHttpClientProxyExtensions.cs

@ -45,11 +45,8 @@ namespace Microsoft.Extensions.DependencyInjection
AddHttpClientFactoryAndPolicy(services, remoteServiceConfigurationName, configureHttpClientBuilder);
//TODO: Make a configuration option and add remoteServiceName inside it!
//TODO: Add option to change type filter
var serviceTypes = assembly.GetTypes().Where(t =>
t.IsInterface && t.IsPublic && typeof(IRemoteService).IsAssignableFrom(t)
);
var serviceTypes = assembly.GetTypes().Where(IsSuitableForDynamicClientProxying);
foreach (var serviceType in serviceTypes)
{
@ -155,7 +152,7 @@ namespace Microsoft.Extensions.DependencyInjection
services.AddTransient(interceptorType);
var interceptorAdapterType = typeof(AbpAsyncDeterminationInterceptor<>).MakeGenericType(interceptorType);
var validationInterceptorAdapterType =
typeof(AbpAsyncDeterminationInterceptor<>).MakeGenericType(typeof(ValidationInterceptor));
@ -191,5 +188,21 @@ namespace Microsoft.Extensions.DependencyInjection
return services;
}
/// <summary>
/// Checks wether the type is suitable to use with the dynamic proxying.
/// Currently the type is checked statically against some fixed conditions.
/// </summary>
/// <param name="type">Type to check</param>
/// <returns>True, if the type is suitable for dynamic proxying. Otherwise false.</returns>
static bool IsSuitableForDynamicClientProxying(Type type)
{
//TODO: Add option to change type filter
return type.IsInterface
&& type.IsPublic
&& !type.IsGenericType
&& typeof(IRemoteService).IsAssignableFrom(type);
}
}
}

23
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientModule.cs

@ -1,4 +1,6 @@
using Microsoft.Extensions.DependencyInjection;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Http;
using Volo.Abp.Castle;
using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
@ -21,5 +23,24 @@ namespace Volo.Abp.Http.Client
var configuration = context.Services.GetConfiguration();
Configure<AbpRemoteServiceOptions>(configuration);
}
public override void PostConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpHttpClientOptions>(options =>
{
if (options.HttpClientActions.Any())
{
var httpClientNames = options.HttpClientProxies.Select(x => x.Value.RemoteServiceName);
foreach (var httpClientName in httpClientNames)
{
foreach (var httpClientAction in options.HttpClientActions)
{
context.Services.Configure<HttpClientFactoryOptions>(httpClientName,
x => x.HttpClientActions.Add(httpClientAction.Invoke(httpClientName)));
}
}
}
});
}
}
}

6
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientOptions.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using Volo.Abp.Http.Client.DynamicProxying;
namespace Volo.Abp.Http.Client
@ -8,9 +9,12 @@ namespace Volo.Abp.Http.Client
{
public Dictionary<Type, DynamicHttpClientProxyConfig> HttpClientProxies { get; set; }
public List<Func<string, Action<HttpClient>>> HttpClientActions { get; }
public AbpHttpClientOptions()
{
HttpClientProxies = new Dictionary<Type, DynamicHttpClientProxyConfig>();
HttpClientActions = new List<Func<string, Action<HttpClient>>>();
}
}
}
}

15
framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs

@ -25,17 +25,20 @@ namespace Volo.Abp.IdentityModel
protected ICancellationTokenProvider CancellationTokenProvider { get; }
protected IHttpClientFactory HttpClientFactory { get; }
protected ICurrentTenant CurrentTenant { get; }
protected IdentityModelHttpRequestMessageOptions IdentityModelHttpRequestMessageOptions { get; }
public IdentityModelAuthenticationService(
IOptions<AbpIdentityClientOptions> options,
ICancellationTokenProvider cancellationTokenProvider,
IHttpClientFactory httpClientFactory,
ICurrentTenant currentTenant)
ICurrentTenant currentTenant,
IOptions<IdentityModelHttpRequestMessageOptions> identityModelHttpRequestMessageOptions)
{
ClientOptions = options.Value;
CancellationTokenProvider = cancellationTokenProvider;
HttpClientFactory = httpClientFactory;
CurrentTenant = currentTenant;
IdentityModelHttpRequestMessageOptions = identityModelHttpRequestMessageOptions.Value;
Logger = NullLogger<IdentityModelAuthenticationService>.Instance;
}
@ -74,7 +77,7 @@ namespace Volo.Abp.IdentityModel
}
var tokenResponse = await GetTokenResponse(discoveryResponse, configuration);
if (tokenResponse.IsError)
{
if (tokenResponse.ErrorDescription != null)
@ -112,14 +115,16 @@ namespace Volo.Abp.IdentityModel
{
using (var httpClient = HttpClientFactory.CreateClient(HttpClientName))
{
return await httpClient.GetDiscoveryDocumentAsync(new DiscoveryDocumentRequest
var request = new DiscoveryDocumentRequest
{
Address = configuration.Authority,
Policy =
{
RequireHttps = configuration.RequireHttps
}
});
};
IdentityModelHttpRequestMessageOptions.ConfigureHttpRequestMessage(request);
return await httpClient.GetDiscoveryDocumentAsync(request);
}
}
@ -160,6 +165,7 @@ namespace Volo.Abp.IdentityModel
UserName = configuration.UserName,
Password = configuration.UserPassword
};
IdentityModelHttpRequestMessageOptions.ConfigureHttpRequestMessage(request);
AddParametersToRequestAsync(configuration, request);
@ -177,6 +183,7 @@ namespace Volo.Abp.IdentityModel
ClientId = configuration.ClientId,
ClientSecret = configuration.ClientSecret
};
IdentityModelHttpRequestMessageOptions.ConfigureHttpRequestMessage(request);
AddParametersToRequestAsync(configuration, request);

10
framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelHttpRequestMessageOptions.cs

@ -0,0 +1,10 @@
using System;
using System.Net.Http;
namespace Volo.Abp.IdentityModel
{
public class IdentityModelHttpRequestMessageOptions
{
public Action<HttpRequestMessage> ConfigureHttpRequestMessage { get; set; }
}
}

6
framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpLocalizationOptions.cs

@ -17,11 +17,17 @@ namespace Volo.Abp.Localization
public List<LanguageInfo> Languages { get; }
public Dictionary<string, List<NameValue>> LanguagesMap { get; }
public Dictionary<string, List<NameValue>> LanguageFilesMap { get; }
public AbpLocalizationOptions()
{
Resources = new LocalizationResourceDictionary();
GlobalContributors = new TypeList<ILocalizationResourceContributor>();
Languages = new List<LanguageInfo>();
LanguagesMap = new Dictionary<string, List<NameValue>>();
LanguageFilesMap = new Dictionary<string, List<NameValue>>();
}
}
}

58
framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpLocalizationOptionsExtensions.cs

@ -0,0 +1,58 @@
using System.Collections.Generic;
using System.Linq;
namespace Volo.Abp.Localization
{
public static class AbpLocalizationOptionsExtensions
{
public static AbpLocalizationOptions AddLanguagesMapOrUpdate(this AbpLocalizationOptions localizationOptions,
string packageName, params NameValue[] maps)
{
foreach (var map in maps)
{
AddOrUpdate(localizationOptions.LanguagesMap, packageName, map);
}
return localizationOptions;
}
public static string GetLanguagesMap(this AbpLocalizationOptions localizationOptions, string packageName,
string language)
{
return localizationOptions.LanguagesMap.TryGetValue(packageName, out var maps)
? maps.FirstOrDefault(x => x.Name == language)?.Value ?? language
: language;
}
public static AbpLocalizationOptions AddLanguageFilesMapOrUpdate(this AbpLocalizationOptions localizationOptions,
string packageName, params NameValue[] maps)
{
foreach (var map in maps)
{
AddOrUpdate(localizationOptions.LanguageFilesMap, packageName, map);
}
return localizationOptions;
}
public static string GetLanguageFilesMap(this AbpLocalizationOptions localizationOptions, string packageName,
string language)
{
return localizationOptions.LanguageFilesMap.TryGetValue(packageName, out var maps)
? maps.FirstOrDefault(x => x.Name == language)?.Value ?? language
: language;
}
private static void AddOrUpdate(IDictionary<string, List<NameValue>> maps, string packageName, NameValue value)
{
if (maps.TryGetValue(packageName, out var existMaps))
{
existMaps.GetOrAdd(x => x.Name == value.Name, () => value).Value = value.Value;
}
else
{
maps.Add(packageName, new List<NameValue> {value});
}
}
}
}

329
framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
@ -17,19 +18,337 @@ namespace Volo.Abp.MongoDB
return queryable.Provider.GetType().Namespace?.StartsWith("MongoDB") ?? false;
}
protected IMongoQueryable<T> GetMongoQueryable<T>(IQueryable<T> queryable)
{
return (IMongoQueryable<T>) queryable;
}
public Task<bool> ContainsAsync<T>(IQueryable<T> queryable, T item, CancellationToken cancellationToken = default)
{
return Task.FromResult(GetMongoQueryable(queryable).Contains(item));
}
public Task<bool> AnyAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).AnyAsync(predicate, cancellationToken);
}
public Task<bool> AllAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
return Task.FromResult(GetMongoQueryable(queryable).All(predicate));
}
public Task<int> CountAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return ((IMongoQueryable<T>) queryable).CountAsync(cancellationToken);
return GetMongoQueryable(queryable).CountAsync(cancellationToken);
}
public Task<List<T>> ToListAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
public Task<int> CountAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).CountAsync(predicate, cancellationToken);
}
public Task<long> LongCountAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).LongCountAsync(cancellationToken);
}
public Task<long> LongCountAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).LongCountAsync(predicate, cancellationToken);
}
public Task<T> FirstAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).FirstAsync(cancellationToken);
}
public Task<T> FirstAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
return ((IMongoQueryable<T>) queryable).ToListAsync(cancellationToken);
return GetMongoQueryable(queryable).FirstAsync(predicate, cancellationToken);
}
public Task<T> FirstOrDefaultAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return ((IMongoQueryable<T>) queryable).FirstOrDefaultAsync(cancellationToken);
return GetMongoQueryable(queryable).FirstOrDefaultAsync(cancellationToken);
}
public Task<T> FirstOrDefaultAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).FirstOrDefaultAsync(predicate, cancellationToken);
}
public Task<T> LastAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return Task.FromResult(GetMongoQueryable(queryable).Last());
}
public Task<T> LastAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
return Task.FromResult(GetMongoQueryable(queryable).Last(predicate));
}
public Task<T> LastOrDefaultAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return Task.FromResult(GetMongoQueryable(queryable).LastOrDefault());
}
public Task<T> LastOrDefaultAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default)
{
return Task.FromResult(GetMongoQueryable(queryable).LastOrDefault(predicate));
}
public Task<T> SingleAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).SingleAsync(cancellationToken);
}
public Task<T> SingleAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).SingleAsync(predicate, cancellationToken);
}
public Task<T> SingleOrDefaultAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).SingleOrDefaultAsync(cancellationToken);
}
public Task<T> SingleOrDefaultAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).SingleOrDefaultAsync(predicate, cancellationToken);
}
public Task<T> MinAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).MinAsync(cancellationToken);
}
public Task<TResult> MinAsync<T, TResult>(IQueryable<T> queryable, Expression<Func<T, TResult>> selector, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).MinAsync(selector, cancellationToken);
}
public Task<T> MaxAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).MaxAsync(cancellationToken);
}
public Task<TResult> MaxAsync<T, TResult>(IQueryable<T> queryable, Expression<Func<T, TResult>> selector, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).MaxAsync(selector, cancellationToken);
}
public Task<decimal> SumAsync(IQueryable<decimal> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).SumAsync(cancellationToken);
}
public Task<decimal?> SumAsync(IQueryable<decimal?> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).SumAsync(cancellationToken);
}
public Task<decimal> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, decimal>> selector, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken);
}
public Task<decimal?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, decimal?>> selector, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken);
}
public Task<int> SumAsync(IQueryable<int> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).SumAsync(cancellationToken);
}
public Task<int?> SumAsync(IQueryable<int?> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).SumAsync(cancellationToken);
}
public Task<int> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, int>> selector, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken);
}
public Task<int?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, int?>> selector, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken);
}
public Task<long> SumAsync(IQueryable<long> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).SumAsync(cancellationToken);
}
public Task<long?> SumAsync(IQueryable<long?> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).SumAsync(cancellationToken);
}
public Task<long> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, long>> selector, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken);
}
public Task<long?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, long?>> selector, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken);
}
public Task<double> SumAsync(IQueryable<double> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).SumAsync(cancellationToken);
}
public Task<double?> SumAsync(IQueryable<double?> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).SumAsync(cancellationToken);
}
public Task<double> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, double>> selector, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken);
}
public Task<double?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, double?>> selector, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken);
}
public Task<float> SumAsync(IQueryable<float> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).SumAsync(cancellationToken);
}
public Task<float?> SumAsync(IQueryable<float?> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).SumAsync(cancellationToken);
}
public Task<float> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, float>> selector, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken);
}
public Task<float?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, float?>> selector, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken);
}
public Task<decimal> AverageAsync(IQueryable<decimal> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).AverageAsync(cancellationToken);
}
public Task<decimal?> AverageAsync(IQueryable<decimal?> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).AverageAsync(cancellationToken);
}
public Task<decimal> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, decimal>> selector, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken);
}
public Task<decimal?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, decimal?>> selector, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken);
}
public Task<double> AverageAsync(IQueryable<int> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).AverageAsync(cancellationToken);
}
public Task<double?> AverageAsync(IQueryable<int?> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).AverageAsync(cancellationToken);
}
public Task<double> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, int>> selector, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken);
}
public Task<double?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, int?>> selector, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken);
}
public Task<double> AverageAsync(IQueryable<long> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).AverageAsync(cancellationToken);
}
public Task<double?> AverageAsync(IQueryable<long?> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).AverageAsync(cancellationToken);
}
public Task<double> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, long>> selector, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken);
}
public Task<double?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, long?>> selector, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken);
}
public Task<double> AverageAsync(IQueryable<double> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).AverageAsync(cancellationToken);
}
public Task<double?> AverageAsync(IQueryable<double?> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).AverageAsync(cancellationToken);
}
public Task<double> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, double>> selector, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken);
}
public Task<double?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, double?>> selector, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken);
}
public Task<float> AverageAsync(IQueryable<float> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).AverageAsync(cancellationToken);
}
public Task<float?> AverageAsync(IQueryable<float?> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).AverageAsync(cancellationToken);
}
public Task<float> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, float>> selector, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken);
}
public Task<float?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, float?>> selector, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken);
}
public Task<List<T>> ToListAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return GetMongoQueryable(queryable).ToListAsync(cancellationToken);
}
public async Task<T[]> ToArrayAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return (await GetMongoQueryable(queryable).ToListAsync(cancellationToken)).ToArray();
}
}
}
}

5
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs

@ -18,10 +18,6 @@ namespace Volo.Abp.ObjectExtending
[NotNull]
public Type Type { get; }
[NotNull]
[Obsolete("Add validation attributes to the Attributes list instead! ValidationAttributes property will be removed in future versions.")]
public List<ValidationAttribute> ValidationAttributes { get; }
[NotNull]
public List<Attribute> Attributes { get; }
@ -71,7 +67,6 @@ namespace Volo.Abp.ObjectExtending
Name = Check.NotNull(name, nameof(name));
Configuration = new Dictionary<object, object>();
ValidationAttributes = new List<ValidationAttribute>();
Attributes = new List<Attribute>();
Validators = new List<Action<ObjectExtensionPropertyValidationContext>>();

1
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfoExtensions.cs

@ -10,7 +10,6 @@ namespace Volo.Abp.ObjectExtending
return propertyInfo
.Attributes
.OfType<ValidationAttribute>()
.Union(propertyInfo.ValidationAttributes)
.ToArray();
}
}

523
framework/src/Volo.Abp.Threading/Volo/Abp/Linq/AsyncQueryableExecuter.cs

@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
@ -15,9 +17,36 @@ namespace Volo.Abp.Linq
Providers = providers;
}
public virtual Task<int> CountAsync<T>(
IQueryable<T> queryable,
CancellationToken cancellationToken = default)
protected virtual IAsyncQueryableProvider FindProvider<T>(IQueryable<T> queryable)
{
return Providers.FirstOrDefault(p => p.CanExecute(queryable));
}
public Task<bool> ContainsAsync<T>(IQueryable<T> queryable, T item, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.ContainsAsync(queryable, item, cancellationToken)
: Task.FromResult(queryable.Contains(item));
}
public Task<bool> AnyAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.AnyAsync(queryable, predicate, cancellationToken)
: Task.FromResult(queryable.Any(predicate));
}
public Task<bool> AllAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.AllAsync(queryable, predicate, cancellationToken)
: Task.FromResult(queryable.All(predicate));
}
public Task<int> CountAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
@ -25,19 +54,47 @@ namespace Volo.Abp.Linq
: Task.FromResult(queryable.Count());
}
public virtual Task<List<T>> ToListAsync<T>(
IQueryable<T> queryable,
CancellationToken cancellationToken = default)
public Task<int> CountAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.ToListAsync(queryable, cancellationToken)
: Task.FromResult(queryable.ToList());
? provider.CountAsync(queryable, predicate, cancellationToken)
: Task.FromResult(queryable.Count(predicate));
}
public virtual Task<T> FirstOrDefaultAsync<T>(
IQueryable<T> queryable,
CancellationToken cancellationToken = default)
public Task<long> LongCountAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.LongCountAsync(queryable, cancellationToken)
: Task.FromResult(queryable.LongCount());
}
public Task<long> LongCountAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.LongCountAsync(queryable, predicate, cancellationToken)
: Task.FromResult(queryable.LongCount(predicate));
}
public Task<T> FirstAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.FirstAsync(queryable, cancellationToken)
: Task.FromResult(queryable.First());
}
public Task<T> FirstAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.FirstAsync(queryable, predicate, cancellationToken)
: Task.FromResult(queryable.First(predicate));
}
public Task<T> FirstOrDefaultAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
@ -45,9 +102,447 @@ namespace Volo.Abp.Linq
: Task.FromResult(queryable.FirstOrDefault());
}
protected virtual IAsyncQueryableProvider FindProvider<T>(IQueryable<T> queryable)
public Task<T> FirstOrDefaultAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default)
{
return Providers.FirstOrDefault(p => p.CanExecute(queryable));
var provider = FindProvider(queryable);
return provider != null
? provider.FirstOrDefaultAsync(queryable, predicate, cancellationToken)
: Task.FromResult(queryable.FirstOrDefault(predicate));
}
public Task<T> LastAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.LastAsync(queryable, cancellationToken)
: Task.FromResult(queryable.Last());
}
public Task<T> LastAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.LastAsync(queryable, predicate, cancellationToken)
: Task.FromResult(queryable.Last(predicate));
}
public Task<T> LastOrDefaultAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.LastOrDefaultAsync(queryable, cancellationToken)
: Task.FromResult(queryable.LastOrDefault());
}
public Task<T> LastOrDefaultAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.LastOrDefaultAsync(queryable, predicate, cancellationToken)
: Task.FromResult(queryable.LastOrDefault(predicate));
}
public Task<T> SingleAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.SingleAsync(queryable, cancellationToken)
: Task.FromResult(queryable.Single());
}
public Task<T> SingleAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.SingleAsync(queryable, predicate, cancellationToken)
: Task.FromResult(queryable.Single(predicate));
}
public Task<T> SingleOrDefaultAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.SingleOrDefaultAsync(queryable, cancellationToken)
: Task.FromResult(queryable.SingleOrDefault());
}
public Task<T> SingleOrDefaultAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.SingleOrDefaultAsync(queryable, predicate, cancellationToken)
: Task.FromResult(queryable.SingleOrDefault(predicate));
}
public Task<T> MinAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.MinAsync(queryable, cancellationToken)
: Task.FromResult(queryable.Min());
}
public Task<TResult> MinAsync<T, TResult>(IQueryable<T> queryable, Expression<Func<T, TResult>> selector, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.MinAsync(queryable, selector, cancellationToken)
: Task.FromResult(queryable.Min(selector));
}
public Task<T> MaxAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.MaxAsync(queryable, cancellationToken)
: Task.FromResult(queryable.Max());
}
public Task<TResult> MaxAsync<T, TResult>(IQueryable<T> queryable, Expression<Func<T, TResult>> selector, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.MaxAsync(queryable, selector, cancellationToken)
: Task.FromResult(queryable.Max(selector));
}
public Task<decimal> SumAsync(IQueryable<decimal> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.SumAsync(queryable, cancellationToken)
: Task.FromResult(queryable.Sum());
}
public Task<decimal?> SumAsync(IQueryable<decimal?> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.SumAsync(queryable, cancellationToken)
: Task.FromResult(queryable.Sum());
}
public Task<decimal> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, decimal>> selector, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.SumAsync(queryable, selector, cancellationToken)
: Task.FromResult(queryable.Sum(selector));
}
public Task<decimal?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, decimal?>> selector, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.SumAsync(queryable, selector, cancellationToken)
: Task.FromResult(queryable.Sum(selector));
}
public Task<int> SumAsync(IQueryable<int> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.SumAsync(queryable, cancellationToken)
: Task.FromResult(queryable.Sum());
}
public Task<int?> SumAsync(IQueryable<int?> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.SumAsync(queryable, cancellationToken)
: Task.FromResult(queryable.Sum());
}
public Task<int> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, int>> selector, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.SumAsync(queryable, selector, cancellationToken)
: Task.FromResult(queryable.Sum(selector));
}
public Task<int?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, int?>> selector, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.SumAsync(queryable, selector, cancellationToken)
: Task.FromResult(queryable.Sum(selector));
}
public Task<long> SumAsync(IQueryable<long> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.SumAsync(queryable, cancellationToken)
: Task.FromResult(queryable.Sum());
}
public Task<long?> SumAsync(IQueryable<long?> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.SumAsync(queryable, cancellationToken)
: Task.FromResult(queryable.Sum());
}
public Task<long> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, long>> selector, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.SumAsync(queryable, selector, cancellationToken)
: Task.FromResult(queryable.Sum(selector));
}
public Task<long?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, long?>> selector, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.SumAsync(queryable, selector, cancellationToken)
: Task.FromResult(queryable.Sum(selector));
}
public Task<double> SumAsync(IQueryable<double> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.SumAsync(queryable, cancellationToken)
: Task.FromResult(queryable.Sum());
}
public Task<double?> SumAsync(IQueryable<double?> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.SumAsync(queryable, cancellationToken)
: Task.FromResult(queryable.Sum());
}
public Task<double> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, double>> selector, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.SumAsync(queryable, selector, cancellationToken)
: Task.FromResult(queryable.Sum(selector));
}
public Task<double?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, double?>> selector, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.SumAsync(queryable, selector, cancellationToken)
: Task.FromResult(queryable.Sum(selector));
}
public Task<float> SumAsync(IQueryable<float> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.SumAsync(queryable, cancellationToken)
: Task.FromResult(queryable.Sum());
}
public Task<float?> SumAsync(IQueryable<float?> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.SumAsync(queryable, cancellationToken)
: Task.FromResult(queryable.Sum());
}
public Task<float> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, float>> selector, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.SumAsync(queryable, selector, cancellationToken)
: Task.FromResult(queryable.Sum(selector));
}
public Task<float?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, float?>> selector, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.SumAsync(queryable, selector, cancellationToken)
: Task.FromResult(queryable.Sum(selector));
}
public Task<decimal> AverageAsync(IQueryable<decimal> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.AverageAsync(queryable, cancellationToken)
: Task.FromResult(queryable.Average());
}
public Task<decimal?> AverageAsync(IQueryable<decimal?> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.AverageAsync(queryable, cancellationToken)
: Task.FromResult(queryable.Average());
}
public Task<decimal> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, decimal>> selector, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.AverageAsync(queryable, selector, cancellationToken)
: Task.FromResult(queryable.Average(selector));
}
public Task<decimal?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, decimal?>> selector, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.AverageAsync(queryable, selector, cancellationToken)
: Task.FromResult(queryable.Average(selector));
}
public Task<double> AverageAsync(IQueryable<int> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.AverageAsync(queryable, cancellationToken)
: Task.FromResult(queryable.Average());
}
public Task<double?> AverageAsync(IQueryable<int?> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.AverageAsync(queryable, cancellationToken)
: Task.FromResult(queryable.Average());
}
public Task<double> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, int>> selector, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.AverageAsync(queryable, selector, cancellationToken)
: Task.FromResult(queryable.Average(selector));
}
public Task<double?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, int?>> selector, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.AverageAsync(queryable, selector, cancellationToken)
: Task.FromResult(queryable.Average(selector));
}
public Task<double> AverageAsync(IQueryable<long> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.AverageAsync(queryable, cancellationToken)
: Task.FromResult(queryable.Average());
}
public Task<double?> AverageAsync(IQueryable<long?> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.AverageAsync(queryable, cancellationToken)
: Task.FromResult(queryable.Average());
}
public Task<double> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, long>> selector, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.AverageAsync(queryable, selector, cancellationToken)
: Task.FromResult(queryable.Average(selector));
}
public Task<double?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, long?>> selector, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.AverageAsync(queryable, selector, cancellationToken)
: Task.FromResult(queryable.Average(selector));
}
public Task<double> AverageAsync(IQueryable<double> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.AverageAsync(queryable, cancellationToken)
: Task.FromResult(queryable.Average());
}
public Task<double?> AverageAsync(IQueryable<double?> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.AverageAsync(queryable, cancellationToken)
: Task.FromResult(queryable.Average());
}
public Task<double> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, double>> selector, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.AverageAsync(queryable, selector, cancellationToken)
: Task.FromResult(queryable.Average(selector));
}
public Task<double?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, double?>> selector, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.AverageAsync(queryable, selector, cancellationToken)
: Task.FromResult(queryable.Average(selector));
}
public Task<float> AverageAsync(IQueryable<float> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.AverageAsync(queryable, cancellationToken)
: Task.FromResult(queryable.Average());
}
public Task<float?> AverageAsync(IQueryable<float?> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.AverageAsync(queryable, cancellationToken)
: Task.FromResult(queryable.Average());
}
public Task<float> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, float>> selector, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.AverageAsync(queryable, selector, cancellationToken)
: Task.FromResult(queryable.Average(selector));
}
public Task<float?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, float?>> selector, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.AverageAsync(queryable, selector, cancellationToken)
: Task.FromResult(queryable.Average(selector));
}
public Task<List<T>> ToListAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.ToListAsync(queryable, cancellationToken)
: Task.FromResult(queryable.ToList());
}
public Task<T[]> ToArrayAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
var provider = FindProvider(queryable);
return provider != null
? provider.ToArrayAsync(queryable, cancellationToken)
: Task.FromResult(queryable.ToArray());
}
}
}
}

395
framework/src/Volo.Abp.Threading/Volo/Abp/Linq/IAsyncQueryableExecuter.cs

@ -1,25 +1,398 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Volo.Abp.Linq
{
public interface IAsyncQueryableExecuter
{
#region Contains
Task<bool> ContainsAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] T item,
CancellationToken cancellationToken = default);
#endregion
#region Any/All
Task<bool> AnyAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default);
Task<bool> AllAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default);
#endregion
#region Count/LongCount
Task<int> CountAsync<T>(
IQueryable<T> queryable,
CancellationToken cancellationToken = default
);
[NotNull] IQueryable<T> queryable,
CancellationToken cancellationToken = default);
Task<int> CountAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default);
Task<long> LongCountAsync<T>(
[NotNull] IQueryable<T> queryable,
CancellationToken cancellationToken = default);
Task<long> LongCountAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default);
#endregion
#region First/FirstOrDefault
Task<T> FirstAsync<T>(
[NotNull] IQueryable<T> queryable,
CancellationToken cancellationToken = default);
Task<T> FirstAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default);
Task<List<T>> ToListAsync<T>(
IQueryable<T> queryable,
CancellationToken cancellationToken = default
);
Task<T> FirstOrDefaultAsync<T>(
IQueryable<T> queryable,
CancellationToken cancellationToken = default
);
[NotNull] IQueryable<T> queryable,
CancellationToken cancellationToken = default);
Task<T> FirstOrDefaultAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default);
#endregion
#region Last/LastOrDefault
Task<T> LastAsync<T>(
[NotNull] IQueryable<T> queryable,
CancellationToken cancellationToken = default);
Task<T> LastAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default);
Task<T> LastOrDefaultAsync<T>(
[NotNull] IQueryable<T> queryable,
CancellationToken cancellationToken = default);
Task<T> LastOrDefaultAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default);
#endregion
#region Single/SingleOrDefault
Task<T> SingleAsync<T>(
[NotNull] IQueryable<T> queryable,
CancellationToken cancellationToken = default);
Task<T> SingleAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default);
Task<T> SingleOrDefaultAsync<T>(
[NotNull] IQueryable<T> queryable,
CancellationToken cancellationToken = default);
Task<T> SingleOrDefaultAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default);
#endregion
#region Min
Task<T> MinAsync<T>(
[NotNull] IQueryable<T> queryable,
CancellationToken cancellationToken = default);
Task<TResult> MinAsync<T, TResult>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, TResult>> selector,
CancellationToken cancellationToken = default);
#endregion
#region Max
Task<T> MaxAsync<T>(
[NotNull] IQueryable<T> queryable,
CancellationToken cancellationToken = default);
Task<TResult> MaxAsync<T, TResult>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, TResult>> selector,
CancellationToken cancellationToken = default);
#endregion
#region Sum
Task<decimal> SumAsync(
[NotNull] IQueryable<decimal> source,
CancellationToken cancellationToken = default);
Task<decimal?> SumAsync(
[NotNull] IQueryable<decimal?> source,
CancellationToken cancellationToken = default);
Task<decimal> SumAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, decimal>> selector,
CancellationToken cancellationToken = default);
Task<decimal?> SumAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, decimal?>> selector,
CancellationToken cancellationToken = default);
Task<int> SumAsync(
[NotNull] IQueryable<int> source,
CancellationToken cancellationToken = default);
Task<int?> SumAsync(
[NotNull] IQueryable<int?> source,
CancellationToken cancellationToken = default);
Task<int> SumAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, int>> selector,
CancellationToken cancellationToken = default);
Task<int?> SumAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, int?>> selector,
CancellationToken cancellationToken = default);
Task<long> SumAsync(
[NotNull] IQueryable<long> source,
CancellationToken cancellationToken = default);
Task<long?> SumAsync(
[NotNull] IQueryable<long?> source,
CancellationToken cancellationToken = default);
Task<long> SumAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, long>> selector,
CancellationToken cancellationToken = default);
Task<long?> SumAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, long?>> selector,
CancellationToken cancellationToken = default);
Task<double> SumAsync(
[NotNull] IQueryable<double> source,
CancellationToken cancellationToken = default);
Task<double?> SumAsync(
[NotNull] IQueryable<double?> source,
CancellationToken cancellationToken = default);
Task<double> SumAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, double>> selector,
CancellationToken cancellationToken = default);
Task<double?> SumAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, double?>> selector,
CancellationToken cancellationToken = default);
Task<float> SumAsync(
[NotNull] IQueryable<float> source,
CancellationToken cancellationToken = default);
Task<float?> SumAsync(
[NotNull] IQueryable<float?> source,
CancellationToken cancellationToken = default);
Task<float> SumAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, float>> selector,
CancellationToken cancellationToken = default);
Task<float?> SumAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, float?>> selector,
CancellationToken cancellationToken = default);
#endregion
#region Average
Task<decimal> AverageAsync(
[NotNull] IQueryable<decimal> source,
CancellationToken cancellationToken = default);
Task<decimal?> AverageAsync(
[NotNull] IQueryable<decimal?> source,
CancellationToken cancellationToken = default);
Task<decimal> AverageAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, decimal>> selector,
CancellationToken cancellationToken = default);
Task<decimal?> AverageAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, decimal?>> selector,
CancellationToken cancellationToken = default);
Task<double> AverageAsync(
[NotNull] IQueryable<int> source,
CancellationToken cancellationToken = default);
Task<double?> AverageAsync(
[NotNull] IQueryable<int?> source,
CancellationToken cancellationToken = default);
Task<double> AverageAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, int>> selector,
CancellationToken cancellationToken = default);
Task<double?> AverageAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, int?>> selector,
CancellationToken cancellationToken = default);
Task<double> AverageAsync(
[NotNull] IQueryable<long> source,
CancellationToken cancellationToken = default);
Task<double?> AverageAsync(
[NotNull] IQueryable<long?> source,
CancellationToken cancellationToken = default);
Task<double> AverageAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, long>> selector,
CancellationToken cancellationToken = default);
Task<double?> AverageAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, long?>> selector,
CancellationToken cancellationToken = default);
Task<double> AverageAsync(
[NotNull] IQueryable<double> source,
CancellationToken cancellationToken = default);
Task<double?> AverageAsync(
[NotNull] IQueryable<double?> source,
CancellationToken cancellationToken = default);
Task<double> AverageAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, double>> selector,
CancellationToken cancellationToken = default);
Task<double?> AverageAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, double?>> selector,
CancellationToken cancellationToken = default);
Task<float> AverageAsync(
[NotNull] IQueryable<float> source,
CancellationToken cancellationToken = default);
Task<float?> AverageAsync(
[NotNull] IQueryable<float?> source,
CancellationToken cancellationToken = default);
Task<float> AverageAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, float>> selector,
CancellationToken cancellationToken = default);
Task<float?> AverageAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, float?>> selector,
CancellationToken cancellationToken = default);
#endregion
#region ToList/Array
Task<List<T>> ToListAsync<T>(
[NotNull] IQueryable<T> queryable,
CancellationToken cancellationToken = default);
Task<T[]> ToArrayAsync<T>(
[NotNull] IQueryable<T> queryable,
CancellationToken cancellationToken = default);
#endregion
}
}
}

394
framework/src/Volo.Abp.Threading/Volo/Abp/Linq/IAsyncQueryableProvider.cs

@ -1,18 +1,400 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Volo.Abp.Linq
{
public interface IAsyncQueryableProvider
{
bool CanExecute<T>(IQueryable<T> queryable);
Task<int> CountAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default);
Task<List<T>> ToListAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default);
#region Contains
Task<T> FirstOrDefaultAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default);
Task<bool> ContainsAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] T item,
CancellationToken cancellationToken = default);
#endregion
#region Any/All
Task<bool> AnyAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default);
Task<bool> AllAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default);
#endregion
#region Count/LongCount
Task<int> CountAsync<T>(
[NotNull] IQueryable<T> queryable,
CancellationToken cancellationToken = default);
Task<int> CountAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default);
Task<long> LongCountAsync<T>(
[NotNull] IQueryable<T> queryable,
CancellationToken cancellationToken = default);
Task<long> LongCountAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default);
#endregion
#region First/FirstOrDefault
Task<T> FirstAsync<T>(
[NotNull] IQueryable<T> queryable,
CancellationToken cancellationToken = default);
Task<T> FirstAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default);
Task<T> FirstOrDefaultAsync<T>(
[NotNull] IQueryable<T> queryable,
CancellationToken cancellationToken = default);
Task<T> FirstOrDefaultAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default);
#endregion
#region Last/LastOrDefault
Task<T> LastAsync<T>(
[NotNull] IQueryable<T> queryable,
CancellationToken cancellationToken = default);
Task<T> LastAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default);
Task<T> LastOrDefaultAsync<T>(
[NotNull] IQueryable<T> queryable,
CancellationToken cancellationToken = default);
Task<T> LastOrDefaultAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default);
#endregion
#region Single/SingleOrDefault
Task<T> SingleAsync<T>(
[NotNull] IQueryable<T> queryable,
CancellationToken cancellationToken = default);
Task<T> SingleAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default);
Task<T> SingleOrDefaultAsync<T>(
[NotNull] IQueryable<T> queryable,
CancellationToken cancellationToken = default);
Task<T> SingleOrDefaultAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default);
#endregion
#region Min
Task<T> MinAsync<T>(
[NotNull] IQueryable<T> queryable,
CancellationToken cancellationToken = default);
Task<TResult> MinAsync<T, TResult>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, TResult>> selector,
CancellationToken cancellationToken = default);
#endregion
#region Max
Task<T> MaxAsync<T>(
[NotNull] IQueryable<T> queryable,
CancellationToken cancellationToken = default);
Task<TResult> MaxAsync<T, TResult>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, TResult>> selector,
CancellationToken cancellationToken = default);
#endregion
#region Sum
Task<decimal> SumAsync(
[NotNull] IQueryable<decimal> source,
CancellationToken cancellationToken = default);
Task<decimal?> SumAsync(
[NotNull] IQueryable<decimal?> source,
CancellationToken cancellationToken = default);
Task<decimal> SumAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, decimal>> selector,
CancellationToken cancellationToken = default);
Task<decimal?> SumAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, decimal?>> selector,
CancellationToken cancellationToken = default);
Task<int> SumAsync(
[NotNull] IQueryable<int> source,
CancellationToken cancellationToken = default);
Task<int?> SumAsync(
[NotNull] IQueryable<int?> source,
CancellationToken cancellationToken = default);
Task<int> SumAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, int>> selector,
CancellationToken cancellationToken = default);
Task<int?> SumAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, int?>> selector,
CancellationToken cancellationToken = default);
Task<long> SumAsync(
[NotNull] IQueryable<long> source,
CancellationToken cancellationToken = default);
Task<long?> SumAsync(
[NotNull] IQueryable<long?> source,
CancellationToken cancellationToken = default);
Task<long> SumAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, long>> selector,
CancellationToken cancellationToken = default);
Task<long?> SumAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, long?>> selector,
CancellationToken cancellationToken = default);
Task<double> SumAsync(
[NotNull] IQueryable<double> source,
CancellationToken cancellationToken = default);
Task<double?> SumAsync(
[NotNull] IQueryable<double?> source,
CancellationToken cancellationToken = default);
Task<double> SumAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, double>> selector,
CancellationToken cancellationToken = default);
Task<double?> SumAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, double?>> selector,
CancellationToken cancellationToken = default);
Task<float> SumAsync(
[NotNull] IQueryable<float> source,
CancellationToken cancellationToken = default);
Task<float?> SumAsync(
[NotNull] IQueryable<float?> source,
CancellationToken cancellationToken = default);
Task<float> SumAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, float>> selector,
CancellationToken cancellationToken = default);
Task<float?> SumAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, float?>> selector,
CancellationToken cancellationToken = default);
#endregion
#region Average
Task<decimal> AverageAsync(
[NotNull] IQueryable<decimal> source,
CancellationToken cancellationToken = default);
Task<decimal?> AverageAsync(
[NotNull] IQueryable<decimal?> source,
CancellationToken cancellationToken = default);
Task<decimal> AverageAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, decimal>> selector,
CancellationToken cancellationToken = default);
Task<decimal?> AverageAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, decimal?>> selector,
CancellationToken cancellationToken = default);
Task<double> AverageAsync(
[NotNull] IQueryable<int> source,
CancellationToken cancellationToken = default);
Task<double?> AverageAsync(
[NotNull] IQueryable<int?> source,
CancellationToken cancellationToken = default);
Task<double> AverageAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, int>> selector,
CancellationToken cancellationToken = default);
Task<double?> AverageAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, int?>> selector,
CancellationToken cancellationToken = default);
Task<double> AverageAsync(
[NotNull] IQueryable<long> source,
CancellationToken cancellationToken = default);
Task<double?> AverageAsync(
[NotNull] IQueryable<long?> source,
CancellationToken cancellationToken = default);
Task<double> AverageAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, long>> selector,
CancellationToken cancellationToken = default);
Task<double?> AverageAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, long?>> selector,
CancellationToken cancellationToken = default);
Task<double> AverageAsync(
[NotNull] IQueryable<double> source,
CancellationToken cancellationToken = default);
Task<double?> AverageAsync(
[NotNull] IQueryable<double?> source,
CancellationToken cancellationToken = default);
Task<double> AverageAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, double>> selector,
CancellationToken cancellationToken = default);
Task<double?> AverageAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, double?>> selector,
CancellationToken cancellationToken = default);
Task<float> AverageAsync(
[NotNull] IQueryable<float> source,
CancellationToken cancellationToken = default);
Task<float?> AverageAsync(
[NotNull] IQueryable<float?> source,
CancellationToken cancellationToken = default);
Task<float> AverageAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, float>> selector,
CancellationToken cancellationToken = default);
Task<float?> AverageAsync<T>(
[NotNull] IQueryable<T> queryable,
[NotNull] Expression<Func<T, float?>> selector,
CancellationToken cancellationToken = default);
#endregion
#region ToList/Array
Task<List<T>> ToListAsync<T>(
[NotNull] IQueryable<T> queryable,
CancellationToken cancellationToken = default);
Task<T[]> ToArrayAsync<T>(
[NotNull] IQueryable<T> queryable,
CancellationToken cancellationToken = default);
#endregion
}
}
}

6
framework/src/Volo.Abp.Uow/Volo/Abp/Uow/AbpUnitOfWorkDefaultOptions.cs

@ -4,7 +4,7 @@ using System.Data;
namespace Volo.Abp.Uow
{
//TODO: Implement default options!
/// <summary>
/// Global (default) unit of work options
/// </summary>
@ -17,7 +17,7 @@ namespace Volo.Abp.Uow
public IsolationLevel? IsolationLevel { get; set; }
public TimeSpan? Timeout { get; set; }
public int? Timeout { get; set; }
internal AbpUnitOfWorkOptions Normalize(AbpUnitOfWorkOptions options)
{
@ -49,4 +49,4 @@ namespace Volo.Abp.Uow
}
}
}
}
}

11
framework/src/Volo.Abp.Uow/Volo/Abp/Uow/AbpUnitOfWorkOptions.cs

@ -12,14 +12,17 @@ namespace Volo.Abp.Uow
public IsolationLevel? IsolationLevel { get; set; }
public TimeSpan? Timeout { get; set; }
/// <summary>
/// Milliseconds
/// </summary>
public int? Timeout { get; set; }
public AbpUnitOfWorkOptions()
{
}
public AbpUnitOfWorkOptions(bool isTransactional = false, IsolationLevel? isolationLevel = null, TimeSpan? timeout = null)
public AbpUnitOfWorkOptions(bool isTransactional = false, IsolationLevel? isolationLevel = null, int? timeout = null)
{
IsTransactional = isTransactional;
IsolationLevel = isolationLevel;
@ -36,4 +39,4 @@ namespace Volo.Abp.Uow
};
}
}
}
}

7
framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IAbpUnitOfWorkOptions.cs

@ -9,6 +9,9 @@ namespace Volo.Abp.Uow
IsolationLevel? IsolationLevel { get; }
TimeSpan? Timeout { get; }
/// <summary>
/// Milliseconds
/// </summary>
int? Timeout { get; }
}
}
}

2
framework/src/Volo.Abp.Uow/Volo/Abp/Uow/ISupportsSavingChanges.cs

@ -5,8 +5,6 @@ namespace Volo.Abp.Uow
{
public interface ISupportsSavingChanges
{
void SaveChanges();
Task SaveChangesAsync(CancellationToken cancellationToken = default);
}
}

2
framework/src/Volo.Abp.Uow/Volo/Abp/Uow/ITransactionApi.cs

@ -5,8 +5,6 @@ namespace Volo.Abp.Uow
{
public interface ITransactionApi : IDisposable
{
void Commit();
Task CommitAsync();
}
}

10
framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWork.cs

@ -302,15 +302,7 @@ namespace Volo.Abp.Uow
}
}
}
protected virtual void CommitTransactions()
{
foreach (var transaction in GetAllActiveTransactionApis())
{
transaction.Commit();
}
}
protected virtual async Task CommitTransactionsAsync()
{
foreach (var transaction in GetAllActiveTransactionApis())

6
framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkAttribute.cs

@ -22,7 +22,7 @@ namespace Volo.Abp.Uow
/// Timeout of UOW As milliseconds.
/// Uses default value if not supplied.
/// </summary>
public TimeSpan? Timeout { get; set; }
public int? Timeout { get; set; }
/// <summary>
/// If this UOW is transactional, this option indicated the isolation level of the transaction.
@ -39,7 +39,7 @@ namespace Volo.Abp.Uow
public UnitOfWorkAttribute()
{
}
public UnitOfWorkAttribute(bool isTransactional)
@ -53,7 +53,7 @@ namespace Volo.Abp.Uow
IsolationLevel = isolationLevel;
}
public UnitOfWorkAttribute(bool isTransactional, IsolationLevel isolationLevel, TimeSpan timeout)
public UnitOfWorkAttribute(bool isTransactional, IsolationLevel isolationLevel, int timeout)
{
IsTransactional = isTransactional;
IsolationLevel = isolationLevel;

8
framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkManagerExtensions.cs

@ -8,11 +8,11 @@ namespace Volo.Abp.Uow
{
[NotNull]
public static IUnitOfWork Begin(
[NotNull] this IUnitOfWorkManager unitOfWorkManager,
[NotNull] this IUnitOfWorkManager unitOfWorkManager,
bool requiresNew = false,
bool isTransactional = false,
IsolationLevel? isolationLevel = null,
TimeSpan? timeout = null)
IsolationLevel? isolationLevel = null,
int? timeout = null)
{
Check.NotNull(unitOfWorkManager, nameof(unitOfWorkManager));
@ -40,4 +40,4 @@ namespace Volo.Abp.Uow
unitOfWorkManager.TryBeginReserved(reservationName, new AbpUnitOfWorkOptions());
}
}
}
}

62
modules/blogging/Volo.Blogging.sln

@ -43,6 +43,22 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Blogging.MongoDB.Tests
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Blogging.Domain.Tests", "test\Volo.Blogging.Domain.Tests\Volo.Blogging.Domain.Tests.csproj", "{B6D7EF20-9921-490A-AA95-47E3E174DC9B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "admin-app", "admin-app", "{BE2A423C-271E-469A-AD90-5640DEBEE9C1}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "domain", "domain", "{A9EF3061-5205-46C7-ACAA-23931CB98E4F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "public-app", "public-app", "{1314C122-18F0-4C6B-895F-27645B6121FF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Blogging.Admin.Application.Contracts", "src\Volo.Blogging.Admin.Application.Contracts\Volo.Blogging.Admin.Application.Contracts.csproj", "{D8DF4D56-644E-4ADF-9DB9-712DDA62B129}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Blogging.Admin.Application", "src\Volo.Blogging.Admin.Application\Volo.Blogging.Admin.Application.csproj", "{CB5DEBB3-5C2E-48E9-AA42-497575BCC7A4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Blogging.Admin.HttpApi", "src\Volo.Blogging.Admin.HttpApi\Volo.Blogging.Admin.HttpApi.csproj", "{59BBAF94-CC8E-4313-9143-F2F5C36A7C45}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Blogging.Admin.HttpApi.Client", "src\Volo.Blogging.Admin.HttpApi.Client\Volo.Blogging.Admin.HttpApi.Client.csproj", "{58A63CC9-C886-448B-AB4E-068600294D86}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Blogging.Admin.Web", "src\Volo.Blogging.Admin.Web\Volo.Blogging.Admin.Web.csproj", "{DB75CA32-96A5-4D10-8DD0-E62A3D0DDBCB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -117,28 +133,56 @@ Global
{B6D7EF20-9921-490A-AA95-47E3E174DC9B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B6D7EF20-9921-490A-AA95-47E3E174DC9B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B6D7EF20-9921-490A-AA95-47E3E174DC9B}.Release|Any CPU.Build.0 = Release|Any CPU
{D8DF4D56-644E-4ADF-9DB9-712DDA62B129}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D8DF4D56-644E-4ADF-9DB9-712DDA62B129}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D8DF4D56-644E-4ADF-9DB9-712DDA62B129}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D8DF4D56-644E-4ADF-9DB9-712DDA62B129}.Release|Any CPU.Build.0 = Release|Any CPU
{CB5DEBB3-5C2E-48E9-AA42-497575BCC7A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CB5DEBB3-5C2E-48E9-AA42-497575BCC7A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CB5DEBB3-5C2E-48E9-AA42-497575BCC7A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CB5DEBB3-5C2E-48E9-AA42-497575BCC7A4}.Release|Any CPU.Build.0 = Release|Any CPU
{59BBAF94-CC8E-4313-9143-F2F5C36A7C45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{59BBAF94-CC8E-4313-9143-F2F5C36A7C45}.Debug|Any CPU.Build.0 = Debug|Any CPU
{59BBAF94-CC8E-4313-9143-F2F5C36A7C45}.Release|Any CPU.ActiveCfg = Release|Any CPU
{59BBAF94-CC8E-4313-9143-F2F5C36A7C45}.Release|Any CPU.Build.0 = Release|Any CPU
{58A63CC9-C886-448B-AB4E-068600294D86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{58A63CC9-C886-448B-AB4E-068600294D86}.Debug|Any CPU.Build.0 = Debug|Any CPU
{58A63CC9-C886-448B-AB4E-068600294D86}.Release|Any CPU.ActiveCfg = Release|Any CPU
{58A63CC9-C886-448B-AB4E-068600294D86}.Release|Any CPU.Build.0 = Release|Any CPU
{DB75CA32-96A5-4D10-8DD0-E62A3D0DDBCB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DB75CA32-96A5-4D10-8DD0-E62A3D0DDBCB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DB75CA32-96A5-4D10-8DD0-E62A3D0DDBCB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DB75CA32-96A5-4D10-8DD0-E62A3D0DDBCB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{F1D954AD-001A-4533-A8CC-94DDCF70B552} = {42BF26EF-B8C7-42DC-9FFB-3653109B7776}
{9F3AECDD-0B96-4EB4-BB86-59B488350B76} = {42BF26EF-B8C7-42DC-9FFB-3653109B7776}
{237BF49B-5FD8-413C-BBD7-2313D91D0553} = {42BF26EF-B8C7-42DC-9FFB-3653109B7776}
{1678D922-E56D-4D6F-94F5-12AD13C1D919} = {42BF26EF-B8C7-42DC-9FFB-3653109B7776}
{87A423C6-900E-4D59-A4F2-B7C49D91E6F0} = {42BF26EF-B8C7-42DC-9FFB-3653109B7776}
{C20F42B4-0E93-43D3-B7CD-363D7E1B4750} = {42BF26EF-B8C7-42DC-9FFB-3653109B7776}
{03328648-6DE6-43C1-9A27-64771A73FAAD} = {42BF26EF-B8C7-42DC-9FFB-3653109B7776}
{A4DBA051-7FB9-4AD7-B9B7-6810B2268122} = {42BF26EF-B8C7-42DC-9FFB-3653109B7776}
{0D50B2EE-5F62-4C1D-B04D-56BE0CF75967} = {EB4FB44A-FE39-4245-9DAD-D6437BCE3870}
{14409939-5A35-4145-A5C4-F3AED1617243} = {EB4FB44A-FE39-4245-9DAD-D6437BCE3870}
{BBE8D8BE-1B24-49FE-86EF-3848D4BB6829} = {25B3A516-5C0D-42E3-9294-E8A9346CEE4B}
{0B9AAD44-1FCF-4AF1-838F-A09446E98E37} = {25B3A516-5C0D-42E3-9294-E8A9346CEE4B}
{C949B953-80B3-4B36-B535-1AD74A34FEAC} = {25B3A516-5C0D-42E3-9294-E8A9346CEE4B}
{98C2D36A-F874-405D-8565-9CE59438E879} = {42BF26EF-B8C7-42DC-9FFB-3653109B7776}
{4C818374-2DE8-422F-8585-975E8366DB26} = {EB4FB44A-FE39-4245-9DAD-D6437BCE3870}
{0A29F64C-11F1-40B6-8E6D-91E86823775E} = {25B3A516-5C0D-42E3-9294-E8A9346CEE4B}
{B6D7EF20-9921-490A-AA95-47E3E174DC9B} = {25B3A516-5C0D-42E3-9294-E8A9346CEE4B}
{BE2A423C-271E-469A-AD90-5640DEBEE9C1} = {42BF26EF-B8C7-42DC-9FFB-3653109B7776}
{A9EF3061-5205-46C7-ACAA-23931CB98E4F} = {42BF26EF-B8C7-42DC-9FFB-3653109B7776}
{1314C122-18F0-4C6B-895F-27645B6121FF} = {42BF26EF-B8C7-42DC-9FFB-3653109B7776}
{9F3AECDD-0B96-4EB4-BB86-59B488350B76} = {A9EF3061-5205-46C7-ACAA-23931CB98E4F}
{F1D954AD-001A-4533-A8CC-94DDCF70B552} = {A9EF3061-5205-46C7-ACAA-23931CB98E4F}
{87A423C6-900E-4D59-A4F2-B7C49D91E6F0} = {A9EF3061-5205-46C7-ACAA-23931CB98E4F}
{98C2D36A-F874-405D-8565-9CE59438E879} = {A9EF3061-5205-46C7-ACAA-23931CB98E4F}
{1678D922-E56D-4D6F-94F5-12AD13C1D919} = {1314C122-18F0-4C6B-895F-27645B6121FF}
{237BF49B-5FD8-413C-BBD7-2313D91D0553} = {1314C122-18F0-4C6B-895F-27645B6121FF}
{C20F42B4-0E93-43D3-B7CD-363D7E1B4750} = {1314C122-18F0-4C6B-895F-27645B6121FF}
{03328648-6DE6-43C1-9A27-64771A73FAAD} = {1314C122-18F0-4C6B-895F-27645B6121FF}
{A4DBA051-7FB9-4AD7-B9B7-6810B2268122} = {1314C122-18F0-4C6B-895F-27645B6121FF}
{D8DF4D56-644E-4ADF-9DB9-712DDA62B129} = {BE2A423C-271E-469A-AD90-5640DEBEE9C1}
{CB5DEBB3-5C2E-48E9-AA42-497575BCC7A4} = {BE2A423C-271E-469A-AD90-5640DEBEE9C1}
{59BBAF94-CC8E-4313-9143-F2F5C36A7C45} = {BE2A423C-271E-469A-AD90-5640DEBEE9C1}
{58A63CC9-C886-448B-AB4E-068600294D86} = {BE2A423C-271E-469A-AD90-5640DEBEE9C1}
{DB75CA32-96A5-4D10-8DD0-E62A3D0DDBCB} = {BE2A423C-271E-469A-AD90-5640DEBEE9C1}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F2BAE819-78D4-407A-9201-22473B2850B0}

15
modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs

@ -33,6 +33,7 @@ using Volo.Abp.Threading;
using Volo.Abp.UI;
using Volo.Abp.VirtualFileSystem;
using Volo.Blogging;
using Volo.Blogging.Admin;
using Volo.Blogging.Files;
using Volo.BloggingTestApp.EntityFrameworkCore;
using Volo.BloggingTestApp.MongoDB;
@ -42,6 +43,8 @@ namespace Volo.BloggingTestApp
[DependsOn(
typeof(BloggingWebModule),
typeof(BloggingApplicationModule),
typeof(BloggingAdminWebModule),
typeof(BloggingAdminApplicationModule),
#if MONGODB
typeof(BloggingTestAppMongoDbModule),
#else
@ -105,12 +108,12 @@ namespace Volo.BloggingTestApp
options.CustomSchemaIds(type => type.FullName);
});
var cultures = new List<CultureInfo>
{
new CultureInfo("cs"),
new CultureInfo("en"),
new CultureInfo("tr"),
new CultureInfo("zh-Hans")
var cultures = new List<CultureInfo>
{
new CultureInfo("cs"),
new CultureInfo("en"),
new CultureInfo("tr"),
new CultureInfo("zh-Hans")
};
Configure<RequestLocalizationOptions>(options =>

2
modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.csproj

@ -26,6 +26,8 @@
<ProjectReference Include="..\Volo.BloggingTestApp.EntityFrameworkCore\Volo.BloggingTestApp.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\src\Volo.Blogging.Application\Volo.Blogging.Application.csproj" />
<ProjectReference Include="..\..\src\Volo.Blogging.Web\Volo.Blogging.Web.csproj" />
<ProjectReference Include="..\..\src\Volo.Blogging.Admin.Application\Volo.Blogging.Admin.Application.csproj" />
<ProjectReference Include="..\..\src\Volo.Blogging.Admin.Web\Volo.Blogging.Admin.Web.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.csproj" />
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.Identity.Application\Volo.Abp.Identity.Application.csproj" />

3
modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

31
modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo.Blogging.Admin.Application.Contracts.csproj

@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Blogging.Admin.Application.Contracts</AssemblyName>
<PackageId>Volo.Blogging.Admin.Application.Contracts</PackageId>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Blogging.Domain.Shared\Volo.Blogging.Domain.Shared.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Ddd.Application\Volo.Abp.Ddd.Application.csproj" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Volo\Blogging\Admin\Localization\Resources\Blogging\Admin\ApplicationContracts\cs.json" />
<EmbeddedResource Include="Volo\Blogging\Admin\Localization\Resources\Blogging\Admin\ApplicationContracts\de.json" />
<EmbeddedResource Include="Volo\Blogging\Admin\Localization\Resources\Blogging\Admin\ApplicationContracts\en.json" />
<EmbeddedResource Include="Volo\Blogging\Admin\Localization\Resources\Blogging\Admin\ApplicationContracts\nl.json" />
<EmbeddedResource Include="Volo\Blogging\Admin\Localization\Resources\Blogging\Admin\ApplicationContracts\pl-PL.json" />
<EmbeddedResource Include="Volo\Blogging\Admin\Localization\Resources\Blogging\Admin\ApplicationContracts\pt-BR.json" />
<EmbeddedResource Include="Volo\Blogging\Admin\Localization\Resources\Blogging\Admin\ApplicationContracts\sl.json" />
<EmbeddedResource Include="Volo\Blogging\Admin\Localization\Resources\Blogging\Admin\ApplicationContracts\tr.json" />
<EmbeddedResource Include="Volo\Blogging\Admin\Localization\Resources\Blogging\Admin\ApplicationContracts\vi.json" />
<EmbeddedResource Include="Volo\Blogging\Admin\Localization\Resources\Blogging\Admin\ApplicationContracts\zh-Hans.json" />
<EmbeddedResource Include="Volo\Blogging\Admin\Localization\Resources\Blogging\Admin\ApplicationContracts\zh-Hant.json" />
</ItemGroup>
</Project>

25
modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/BloggingAdminApplicationContractsModule.cs

@ -0,0 +1,25 @@
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
using Volo.Blogging.Localization;
namespace Volo.Blogging.Admin
{
[DependsOn(typeof(BloggingDomainSharedModule))]
public class BloggingAdminApplicationContractsModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<BloggingAdminApplicationContractsModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Get<BloggingResource>()
.AddVirtualJson("Volo/Blogging/Admin/Localization/Resources/Blogging/Admin/ApplicationContracts");
});
}
}
}

25
modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/BloggingAdminPermissionDefinitionProvider.cs

@ -0,0 +1,25 @@
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Localization;
using Volo.Blogging.Localization;
namespace Volo.Blogging.Admin
{
public class BloggingAdminPermissionDefinitionProvider : PermissionDefinitionProvider
{
public override void Define(IPermissionDefinitionContext context)
{
var bloggingGroup = context.AddGroup(BloggingAdminPermissions.GroupName, L("Permission:BloggingAdmin"));
var blogs = bloggingGroup.AddPermission(BloggingAdminPermissions.Blogs.Default, L("Permission:Blogs"));
blogs.AddChild(BloggingAdminPermissions.Blogs.Management, L("Permission:Management"));
blogs.AddChild(BloggingAdminPermissions.Blogs.Update, L("Permission:Edit"));
blogs.AddChild(BloggingAdminPermissions.Blogs.Delete, L("Permission:Delete"));
blogs.AddChild(BloggingAdminPermissions.Blogs.Create, L("Permission:Create"));
}
private static LocalizableString L(string name)
{
return LocalizableString.Create<BloggingResource>(name);
}
}
}

23
modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/BloggingAdminPermissions.cs

@ -0,0 +1,23 @@
using Volo.Abp.Reflection;
namespace Volo.Blogging.Admin
{
public class BloggingAdminPermissions
{
public const string GroupName = "Blogging.Admin";
public static class Blogs
{
public const string Default = GroupName + ".Blog";
public const string Management = Default + ".Management";
public const string Delete = Default + ".Delete";
public const string Update = Default + ".Update";
public const string Create = Default + ".Create";
}
public static string[] GetAll()
{
return ReflectionHelper.GetPublicConstantsRecursively(typeof(BloggingAdminPermissions));
}
}
}

7
modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/BloggingAdminRemoteServiceConsts.cs

@ -0,0 +1,7 @@
namespace Volo.Blogging.Admin
{
public static class BloggingAdminRemoteServiceConsts
{
public const string RemoteServiceName = "BloggingAdmin";
}
}

14
modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Blogs/BlogDto.cs

@ -0,0 +1,14 @@
using System;
using Volo.Abp.Application.Dtos;
namespace Volo.Blogging.Admin.Blogs
{
public class BlogDto : FullAuditedEntityDto<Guid>
{
public string Name { get; set; }
public string ShortName { get; set; }
public string Description { get; set; }
}
}

4
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Blogs/Dtos/CreateBlogDto.cs → modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Blogs/CreateBlogDto.cs

@ -1,4 +1,4 @@
namespace Volo.Blogging.Blogs.Dtos
namespace Volo.Blogging.Admin.Blogs
{
public class CreateBlogDto
{
@ -8,4 +8,4 @@ namespace Volo.Blogging.Blogs.Dtos
public string Description { get; set; }
}
}
}

20
modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Blogs/IBlogManagementAppService.cs

@ -0,0 +1,20 @@
using System;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace Volo.Blogging.Admin.Blogs
{
public interface IBlogManagementAppService : IApplicationService
{
Task<ListResultDto<BlogDto>> GetListAsync();
Task<BlogDto> GetAsync(Guid id);
Task<BlogDto> CreateAsync(CreateBlogDto input);
Task<BlogDto> UpdateAsync(Guid id, UpdateBlogDto input);
Task DeleteAsync(Guid id);
}
}

4
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Blogs/Dtos/UpdateBlogDto.cs → modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Blogs/UpdateBlogDto.cs

@ -1,4 +1,4 @@
namespace Volo.Blogging.Blogs.Dtos
namespace Volo.Blogging.Admin.Blogs
{
public class UpdateBlogDto
{
@ -8,4 +8,4 @@
public string Description { get; set; }
}
}
}

11
modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Localization/Resources/Blogging/Admin/ApplicationContracts/cs.json

@ -0,0 +1,11 @@
{
"culture": "cs",
"texts": {
"Permission:BloggingAdmin": "Blog",
"Permission:Blogs": "Blogy",
"Permission:Management": "Správa",
"Permission:Edit": "Upravit",
"Permission:Create": "Vytvořit",
"Permission:Delete": "Smazat"
}
}

11
modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Localization/Resources/Blogging/Admin/ApplicationContracts/de.json

@ -0,0 +1,11 @@
{
"culture": "de",
"texts": {
"Permission:BloggingAdmin": "Blog",
"Permission:Blogs": "Blogs",
"Permission:Management": "Verwaltung",
"Permission:Edit": "Bearbeiten",
"Permission:Create": "Erstellen",
"Permission:Delete": "Löschen"
}
}

11
modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Localization/Resources/Blogging/Admin/ApplicationContracts/en.json

@ -0,0 +1,11 @@
{
"culture": "en",
"texts": {
"Permission:BloggingAdmin": "Blogging",
"Permission:Blogs": "Blogs",
"Permission:Management": "Management",
"Permission:Edit": "Edit",
"Permission:Create": "Create",
"Permission:Delete": "Delete"
}
}

11
modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Localization/Resources/Blogging/Admin/ApplicationContracts/nl.json

@ -0,0 +1,11 @@
{
"culture": "nl",
"texts": {
"Permission:BloggingAdmin": "Blog",
"Permission:Blogs": "Blogs",
"Permission:Management": "Beheer",
"Permission:Edit": "Bewerk",
"Permission:Create": "Maak aan",
"Permission:Delete": "Verwijder"
}
}

11
modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Localization/Resources/Blogging/Admin/ApplicationContracts/pl-PL.json

@ -0,0 +1,11 @@
{
"culture": "pl-PL",
"texts": {
"Permission:BloggingAdmin": "Blog",
"Permission:Blogs": "Blogi",
"Permission:Management": "Zarządzanie",
"Permission:Edit": "Edytuj",
"Permission:Create": "Utwórz",
"Permission:Delete": "Usuń"
}
}

11
modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Localization/Resources/Blogging/Admin/ApplicationContracts/pt-BR.json

@ -0,0 +1,11 @@
{
"culture": "pt-BR",
"texts": {
"Permission:BloggingAdmin": "Blog",
"Permission:Blogs": "Blogs",
"Permission:Management": "Gerenciamento",
"Permission:Edit": "Editar",
"Permission:Create": "Criar",
"Permission:Delete": "Excluir"
}
}

11
modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Localization/Resources/Blogging/Admin/ApplicationContracts/sl.json

@ -0,0 +1,11 @@
{
"culture": "sl",
"texts": {
"Permission:BloggingAdmin": "Blog",
"Permission:Blogs": "Blogi",
"Permission:Management": "Upravljanje",
"Permission:Edit": "Urejanje",
"Permission:Create": "Ustvarjanje",
"Permission:Delete": "Brisanje"
}
}

11
modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Localization/Resources/Blogging/Admin/ApplicationContracts/tr.json

@ -0,0 +1,11 @@
{
"culture": "tr",
"texts": {
"Permission:BloggingAdmin": "Blog",
"Permission:Blogs": "Bloglar",
"Permission:Management": "Yönetme",
"Permission:Edit": "Düzenle",
"Permission:Create": "Ekle",
"Permission:Delete": "Sil"
}
}

11
modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Localization/Resources/Blogging/Admin/ApplicationContracts/vi.json

@ -0,0 +1,11 @@
{
"culture": "vi",
"texts": {
"Permission:BloggingAdmin": "Blog",
"Permission:Blogs": "Blogs",
"Permission:Management": "Quản lý",
"Permission:Edit": "Sửa",
"Permission:Create": "Tạo",
"Permission:Delete": "Xóa"
}
}

11
modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Localization/Resources/Blogging/Admin/ApplicationContracts/zh-Hans.json

@ -0,0 +1,11 @@
{
"culture": "zh-Hans",
"texts": {
"Permission:BloggingAdmin": "博客",
"Permission:Blogs": "博客",
"Permission:Management": "管理",
"Permission:Edit": "编辑",
"Permission:Create": "创建",
"Permission:Delete": "删除"
}
}

11
modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Localization/Resources/Blogging/Admin/ApplicationContracts/zh-Hant.json

@ -0,0 +1,11 @@
{
"culture": "zh-Hant",
"texts": {
"Permission:BloggingAdmin": "部落格",
"Permission:Blogs": "部落格",
"Permission:Management": "管理",
"Permission:Edit": "標及",
"Permission:Create": "新增",
"Permission:Delete": "刪除"
}
}

3
modules/blogging/src/Volo.Blogging.Admin.Application/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
modules/blogging/src/Volo.Blogging.Admin.Application/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

20
modules/blogging/src/Volo.Blogging.Admin.Application/Volo.Blogging.Admin.Application.csproj

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Blogging.Admin.Application</AssemblyName>
<PackageId>Volo.Blogging.Admin.Application</PackageId>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="4.7.0" />
<ProjectReference Include="..\Volo.Blogging.Admin.Application.Contracts\Volo.Blogging.Admin.Application.Contracts.csproj" />
<ProjectReference Include="..\Volo.Blogging.Domain\Volo.Blogging.Domain.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Caching\Volo.Abp.Caching.csproj" />
</ItemGroup>
</Project>

14
modules/blogging/src/Volo.Blogging.Admin.Application/Volo/Blogging/Admin/BloggingAdminAppServiceBase.cs

@ -0,0 +1,14 @@
using Volo.Abp.Application.Services;
using Volo.Blogging.Localization;
namespace Volo.Blogging.Admin
{
public abstract class BloggingAdminAppServiceBase : ApplicationService
{
protected BloggingAdminAppServiceBase()
{
ObjectMapperContext = typeof(BloggingAdminApplicationModule);
LocalizationResource = typeof(BloggingResource);
}
}
}

14
modules/blogging/src/Volo.Blogging.Admin.Application/Volo/Blogging/Admin/BloggingAdminApplicationAutoMapperProfile.cs

@ -0,0 +1,14 @@
using AutoMapper;
using Volo.Blogging.Admin.Blogs;
using Volo.Blogging.Blogs;
namespace Volo.Blogging.Admin
{
public class BloggingAdminApplicationAutoMapperProfile : Profile
{
public BloggingAdminApplicationAutoMapperProfile()
{
CreateMap<Blog, BlogDto>();
}
}
}

27
modules/blogging/src/Volo.Blogging.Admin.Application/Volo/Blogging/Admin/BloggingAdminApplicationModule.cs

@ -0,0 +1,27 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AutoMapper;
using Volo.Abp.Caching;
using Volo.Abp.Modularity;
using Volo.Blogging.Comments;
using Volo.Blogging.Posts;
namespace Volo.Blogging.Admin
{
[DependsOn(
typeof(BloggingDomainModule),
typeof(BloggingAdminApplicationContractsModule),
typeof(AbpCachingModule),
typeof(AbpAutoMapperModule))]
public class BloggingAdminApplicationModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAutoMapperObjectMapper<BloggingAdminApplicationModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<BloggingAdminApplicationAutoMapperProfile>(validate: true);
});
}
}
}

64
modules/blogging/src/Volo.Blogging.Admin.Application/Volo/Blogging/Admin/Blogs/BlogManagementAppService.cs

@ -0,0 +1,64 @@
using Microsoft.AspNetCore.Authorization;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Blogging.Blogs;
namespace Volo.Blogging.Admin.Blogs
{
public class BlogManagementAppService : BloggingAdminAppServiceBase, IBlogManagementAppService
{
private readonly IBlogRepository _blogRepository;
public BlogManagementAppService(IBlogRepository blogRepository)
{
_blogRepository = blogRepository;
}
public async Task<ListResultDto<BlogDto>> GetListAsync()
{
var blogs = await _blogRepository.GetListAsync();
return new ListResultDto<BlogDto>(
ObjectMapper.Map<List<Blog>, List<BlogDto>>(blogs)
);
}
public async Task<BlogDto> GetAsync(Guid id)
{
var blog = await _blogRepository.GetAsync(id);
return ObjectMapper.Map<Blog, BlogDto>(blog);
}
[Authorize(BloggingAdminPermissions.Blogs.Create)]
public async Task<BlogDto> CreateAsync(CreateBlogDto input)
{
var newBlog = await _blogRepository.InsertAsync(new Blog(GuidGenerator.Create(), input.Name, input.ShortName)
{
Description = input.Description
});
return ObjectMapper.Map<Blog, BlogDto>(newBlog);
}
[Authorize(BloggingAdminPermissions.Blogs.Update)]
public async Task<BlogDto> UpdateAsync(Guid id, UpdateBlogDto input)
{
var blog = await _blogRepository.GetAsync(id);
blog.SetName(input.Name);
blog.SetShortName(input.ShortName);
blog.Description = input.Description;
return ObjectMapper.Map<Blog, BlogDto>(blog);
}
[Authorize(BloggingAdminPermissions.Blogs.Delete)]
public async Task DeleteAsync(Guid id)
{
await _blogRepository.DeleteAsync(id);
}
}
}

3
modules/blogging/src/Volo.Blogging.Admin.HttpApi.Client/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
modules/blogging/src/Volo.Blogging.Admin.HttpApi.Client/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

18
modules/blogging/src/Volo.Blogging.Admin.HttpApi.Client/Volo.Blogging.Admin.HttpApi.Client.csproj

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Blogging.Admin.HttpApi.Client</AssemblyName>
<PackageId>Volo.Blogging.Admin.HttpApi.Client</PackageId>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Blogging.Admin.Application.Contracts\Volo.Blogging.Admin.Application.Contracts.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Http.Client\Volo.Abp.Http.Client.csproj" />
</ItemGroup>
</Project>

19
modules/blogging/src/Volo.Blogging.Admin.HttpApi.Client/Volo/Blogging/Admin/BloggingAdminHttpApiClientModule.cs

@ -0,0 +1,19 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Http.Client;
using Volo.Abp.Modularity;
namespace Volo.Blogging.Admin
{
[DependsOn(
typeof(BloggingAdminApplicationContractsModule),
typeof(AbpHttpClientModule))]
public class BloggingAdminHttpApiClientModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddHttpClientProxies(typeof(BloggingAdminApplicationContractsModule).Assembly,
BloggingAdminRemoteServiceConsts.RemoteServiceName);
}
}
}

3
modules/blogging/src/Volo.Blogging.Admin.HttpApi/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
modules/blogging/src/Volo.Blogging.Admin.HttpApi/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

18
modules/blogging/src/Volo.Blogging.Admin.HttpApi/Volo.Blogging.Admin.HttpApi.csproj

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AssemblyName>Volo.Blogging.Admin.HttpApi</AssemblyName>
<PackageId>Volo.Blogging.Admin.HttpApi</PackageId>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Blogging.Admin.Application.Contracts\Volo.Blogging.Admin.Application.Contracts.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc\Volo.Abp.AspNetCore.Mvc.csproj" />
</ItemGroup>
</Project>

56
modules/blogging/src/Volo.Blogging.Admin.HttpApi/Volo/Blogging/Admin/BlogManagementController.cs

@ -0,0 +1,56 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Blogging.Admin.Blogs;
namespace Volo.Blogging.Admin
{
[RemoteService(Name = BloggingAdminRemoteServiceConsts.RemoteServiceName)]
[Area("bloggingAdmin")]
[Route("api/blogging/blogs/admin")]
public class BlogManagementController : AbpController, IBlogManagementAppService
{
private readonly IBlogManagementAppService _blogManagementAppService;
public BlogManagementController(IBlogManagementAppService blogManagementAppService)
{
_blogManagementAppService = blogManagementAppService;
}
[HttpGet]
public async Task<ListResultDto<BlogDto>> GetListAsync()
{
return await _blogManagementAppService.GetListAsync();
}
[HttpGet]
[Route("{id}")]
public async Task<BlogDto> GetAsync(Guid id)
{
return await _blogManagementAppService.GetAsync(id);
}
[HttpPost]
public async Task<BlogDto> CreateAsync(CreateBlogDto input)
{
return await _blogManagementAppService.CreateAsync(input);
}
[HttpPut]
[Route("{id}")]
public async Task<BlogDto> UpdateAsync(Guid id, UpdateBlogDto input)
{
return await _blogManagementAppService.UpdateAsync(id, input);
}
[HttpDelete]
[Route("{id}")]
public async Task DeleteAsync(Guid id)
{
await _blogManagementAppService.DeleteAsync(id);
}
}
}

33
modules/blogging/src/Volo.Blogging.Admin.HttpApi/Volo/Blogging/Admin/BloggingAdminHttpApiModule.cs

@ -0,0 +1,33 @@
using Localization.Resources.AbpUi;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Blogging.Localization;
using Microsoft.Extensions.DependencyInjection;
namespace Volo.Blogging.Admin
{
[DependsOn(
typeof(BloggingAdminApplicationContractsModule),
typeof(AbpAspNetCoreMvcModule))]
public class BloggingAdminHttpApiModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<IMvcBuilder>(mvcBuilder =>
{
mvcBuilder.AddApplicationPartIfNotExists(typeof(BloggingAdminHttpApiModule).Assembly);
});
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Get<BloggingResource>()
.AddBaseTypes(typeof(AbpUiResource));
});
}
}
}

16
modules/blogging/src/Volo.Blogging.Admin.Web/AbpBloggingAdminWebAutoMapperProfile.cs

@ -0,0 +1,16 @@
using AutoMapper;
using Volo.Blogging.Admin.Blogs;
using Volo.Blogging.Admin.Pages.Blogging.Admin.Blogs;
using EditModel = Volo.Blogging.Admin.Pages.Blogging.Admin.Blogs.EditModel;
namespace Volo.Blogging.Admin
{
public class AbpBloggingAdminWebAutoMapperProfile : Profile
{
public AbpBloggingAdminWebAutoMapperProfile()
{
CreateMap<CreateModel.BlogCreateModalView, CreateBlogDto>();
CreateMap<BlogDto, EditModel.BlogEditViewModel>();
}
}
}

17
modules/blogging/src/Volo.Blogging.Web/BloggingMenuContributor.cs → modules/blogging/src/Volo.Blogging.Admin.Web/BloggingAdminMenuContributor.cs

@ -1,13 +1,10 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using System.Threading.Tasks;
using System.Threading.Tasks;
using Volo.Abp.UI.Navigation;
using Volo.Blogging.Localization;
namespace Volo.Blogging
namespace Volo.Blogging.Admin
{
public class BloggingMenuContributor : IMenuContributor
public class BloggingAdminMenuContributor : IMenuContributor
{
public async Task ConfigureMenuAsync(MenuConfigurationContext context)
{
@ -21,17 +18,17 @@ namespace Volo.Blogging
{
var l = context.GetLocalizer<BloggingResource>();
if (await context.IsGrantedAsync(BloggingPermissions.Blogs.Management))
if (await context.IsGrantedAsync(BloggingAdminPermissions.Blogs.Management))
{
var managementRootMenuItem = new ApplicationMenuItem("BlogManagement", l["Menu:BlogManagement"]);
//TODO: Using the same permission. Reconsider.
if (await context.IsGrantedAsync(BloggingPermissions.Blogs.Management))
if (await context.IsGrantedAsync(BloggingAdminPermissions.Blogs.Management))
{
managementRootMenuItem.AddItem(new ApplicationMenuItem("BlogManagement.Blogs", l["Menu:Blogs"], "~/Admin/Blogs"));
managementRootMenuItem.AddItem(new ApplicationMenuItem("BlogManagement.Blogs", l["Menu:Blogs"], "~/Blogging/Admin/Blogs"));
}
context.Menu.AddItem(managementRootMenuItem);
context.Menu.GetAdministration().AddItem(managementRootMenuItem);
}
}
}

53
modules/blogging/src/Volo.Blogging.Admin.Web/BloggingAdminWebModule.cs

@ -0,0 +1,53 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AutoMapper;
using Volo.Abp.Modularity;
using Volo.Abp.UI.Navigation;
using Volo.Abp.VirtualFileSystem;
using Volo.Blogging.Localization;
namespace Volo.Blogging.Admin
{
[DependsOn(
typeof(BloggingAdminHttpApiModule),
typeof(AbpAspNetCoreMvcUiBootstrapModule),
typeof(AbpAspNetCoreMvcUiBundlingModule),
typeof(AbpAutoMapperModule)
)]
public class BloggingAdminWebModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
context.Services.PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options =>
{
options.AddAssemblyResource(typeof(BloggingResource), typeof(BloggingAdminWebModule).Assembly);
});
PreConfigure<IMvcBuilder>(mvcBuilder =>
{
mvcBuilder.AddApplicationPartIfNotExists(typeof(BloggingAdminWebModule).Assembly);
});
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpNavigationOptions>(options =>
{
options.MenuContributors.Add(new BloggingAdminMenuContributor());
});
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<BloggingAdminWebModule>("Volo.Blogging.Admin");
});
context.Services.AddAutoMapperObjectMapper<BloggingAdminWebModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<AbpBloggingAdminWebAutoMapperProfile>(validate: true);
});
}
}
}

3
modules/blogging/src/Volo.Blogging.Admin.Web/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
modules/blogging/src/Volo.Blogging.Admin.Web/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

6
modules/blogging/src/Volo.Blogging.Web/Pages/Admin/Blogs/Create.cshtml → modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/Create.cshtml

@ -1,7 +1,7 @@
@page
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
@using Volo.Blogging.Pages.Blog
@model Volo.Blogging.Pages.Admin.Blogs.CreateModel
@inherits Volo.Blogging.Admin.Pages.Blogging.BloggingAdminPage
@model Volo.Blogging.Admin.Pages.Blogging.Admin.Blogs.CreateModel
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Blogging.Localization
@inject IHtmlLocalizer<BloggingResource> L
@ -10,7 +10,7 @@
}
<abp-dynamic-form submit-button="false" abp-model="Blog" asp-page="/Admin/Blogs/Create">
<abp-dynamic-form submit-button="false" abp-model="Blog" asp-page="/Blogging/Admin/Blogs/Create">
<abp-modal size="@(AbpModalSize.Large)">
<abp-modal-header title="@L["Create"].Value"></abp-modal-header>
<abp-modal-body>

19
modules/blogging/src/Volo.Blogging.Web/Pages/Admin/Blogs/Create.cshtml.cs → modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/Create.cshtml.cs

@ -2,23 +2,20 @@ using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Blogging.Admin.Blogs;
using Volo.Blogging.Blogs;
using Volo.Blogging.Blogs.Dtos;
using Volo.Blogging.Pages.Blog;
namespace Volo.Blogging.Pages.Admin.Blogs
namespace Volo.Blogging.Admin.Pages.Blogging.Admin.Blogs
{
public class CreateModel : BloggingPageModel
public class CreateModel : BloggingAdminPageModel
{
private readonly IBlogAppService _blogAppService;
private readonly IBlogManagementAppService _blogAppService;
private readonly IAuthorizationService _authorization;
[BindProperty]
public BlogCreateModalView Blog { get; set; } = new BlogCreateModalView();
public CreateModel(IBlogAppService blogAppService, IAuthorizationService authorization)
public CreateModel(IBlogManagementAppService blogAppService, IAuthorizationService authorization)
{
_blogAppService = blogAppService;
_authorization = authorization;
@ -26,7 +23,7 @@ namespace Volo.Blogging.Pages.Admin.Blogs
public virtual async Task<ActionResult> OnGetAsync()
{
if (!await _authorization.IsGrantedAsync(BloggingPermissions.Blogs.Create))
if (!await _authorization.IsGrantedAsync(BloggingAdminPermissions.Blogs.Create))
{
return Redirect("/");
}
@ -38,7 +35,7 @@ namespace Volo.Blogging.Pages.Admin.Blogs
{
var blogDto = ObjectMapper.Map<BlogCreateModalView, CreateBlogDto>(Blog);
await _blogAppService.Create(blogDto);
await _blogAppService.CreateAsync(blogDto);
return NoContent();
}
@ -59,4 +56,4 @@ namespace Volo.Blogging.Pages.Admin.Blogs
}
}
}
}

7
modules/blogging/src/Volo.Blogging.Web/Pages/Admin/Blogs/Edit.cshtml → modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/Edit.cshtml

@ -1,7 +1,7 @@
@page
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
@using Volo.Blogging.Pages.Blog
@model Volo.Blogging.Pages.Admin.Blogs.EditModel
@inherits Volo.Blogging.Admin.Pages.Blogging.BloggingAdminPage
@model Volo.Blogging.Admin.Pages.Blogging.Admin.Blogs.EditModel
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Blogging.Localization
@inject IHtmlLocalizer<BloggingResource> L
@ -9,8 +9,7 @@
Layout = null;
}
<abp-dynamic-form abp-model="Blog" asp-page="/Admin/Blogs/Edit">
<abp-dynamic-form abp-model="Blog" asp-page="/Blogging/Admin/Blogs/Edit">
<abp-modal size="@(AbpModalSize.Large)">
<abp-modal-header title="@L["Edit"].Value"></abp-modal-header>
<abp-modal-body>

22
modules/blogging/src/Volo.Blogging.Web/Pages/Admin/Blogs/Edit.cshtml.cs → modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/Edit.cshtml.cs

@ -1,20 +1,16 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Blogging.Admin.Blogs;
using Volo.Blogging.Blogs;
using Volo.Blogging.Blogs.Dtos;
using Volo.Blogging.Pages.Blog;
using Volo.Blogging.Posts;
namespace Volo.Blogging.Pages.Admin.Blogs
namespace Volo.Blogging.Admin.Pages.Blogging.Admin.Blogs
{
public class EditModel : BloggingPageModel
public class EditModel : BloggingAdminPageModel
{
private readonly IBlogAppService _blogAppService;
private readonly IBlogManagementAppService _blogAppService;
private readonly IAuthorizationService _authorization;
[BindProperty(SupportsGet = true)]
@ -23,7 +19,7 @@ namespace Volo.Blogging.Pages.Admin.Blogs
[BindProperty]
public BlogEditViewModel Blog { get; set; } = new BlogEditViewModel();
public EditModel(IBlogAppService blogAppService, IAuthorizationService authorization)
public EditModel(IBlogManagementAppService blogAppService, IAuthorizationService authorization)
{
_blogAppService = blogAppService;
_authorization = authorization;
@ -31,7 +27,7 @@ namespace Volo.Blogging.Pages.Admin.Blogs
public virtual async Task<ActionResult> OnGetAsync()
{
if (!await _authorization.IsGrantedAsync(BloggingPermissions.Blogs.Update))
if (!await _authorization.IsGrantedAsync(BloggingAdminPermissions.Blogs.Update))
{
return Redirect("/");
}
@ -45,7 +41,7 @@ namespace Volo.Blogging.Pages.Admin.Blogs
public virtual async Task<IActionResult> OnPostAsync()
{
await _blogAppService.Update(Blog.Id, new UpdateBlogDto()
await _blogAppService.UpdateAsync(Blog.Id, new UpdateBlogDto()
{
Name = Blog.Name,
ShortName = Blog.ShortName,
@ -74,5 +70,5 @@ namespace Volo.Blogging.Pages.Admin.Blogs
}
}
}
}

16
modules/blogging/src/Volo.Blogging.Web/Pages/Admin/Blogs/Index.cshtml → modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/Index.cshtml

@ -1,10 +1,12 @@
@page
@using Microsoft.AspNetCore.Authorization
@using Volo.Blogging.Admin
@using Volo.Blogging.Admin.Pages.Blogging.Admin.Blogs
@using Volo.Blogging
@using Volo.Blogging.Pages.Blog
@model Volo.Blogging.Pages.Admin.Blogs.IndexModel
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Blogging.Localization
@inherits Volo.Blogging.Admin.Pages.Blogging.BloggingAdminPage
@model IndexModel
@inject IHtmlLocalizer<BloggingResource> L
@inject IAuthorizationService Authorization
@{
@ -12,9 +14,11 @@
}
@section scripts {
<abp-script src="/Pages/Admin/Blogs/index.js" />
<abp-script src="/Pages/Admin/Blogs/create.js" />
<abp-script src="/Pages/Admin/Blogs/edit.js" />
<abp-script-bundle name="@typeof(IndexModel).FullName">
<abp-script src="/Pages/Blogging/Admin/Blogs/index.js" />
<abp-script src="/Pages/Blogging/Admin/Blogs/create.js" />
<abp-script src="/Pages/Blogging/Admin/Blogs/edit.js" />
</abp-script-bundle>
}
<abp-card>
@ -24,7 +28,7 @@
<h2>@L["Blogs"]</h2>
</abp-column>
<abp-column size-md="_6" class="text-right">
@if (await Authorization.IsGrantedAsync(BloggingPermissions.Blogs.Create))
@if (await Authorization.IsGrantedAsync(BloggingAdminPermissions.Blogs.Create))
{
<abp-button icon="plus" text="@L["CreateANewBlog"].Value" button-type="Primary" id="CreateNewBlogButtonId"></abp-button>
}

10
modules/blogging/src/Volo.Blogging.Web/Pages/Admin/Blogs/Index.cshtml.cs → modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/Index.cshtml.cs

@ -1,12 +1,10 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Blogging.Pages.Blog;
namespace Volo.Blogging.Pages.Admin.Blogs
namespace Volo.Blogging.Admin.Pages.Blogging.Admin.Blogs
{
public class IndexModel : BloggingPageModel
public class IndexModel : BloggingAdminPageModel
{
private readonly IAuthorizationService _authorization;
@ -17,7 +15,7 @@ namespace Volo.Blogging.Pages.Admin.Blogs
public virtual async Task<ActionResult> OnGetAsync()
{
if (!await _authorization.IsGrantedAsync(BloggingPermissions.Blogs.Management))
if (!await _authorization.IsGrantedAsync(BloggingAdminPermissions.Blogs.Management))
{
return Redirect("/");
}
@ -25,4 +23,4 @@ namespace Volo.Blogging.Pages.Admin.Blogs
return Page();
}
}
}
}

0
modules/blogging/src/Volo.Blogging.Web/Pages/Admin/Blogs/create.js → modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/create.js

0
modules/blogging/src/Volo.Blogging.Web/Pages/Admin/Blogs/edit.js → modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/edit.js

14
modules/blogging/src/Volo.Blogging.Web/Pages/Admin/Blogs/index.js → modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/index.js

@ -1,8 +1,8 @@
$(function () {
var l = abp.localization.getResource('Blogging');
var _createModal = new abp.ModalManager(abp.appPath + 'Admin/Blogs/Create');
var _editModal = new abp.ModalManager(abp.appPath + 'Admin/Blogs/Edit');
var _createModal = new abp.ModalManager(abp.appPath + 'Blogging/Admin/Blogs/Create');
var _editModal = new abp.ModalManager(abp.appPath + 'Blogging/Admin/Blogs/Edit');
var _dataTable = $('#BlogsTable').DataTable(abp.libs.datatables.normalizeConfiguration({
processing: true,
@ -14,7 +14,7 @@
autoWidth: false,
scrollCollapse: true,
order: [[3, "desc"]],
ajax: abp.libs.datatables.createAjax(volo.blogging.blogs.getList),
ajax: abp.libs.datatables.createAjax(volo.blogging.admin.blogManagement.getList),
columnDefs: [
{
rowAction: {
@ -22,7 +22,7 @@
[
{
text: l('Edit'),
visible: abp.auth.isGranted('Blogging.Blog.Update'),
visible: abp.auth.isGranted('Blogging.Admin.Blog.Update'),
action: function (data) {
_editModal.open({
blogId: data.record.id
@ -31,10 +31,10 @@
},
{
text: l('Delete'),
visible: abp.auth.isGranted('Blogging.Blog.Delete'),
visible: abp.auth.isGranted('Blogging.Admin.Blog.Delete'),
confirmMessage: function (data) { return l('BlogDeletionWarningMessage') },
action: function (data) {
volo.blogging.blogs
volo.blogging.admin.blogManagement
.delete(data.record.id)
.then(function () {
_dataTable.ajax.reload();
@ -79,4 +79,4 @@
_dataTable.ajax.reload();
});
});
});

17
modules/blogging/src/Volo.Blogging.Admin.Web/Pages/BloggingAdminPage.cs

@ -0,0 +1,17 @@
using Microsoft.AspNetCore.Mvc.Localization;
using Microsoft.AspNetCore.Mvc.Razor.Internal;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Blogging.Localization;
namespace Volo.Blogging.Admin.Pages.Blogging
{
public abstract class BloggingAdminPage : AbpPage
{
[RazorInject]
public IHtmlLocalizer<BloggingResource> L { get; set; }
public const string DefaultTitle = "Blogging";
public const int MaxShortContentLength = 200;
}
}

12
modules/blogging/src/Volo.Blogging.Admin.Web/Pages/BloggingAdminPageModel.cs

@ -0,0 +1,12 @@
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
namespace Volo.Blogging.Admin.Pages
{
public abstract class BloggingAdminPageModel : AbpPageModel
{
public BloggingAdminPageModel()
{
ObjectMapperContext = typeof(BloggingAdminWebModule);
}
}
}

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

Loading…
Cancel
Save