Browse Source

Merge branch 'dev' into mongo-global-filters

pull/2375/head
Halil İbrahim Kalkan 7 years ago
committed by GitHub
parent
commit
7cebf1ce6b
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      .github/labeler.yml
  2. 21
      .github/workflows/labeler.yml
  3. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
  4. 2
      common.props
  5. 35
      docs/cs/Best-Practices/PostgreSQL-Integration.md
  6. 4
      docs/cs/CLI.md
  7. 74
      docs/cs/EntityFrameworkCore-PostgreSQL-Integration.md
  8. 2
      docs/cs/Getting-Started-Angular-Template.md
  9. 113
      docs/cs/Getting-Started-AspNetCore-Application.md
  10. 10
      docs/cs/Index.md
  11. 23
      docs/cs/docs-nav.json
  12. BIN
      docs/cs/images/authorization-new-permission-ui-hierarcy.png
  13. BIN
      docs/cs/images/authorization-new-permission-ui-localized.png
  14. BIN
      docs/cs/images/authorization-new-permission-ui.png
  15. BIN
      docs/cs/images/create-aspnet-core-application.png
  16. BIN
      docs/cs/images/create-new-aspnet-core-application-v2.png
  17. BIN
      docs/cs/images/select-empty-web-application-v2.png
  18. 18
      docs/en/CLI.md
  19. 0
      docs/en/EntityFrameworkCore-PostgreSQL-Integration.md
  20. 93
      docs/en/Modules/Docs.md
  21. 2
      docs/en/docs-nav.json
  22. BIN
      docs/en/images/docs-section-ui.png
  23. 2
      docs/pt-BR/docs-nav.json
  24. 0
      docs/zh-Hans/EntityFrameworkCore-PostgreSQL-Integration.md
  25. 10
      docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md
  26. 2
      docs/zh-Hans/docs-nav.json
  27. 6
      framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/MultipleClaimAction.cs
  28. 1
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/CachedApplicationConfigurationClient.cs
  29. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteLocalizationContributor.cs
  30. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemotePermissionChecker.cs
  31. 50
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteTenantStore.cs
  32. 1
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/cs.json
  33. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Views/Error/Default.cshtml
  34. 29
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs
  35. 4
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationController.cs
  36. 14
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationScriptController.cs
  37. 4
      framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs
  38. 79
      framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs
  39. 3
      framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/IAbpRequestLocalizationOptionsProvider.cs
  40. 27
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptor.cs
  41. 15
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingManager.cs
  42. 2
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditLogSaveHandle.cs
  43. 2
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditingStore.cs
  44. 7
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/SimpleLogAuditingStore.cs
  45. 28
      framework/src/Volo.Abp.Authorization/Microsoft/AspNetCore/Authorization/AbpAuthorizationServiceExtensions.cs
  46. 7
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AuthorizationInterceptor.cs
  47. 4
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionChecker.cs
  48. 2
      framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs
  49. 5
      framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/IJobQueueManager.cs
  50. 31
      framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueueManager.cs
  51. 7
      framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/RabbitMqBackgroundJobManager.cs
  52. 6
      framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs
  53. 34
      framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/IBackgroundJobStore.cs
  54. 35
      framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/InMemoryBackgroundJobStore.cs
  55. 1
      framework/src/Volo.Abp.Castle.Core/Volo.Abp.Castle.Core.csproj
  56. 2
      framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/AbpCastleCoreModule.cs
  57. 15
      framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/AbpAsyncDeterminationInterceptor.cs
  58. 89
      framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpInterceptorAdapter.cs
  59. 67
      framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapter.cs
  60. 48
      framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapterBase.cs
  61. 27
      framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapterWithReturnValue.cs
  62. 36
      framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAsyncAbpInterceptorAdapter.cs
  63. 2
      framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj
  64. 5
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs
  65. 23
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs
  66. 11
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliUrls.cs
  67. 5
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs
  68. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs
  69. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GetSourceCommand.cs
  70. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/HelpCommand.cs
  71. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs
  72. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LogoutCommand.cs
  73. 6
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs
  74. 156
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SuiteCommand.cs
  75. 31
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs
  76. 28
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Http/CliHttpClient.cs
  77. 40
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/AbpIoApiKeyService.cs
  78. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs
  79. 22
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/RemoteServiceExceptionHandler.cs
  80. 8
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/CmdHelper.cs
  81. 34
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/GlobalToolHelper.cs
  82. 51
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/PlatformHelper.cs
  83. 7
      framework/src/Volo.Abp.Cli/Properties/launchSettings.json
  84. 12
      framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/AbpInterceptor.cs
  85. 2
      framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/IAbpInterceptor.cs
  86. 2
      framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/IAbpMethodInvocation.cs
  87. 6
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo.Abp.Ddd.Application.Contracts.csproj
  88. 22
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/AbpDddApplicationContractsModule.cs
  89. 3
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/ILimitedResultRequest.cs
  90. 30
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/LimitedResultRequestDto.cs
  91. 9
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/AbpDddResource.cs
  92. 6
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/en.json
  93. 6
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/tr.json
  94. 6
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/zh-Hans.json
  95. 70
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/BasicRepositoryBase.cs
  96. 42
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IBasicRepository.cs
  97. 31
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IReadOnlyBasicRepository.cs
  98. 13
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IRepository.cs
  99. 55
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryBase.cs
  100. 73
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs

11
.github/labeler.yml

@ -1,4 +1,15 @@
ui-angular:
- npm/ng-packs/*
- npm/ng-packs/**/*
- npm/ng-packs/**/**/*
- npm/ng-packs/**/**/**/*
- npm/ng-packs/**/**/**/**/*
- npm/ng-packs/**/**/**/**/**/*
- templates/app/angular/*
- templates/app/angular/**/*
- templates/app/angular/**/**/*
- templates/app/angular/**/**/**/*
- templates/module/angular/*
- templates/module/angular/**/*
- templates/module/angular/**/**/*
- templates/module/angular/**/**/**/*

21
.github/workflows/labeler.yml

@ -1,17 +1,12 @@
name: "Pull Request Labeler"
name: Pull request labeler
on:
pull_request:
paths:
- npm/ng-packs/**/*
- templates/app/angular/**/*
- templates/module/angular/**/*
branches:
- master
- dev
schedule:
- cron: '0 12 */1 * *'
jobs:
labeler:
runs-on: ubuntu-18.04
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v2
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
- uses: paulfantom/periodic-labeler@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REPOSITORY: ${{ github.repository }}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json

@ -25,6 +25,7 @@
"Volo.AbpIo.Commercial:010004": "Can not find the specified user! The user must have already registered.",
"MyOrganizations": "My organizations",
"ApiKey": "API key",
"UserNameNotFound": "There is no user with username {0}"
"UserNameNotFound": "There is no user with username {0}",
"SuccessfullyAddedToNewsletter": "Thanks you for subscribing to our newsletter!"
}
}

2
common.props

@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<LangVersion>latest</LangVersion>
<Version>1.1.1</Version>
<Version>2.0.0</Version>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<PackageIconUrl>https://abp.io/assets/abp_nupkg.png</PackageIconUrl>
<PackageProjectUrl>https://abp.io</PackageProjectUrl>

35
docs/cs/Best-Practices/PostgreSQL-Integration.md

@ -1,35 +0,0 @@
## Entity Framework Core PostgreSQL integrace
> Podívejte se na [Entity Framework Core integrační dokument](../Entity-Framework-Core.md) pro základy integrace EF Core.
### Aktualizace projektu EntityFrameworkCore
- V projektu `Acme.BookStore.EntityFrameworkCore` nahraďte balík `Volo.Abp.EntityFrameworkCore.SqlServer` za `Volo.Abp.EntityFrameworkCore.PostgreSql`
- Aktualizace pro použití PostgreSQL v `BookStoreEntityFrameworkCoreModule`
- Nahraďte `AbpEntityFrameworkCoreSqlServerModule` za `AbpEntityFrameworkCorePostgreSqlModule`
- Nahraďte `options.UseSqlServer()` za `options.UsePostgreSql()`
- V jiných projektech aktualizujte PostgreSQL connection string v nezbytných `appsettings.json` souborech
#### Odstranění stávajících migrací
Smažte všechny stavající migrační soubory (včetně `DbContextModelSnapshot`)
![postgresql-delete-initial-migrations](images/postgresql-delete-initial-migrations.png)
#### Znovu vygenerujte počáteční migraci & aktualizujte databázi
Nastavte správný spouštěcí projekt (obvykle web projekt),
Otevřete **Package Manager Console** (Tools -> Nuget Package Manager -> Package Manager Console), zvolte `Acme.BookStore.EntityFrameworkCore.DbMigrations` jako **Default project** a proveďte následující příkaz:
Proveďte příkaz `Add-Migration`:
````
PM> Add-Migration Initial
````
Poté proveďte příkaz `Update-Database` k aktualizaci schématu databáze:
````
PM> Update-Database
````
![postgresql-update-database](images/postgresql-update-database.png)

4
docs/cs/CLI.md

@ -46,11 +46,13 @@ abp new Acme.BookStore
* `--tiered`: Vytvoří stupňovité řešení, kde jsou vrstvy Web a Http API fyzicky odděleny. Pokud není uvedeno, tak vytvoří vrstvené řešení, které je méně složité a vhodné pro většinu scénářů.
* `angular`: Angular. Pro tuto šablonu jsou dostupné dodatečné možnosti:
* `--separate-identity-server`: Oddělí identity server aplikaci od API host aplikace. Pokud není uvedeno, bude na straně serveru jediný koncový bod.
* `none`: Bez UI. Pro tuto šablonu jsou dostupné dodatečné možnosti:
* `--separate-identity-server`: Oddělí identity server aplikaci od API host aplikace. Pokud není uvedeno, bude na straně serveru jediný koncový bod.
* `--database-provider` nebo `-d`: Určuje poskytovatele databáze. Výchozí poskytovatel je `ef`. Dostupní poskytovatelé:
* `ef`: Entity Framework Core.
* `mongodb`: MongoDB.
* `module`: [Šablona modulu](Startup-Templates/Module.md). Dodatečné možnosti:
* `--no-ui`: Určuje nezahrnutí uživatelského rozhraní. Umožňuje vytvořit moduly pouze pro služby (a.k.a. mikroslužby - bez uživatelského rozhraní).
* `--no-ui`: Určuje nezahrnutí uživatelského rozhraní. Umožňuje vytvořit moduly pouze pro služby (a.k.a. mikroslužby - bez uživatelského rozhraní).
* `--output-folder` nebo `-o`: Určuje výstupní složku. Výchozí hodnota je aktuální adresář.
* `--version` nebo `-v`: Určuje verzi ABP & šablony. Může to být [štítek vydání](https://github.com/abpframework/abp/releases) nebo [název větve](https://github.com/abpframework/abp/branches). Pokud není uvedeno, používá nejnovější vydání. Většinou budete chtít použít nejnovější verzi.

74
docs/cs/EntityFrameworkCore-PostgreSQL-Integration.md

@ -0,0 +1,74 @@
## Entity Framework Core PostgreSQL integrace
> Podívejte se na [Entity Framework Core integrační dokument](../Entity-Framework-Core.md) pro základy integrace EF Core.
### Aktualizace projektu EntityFrameworkCore
- V projektu `Acme.BookStore.EntityFrameworkCore` nahraďte balík `Volo.Abp.EntityFrameworkCore.SqlServer` za `Volo.Abp.EntityFrameworkCore.PostgreSql`
- Aktualizace pro použití PostgreSQL v `BookStoreEntityFrameworkCoreModule`
- Nahraďte `AbpEntityFrameworkCoreSqlServerModule` za `AbpEntityFrameworkCorePostgreSqlModule`
- Nahraďte `options.UseSqlServer()` za `options.UsePostgreSql()`
- V jiných projektech aktualizujte PostgreSQL connection string v nezbytných `appsettings.json` souborech
- Více informací v [PostgreSQL connection strings](https://www.connectionstrings.com/postgresql/), v tomto dokumentu věnujte pozornost sekci `Npgsql`
### Aktualizace projektu EntityFrameworkCore.DbMigrations
- Aktualizace pro použití PostgreSQL v `XXXMigrationsDbContextFactory`
- Nahraďte `new DbContextOptionsBuilder<XXXMigrationsDbContext>().UseSqlServer()` za `new DbContextOptionsBuilder<XXXMigrationsDbContext>().UseNpgsql()`
### Odstranění stávajících migrací
Smažte všechny stavající migrační soubory (včetně `DbContextModelSnapshot`)
![postgresql-delete-initial-migrations](images/postgresql-delete-initial-migrations.png)
### Znovu vygenerujte počáteční migraci
Nastavte správný spouštěcí projekt (obvykle web projekt)
![set-as-startup-project](../images/set-as-startup-project.png)
Otevřete **Package Manager Console** (Tools -> Nuget Package Manager -> Package Manager Console), zvolte `.EntityFrameworkCore.DbMigrations` jako **Default project** a proveďte následující příkaz:
Proveďte příkaz `Add-Migration`:
````
PM> Add-Migration Initial
````
### Aktualizace databáze
K vytvoření databáze máte dvě možnosti.
#### Použití DbMigrator aplikace
Řešení obsahuje konzolovou aplikaci (v tomto příkladu nazvanou `Acme.BookStore.DbMigrator`), která může vytvářet databáze, aplikovat migrace a vkládat seed data. Je užitečná jak pro vývojové, tak pro produkční prostředí.
> Projekt `.DbMigrator` má vlastní `appsettings.json`. Takže pokud jste změnili connection string uvedený výše, musíte změnit také tento.
Klikněte pravým na projekt `.DbMigrator` a vyberte **Set as StartUp Project**:
![set-as-startup-project](images/set-as-startup-project.png)
Zmáčkněte F5 (nebo Ctrl+F5) ke spuštění aplikace. Výstup bude vypadat následovně:
![set-as-startup-project](images/db-migrator-app.png)
#### Použití EF Core Update-Database příkazu
Ef Core má `Update-Database` příkaz, který v případě potřeby vytvoří databázi a aplikuje čekající migrace.
Nastavte správný spouštěcí projekt (obvykle web projekt)
![set-as-startup-project](../images/set-as-startup-project.png)
Otevřete **Package Manager Console** (Tools -> Nuget Package Manager -> Package Manager Console), vyberte projekt `.EntityFrameworkCore.DbMigrations` jako **Default Project** and spusťte následující příkaz:
````
PM> Update-Database
````
Dojde k vytvoření nové databáze na základě nakonfigurovaného connection stringu.
![postgresql-update-database](images/postgresql-update-database.png)
> Použití nástroje `.DbMigrator` je doporučený způsob, jelikož zároveň vloží seed data nutné k správnému běhu webové aplikace.

2
docs/cs/Getting-Started-Angular-Template.md

@ -75,7 +75,7 @@ Zmáčkněte F5 (nebo Ctrl+F5) ke spuštění aplikace. Výstup by měl být pod
#### Použití příkazu EF Core Update-Database
Ef Core máš příkaz `Update-Database`, který v případě potřeby vytvoří databázi a aplikuje čekající migrace. Klikněte pravým na projekt `.Web` a zvolte **Set as StartUp Project**:
Ef Core máš příkaz `Update-Database`, který v případě potřeby vytvoří databázi a aplikuje čekající migrace. Klikněte pravým na projekt `.HttpApi.Host` a zvolte **Set as StartUp Project**:
![set-as-startup-project](images/set-as-startup-project.png)

113
docs/cs/Getting-Started-AspNetCore-Application.md

@ -4,15 +4,17 @@ Tento tutoriál vysvětluje jak začít s ABP z ničeho s minimem závislostí.
## Tvorba nového projektu
1. Vytvořte novou prázdnou AspNet Core Web aplikaci ve Visual Studio:
1. Vytvořte novou AspNet Core Web aplikaci ve Visual Studio 2019 (16.3.0+):
![](images/create-new-aspnet-core-application.png)
![](images/create-new-aspnet-core-application-v2.png)
2. Zvolte prázdnou šablonu
2. Nakonfigurujte váš nový projekt:
![](images/select-empty-web-application.png)
![](images/select-empty-web-application-v2.png)
Můžete zvolit i jinou šablonu, ale pro demonstraci je lepší čístý projekt.
3. Potvrďte kliknutím na tlačítko vytvořit
![create-aspnet-core-application](images/create-aspnet-core-application.png)
## Instalace Volo.Abp.AspNetCore.Mvc balíku
@ -28,10 +30,8 @@ ABP je modulární framework a proto vyžaduje **spouštěcí (kořenový) modul
````C#
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Volo.Abp;
using Volo.Abp.AspNetCore.Modularity;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Modularity;
@ -40,7 +40,8 @@ namespace BasicAspNetCoreApplication
[DependsOn(typeof(AbpAspNetCoreMvcModule))]
public class AppModule : AbpModule
{
public override void OnApplicationInitialization(ApplicationInitializationContext context)
public override void OnApplicationInitialization(
ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
@ -49,8 +50,14 @@ namespace BasicAspNetCoreApplication
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
}
app.UseMvcWithDefaultRoute();
app.UseStaticFiles();
app.UseRouting();
app.UseMvcWithDefaultRouteAndArea();
}
}
}
@ -58,7 +65,7 @@ namespace BasicAspNetCoreApplication
``AppModule`` je dobrý název pro spouštěcí modul aplikace.
ABP balíky definují modulové třídy a modul může mít závislost na jiný modul. V kódu výše, náš ``AppModule`` má závislost na ``AbpAspNetCoreMvcModule`` (definován v balíku Volo.Abp.AspNetCore.Mvc). Je běžné přidat ``DependsOn`` atribute po instalaci nového ABP NuGet balíku.
ABP balíky definují modulové třídy a modul může mít závislost na jiném. V kódu výše, ``AppModule`` má závislost na ``AbpAspNetCoreMvcModule`` (definován v balíku [Volo.Abp.AspNetCore.Mvc](https://www.nuget.org/packages/Volo.Abp.AspNetCore.Mvc)). Je běžné přidat ``DependsOn`` atribute po instalaci nového ABP NuGet balíku.
Místo třídy Startup, konfigurujeme ASP.NET Core pipeline v této modulové třídě.
@ -67,7 +74,6 @@ Místo třídy Startup, konfigurujeme ASP.NET Core pipeline v této modulové t
V dalším kroku upravíme Startup třídu k integraci ABP modulového systému:
````C#
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
@ -75,11 +81,9 @@ namespace BasicAspNetCoreApplication
{
public class Startup
{
public IServiceProvider ConfigureServices(IServiceCollection services)
public void ConfigureServices(IServiceCollection services)
{
services.AddApplication<AppModule>();
return services.BuildServiceProviderFromFactory();
}
public void Configure(IApplicationBuilder app)
@ -88,41 +92,19 @@ namespace BasicAspNetCoreApplication
}
}
}
````
Změnili jsme metodu ``ConfigureServices`` aby vracela ``IServiceProvider`` místo ``void``. Tato změna nám dovoluje nahradit AspNet Core vkládání závislostí za jiný framework (více v sekci Autofac integrace níže). ``services.AddApplication<AppModule>()`` přidává všechny služby definované ve všech modulech počínaje ``AppModule``.
``services.AddApplication<AppModule>()`` přidává všechny služby definované ve všech modulech počínaje od ``AppModule``.
Volání ``app.InitializeApplication()`` v metodě ``Configure`` inicializuje a spustí aplikaci.
``app.InitializeApplication()`` v metodě ``Configure`` inicializuje a spustí aplikaci.
## Ahoj světe!
## Spusťte aplikaci!
Aplikace výše zatím nic nedělá. Pojďme proto vytvořit MVC controller, který už něco dělá:
````C#
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
namespace BasicAspNetCoreApplication.Controllers
{
public class HomeController : AbpController
{
public IActionResult Index()
{
return Content("Hello World!");
}
}
}
````
Jakmile spustíte aplikaci, uvidíte na stránce zprávu "Hello World!".
Odvození ``HomeController`` od ``AbpController`` místo standardní třídy ``Controller``. Toto není vyžadováno, ale třída ``AbpController`` má užitečné základní vlastnosti a metody, které usnadňují vývoj.
To je vše! Spusťte aplikaci, bude fungovat podle očekávání.
## Použití Autofac jako frameworku pro vkládání závislostí
Ačkoliv je AspNet Core systém pro vkládání závíslostí (DI) skvělý pro základní požadavky, Autofac poskytuje pokročilé funkce jako injekce vlastností nebo záchyt metod, které jsou v ABP užity k provádění pokročilých funkcí frameworku.
Ačkoliv je AspNet Core systém pro vkládání závíslostí (DI) dostatečný pro základní požadavky, [Autofac](https://autofac.org/) poskytuje pokročilé funkce jako injekce vlastností nebo záchyt metod, které jsou v ABP užity k provádění pokročilých funkcí frameworku.
Nahrazení AspNet Core DI systému za Autofac a integrace s ABP je snadná.
@ -143,40 +125,29 @@ public class AppModule : AbpModule
}
````
3. Změníme řádek ``services.AddApplication<AppModule>();`` v třídě ``Startup`` následovně:
````C#
services.AddApplication<AppModule>(options =>
{
options.UseAutofac(); // Integrace s Autofac
});
````
4. Upravíme `Program.cs` aby nepoužíval metodu `WebHost.CreateDefaultBuilder()` jelikož ta používá výchozí DI kontejner:
3. Upravíme `Program.cs` aby používal Autofac:
````csharp
public class Program
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
namespace BasicAspNetCoreApplication
{
public static void Main(string[] args)
public class Program
{
/*
https://github.com/aspnet/AspNetCore/issues/4206#issuecomment-445612167
CurrentDirectoryHelpers exists in: \framework\src\Volo.Abp.AspNetCore.Mvc\Microsoft\AspNetCore\InProcess\CurrentDirectoryHelpers.cs
Will remove CurrentDirectoryHelpers.cs when upgrade to ASP.NET Core 3.0.
*/
CurrentDirectoryHelpers.SetCurrentDirectory();
BuildWebHostInternal(args).Run();
}
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IWebHost BuildWebHostInternal(string[] args) =>
new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIIS()
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseAutofac(); // Přidejte tento řádek
}
}
````

10
docs/cs/Index.md

@ -4,18 +4,12 @@ ABP je **open source aplikační framework** se zaměřením na vývoj webových
K procházení dokumentace využijte navigační nabídky vlevo.
## Stav projektu
ABP je **novou generací** open source frameworku [ASP.NET Boilerplate](https://aspnetboilerplate.com/). V současné době je v náhledové fázi a není připraven k ostrému nasazení. Na dokumentaci se stále pracuje a ještě zdaleka není dokončena.
Pro aplikace na krátkodobé a ostré nasazení je doporučeno použít [ASP.NET Boilerplate](https://aspnetboilerplate.com/) framework, který je bohatý na funkce, vyspělý, aktivně udržovaný a aktuální.
## Začínáme
Nejsnazší cestou jak začít nový projekt s ABP je užití startovací šablony:
* [ASP.NET Core MVC (Razor Pages) UI Šablona](Getting-Started-AspNetCore-MVC-Template.md)
* [Angular UI Šablona](Getting-Started-Angular-Template.md)
* [ASP.NET Core MVC (Razor Pages) UI Počáteční Šablona](Getting-Started-AspNetCore-MVC-Template.md)
* [Angular UI Počáteční Šablona](Getting-Started-Angular-Template.md)
Pokud chcete začít od nuly (s prázdným projektem) tak manuálně nainstalujte ABP Framework s pomocí následujících tutoriálů:

23
docs/cs/docs-nav.json

@ -56,6 +56,10 @@
{
"text": "Základy",
"items": [
{
"text": "Konfigurace",
"path": "Configuration.md"
},
{
"text": "Vkládání závislostí",
"path": "Dependency-Injection.md",
@ -82,16 +86,19 @@
"text": "Validace"
},
{
"text": "Autorizace"
"text": "Autorizace",
"path": "Authorization.md"
},
{
"text": "Ukládání do mezipaměti"
"text": "Ukládání do mezipaměti",
"path": "Caching.md"
},
{
"text": "Audit"
},
{
"text": "Správa nastavení"
"text": "Nastavení",
"path": "Settings.md"
}
]
},
@ -114,6 +121,14 @@
{
"text": "Služby",
"items": [
{
"text": "Současný uživatel",
"path": "CurrentUser.md"
},
{
"text": "Mapování objekt na objekt",
"path": "Object-To-Object-Mapping.md"
},
{
"text": "Serializace objektu"
},
@ -249,7 +264,7 @@
"items": [
{
"text": "PostgreSQL integrace",
"path": "Best-Practices/PostgreSQL-Integration.md"
"path": "EntityFrameworkCore-PostgreSQL-Integration.md"
}
]
},

BIN
docs/cs/images/authorization-new-permission-ui-hierarcy.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

BIN
docs/cs/images/authorization-new-permission-ui-localized.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
docs/cs/images/authorization-new-permission-ui.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
docs/cs/images/create-aspnet-core-application.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

BIN
docs/cs/images/create-new-aspnet-core-application-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

BIN
docs/cs/images/select-empty-web-application-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

18
docs/en/CLI.md

@ -128,6 +128,24 @@ abp update [options]
* `--npm`: Only updates NPM packages.
* `--nuget`: Only updates NuGet packages.
### login
Some features of the CLI requires to be logged in to abp.io platform. To login with your username write
```bash
abp login <username>
```
Notice that, a new login with an already active session, will kill the previous session and creates a new one.
### logout
Logs you out by removing the session token from your computer.
```
abp logout
```
### help
Writes basic usage information of the CLI.

0
docs/en/Best-Practices/PostgreSQL-Integration.md → docs/en/EntityFrameworkCore-PostgreSQL-Integration.md

93
docs/en/Modules/Docs.md

@ -408,12 +408,101 @@ public class Person
```
~~~
As an example you can see ABP Framework documentation:
[https://github.com/abpframework/abp/blob/master/docs/en/](https://github.com/abpframework/abp/blob/master/docs/en/)
#### Conditional sections feature (Using Scriban)
Docs module uses [Scriban](<https://github.com/lunet-io/scriban/tree/master/doc> ) for conditionally show or hide some parts of a document. In order to use that feature, you have to create a JSON file as **Parameter document** per every language. It will contain all the key-values, as well as their display names.
For example, [en/docs-params.json](https://github.com/abpio/abp-commercial-docs/blob/master/en/docs-params.json):
```json
{
"parameters": [{
"name": "UI",
"displayName": "UI",
"values": {
"MVC": "MVC / Razor Pages",
"NG": "Angular"
}
},
{
"name": "DB",
"displayName": "Database",
"values": {
"EF": "Entity Framework Core",
"Mongo": "MongoDB"
}
},
{
"name": "Tiered",
"displayName": "Tiered",
"values": {
"No": "Not Tiered",
"Yes": "Tiered"
}
}]
}
```
Since not every single document in your projects may not have sections or may not need all of those parameters, you have to declare which of those parameters will be used for sectioning the document, as a JSON block anywhere on the document.
For example [Getting-Started.md](https://github.com/abpio/abp-commercial-docs/blob/master/en/Getting-Started.md):
```
.....
​````json
//[doc-params]
{
"UI": ["MVC","NG"],
"DB": ["EF", "Mongo"],
"Tiered": ["Yes", "No"]
}
​````
........
```
This section will be automatically deleted during render. And f course, those key values must match with the ones in **Parameter document**.
![Interface](..\images\docs-section-ui.png)
Now you can use **Scriban** syntax to create sections in your document.
For example:
````
{{ if UI == "NG" }}
* `-u` argument specifies the UI framework, `angular` in this case.
{{ end }}
{{ if DB == "Mongo" }}
* `-d` argument specifies the database provider, `mongodb` in this case.
{{ end }}
{{ if Tiered == "Yes" }}
* `--tiered` argument is used to create N-tiered solution where authentication server, UI and API layers are physically separated.
{{ end }}
````
You can also use variables in a text, adding **_Value** postfix to its key:
````
This document assumes that you prefer to use **{{ UI_Value }}** as the UI framework and **{{ DB_Value }}** as the database provider.
````
**IMPORTANT NOTICE**: Scriban uses "{{" and "}}" for syntax. Therefore, you must use escape blocks if you are going to use those in your document (an Angular document, for example). See [Scriban docs](<https://github.com/lunet-io/scriban/blob/master/doc/language.md#13-escape-block> ) for more information.
### 8- Creating the Navigation Document
Navigation document is the main menu of the documents page. It is located on the left side of the page. It is a `JSON` file. Take a look at the below sample navigation document to understand the structure.

2
docs/en/docs-nav.json

@ -265,7 +265,7 @@
"items": [
{
"text": "PostgreSQL Integration",
"path": "Best-Practices/PostgreSQL-Integration.md"
"path": "EntityFrameworkCore-PostgreSQL-Integration.md"
}
]
},

BIN
docs/en/images/docs-section-ui.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

2
docs/pt-BR/docs-nav.json

@ -249,7 +249,7 @@
"items": [
{
"text": "Integração do PostgreSQL",
"path": "Best-Practices/PostgreSQL-Integration.md"
"path": "EntityFrameworkCore-PostgreSQL-Integration.md"
}
]
},

0
docs/zh-Hans/Best-Practices/PostgreSQL-Integration.md → docs/zh-Hans/EntityFrameworkCore-PostgreSQL-Integration.md

10
docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md

@ -225,7 +225,7 @@ using Volo.Abp.Application.Services;
namespace Acme.BookStore
{
public interface IBookAppService :
IAsyncCrudAppService< //定义了CRUD方法
ICrudAppService< //定义了CRUD方法
BookDto, //用来展示书籍
Guid, //Book实体的主键
PagedAndSortedResultRequestDto, //获取书籍的时候用于分页和排序
@ -238,8 +238,8 @@ namespace Acme.BookStore
````
* 框架定义应用程序服务的接口<u>不是必需的</u>. 但是,它被建议作为最佳实践.
* `IAsyncCrudAppService`定义了常见的**CRUD**方法:`GetAsync`,`GetListAsync`,`CreateAsync`,`UpdateAsync`和`DeleteAsync`. 你可以从空的`IApplicationService`接口继承并手动定义自己的方法.
* `IAsyncCrudAppService`有一些变体, 你可以在每个方法中使用单独的DTO,也可以分别单独指定.
* `ICrudAppService`定义了常见的**CRUD**方法:`GetAsync`,`GetListAsync`,`CreateAsync`,`UpdateAsync`和`DeleteAsync`. 你可以从空的`IApplicationService`接口继承并手动定义自己的方法.
* `ICrudAppService`有一些变体, 你可以在每个方法中使用单独的DTO,也可以分别单独指定.
#### BookAppService
@ -255,7 +255,7 @@ using Volo.Abp.Domain.Repositories;
namespace Acme.BookStore
{
public class BookAppService :
AsyncCrudAppService<Book, BookDto, Guid, PagedAndSortedResultRequestDto,
CrudAppService<Book, BookDto, Guid, PagedAndSortedResultRequestDto,
CreateUpdateBookDto, CreateUpdateBookDto>,
IBookAppService
{
@ -268,7 +268,7 @@ namespace Acme.BookStore
}
````
* `BookAppService`继承了`AsyncCrudAppService<...>`.`AsyncCrudAppService<...>`实现了上面定义的CRUD方法.
* `BookAppService`继承了`CrudAppService<...>`.实现了上面定义的CRUD方法.
* `BookAppService`注入`IRepository <Book,Guid>`,这是`Book`实体的默认仓储. ABP自动为每个聚合根(或实体)创建默认仓储. 请参阅[仓储文档](../../Repositories.md)
* `BookAppService`使用`IObjectMapper`将`Book`对象转换为`BookDto`对象, 将`CreateUpdateBookDto`对象转换为`Book`对象. 启动模板使用[AutoMapper](http://automapper.org/)库作为对象映射提供程序. 你之前定义了映射, 因此它将按预期工作.

2
docs/zh-Hans/docs-nav.json

@ -254,7 +254,7 @@
"items": [
{
"text": "PostgreSQL 集成",
"path": "Best-Practices/PostgreSQL-Integration.md"
"path": "EntityFrameworkCore-PostgreSQL-Integration.md"
}
]
},

6
framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/MultipleClaimAction.cs

@ -14,7 +14,11 @@ namespace Volo.Abp.AspNetCore.Authentication.OAuth.Claims
public override void Run(JsonElement userData, ClaimsIdentity identity, string issuer)
{
var prop = userData.GetProperty(ValueType);
JsonElement prop;
if (!userData.TryGetProperty(ValueType, out prop))
return;
if (prop.ValueKind == JsonValueKind.Null)
{
return;

1
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/CachedApplicationConfigurationClient.cs

@ -7,6 +7,7 @@ using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.Client.DynamicProxying;
using Volo.Abp.Threading;
using Volo.Abp.Users;
namespace Volo.Abp.AspNetCore.Mvc.Client

4
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteLocalizationContributor.cs

@ -55,9 +55,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
private Dictionary<string, string> GetResourceOrNull()
{
var applicationConfigurationDto = AsyncHelper.RunSync(
() => _applicationConfigurationClient.GetAsync()
);
var applicationConfigurationDto = AsyncHelper.RunSync(() => _applicationConfigurationClient.GetAsync());
var resource = applicationConfigurationDto
.Localization.Values

4
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemotePermissionChecker.cs

@ -21,10 +21,10 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
return configuration.Auth.GrantedPolicies.ContainsKey(name);
}
public Task<bool> IsGrantedAsync(ClaimsPrincipal claimsPrincipal, string name)
public async Task<bool> IsGrantedAsync(ClaimsPrincipal claimsPrincipal, string name)
{
/* This provider always works for the current principal. */
return IsGrantedAsync(name);
return await IsGrantedAsync(name);
}
}
}

50
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteTenantStore.cs

@ -85,12 +85,58 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
public TenantConfiguration Find(string name)
{
return AsyncHelper.RunSync(() => FindAsync(name));
var cacheKey = CreateCacheKey(name);
var httpContext = HttpContextAccessor?.HttpContext;
if (httpContext != null && httpContext.Items[cacheKey] is TenantConfiguration tenantConfiguration)
{
return tenantConfiguration;
}
tenantConfiguration = Cache.GetOrAdd(
cacheKey,
() => AsyncHelper.RunSync(async () => CreateTenantConfiguration(await Proxy.Service.FindTenantByNameAsync(name))),
() => new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow =
TimeSpan.FromMinutes(5) //TODO: Should be configurable.
}
);
if (httpContext != null)
{
httpContext.Items[cacheKey] = tenantConfiguration;
}
return tenantConfiguration;
}
public TenantConfiguration Find(Guid id)
{
return AsyncHelper.RunSync(() => FindAsync(id));
var cacheKey = CreateCacheKey(id);
var httpContext = HttpContextAccessor?.HttpContext;
if (httpContext != null && httpContext.Items[cacheKey] is TenantConfiguration tenantConfiguration)
{
return tenantConfiguration;
}
tenantConfiguration = Cache.GetOrAdd(
cacheKey,
() => AsyncHelper.RunSync(async () => CreateTenantConfiguration(await Proxy.Service.FindTenantByIdAsync(id))),
() => new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow =
TimeSpan.FromMinutes(5) //TODO: Should be configurable.
}
);
if (httpContext != null)
{
httpContext.Items[cacheKey] = tenantConfiguration;
}
return tenantConfiguration;
}
protected virtual TenantConfiguration CreateTenantConfiguration(FindTenantResultDto tenantResultDto)

1
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/cs.json

@ -6,6 +6,7 @@
"Switch": "změnit",
"Name": "Název",
"SwitchTenantHint": "Nechte pole prázdné ke změně na hostitele.",
"SwitchTenant": "Změnit tenant",
"NotSelected": "Nevybrán"
}
}

4
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Views/Error/Default.cshtml

@ -2,8 +2,8 @@
@using System.Collections.Generic
@using Localization.Resources.AbpUi
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Pages.Error
@model AbpErrorPageModel
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Views.Error
@model AbpErrorViewModel
@inject IHtmlLocalizer<AbpUiResource> L
@{
var errorMessage = Model.ErrorInfo.Message;

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

@ -6,6 +6,7 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Volo.Abp.Application.Services;
using Volo.Abp.Authorization;
using Volo.Abp.Features;
@ -34,7 +35,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
IAuthorizationService authorizationService,
ICurrentUser currentUser,
ISettingProvider settingProvider,
SettingDefinitionManager settingDefinitionManager,
ISettingDefinitionManager settingDefinitionManager,
IFeatureDefinitionManager featureDefinitionManager,
ILanguageProvider languageProvider)
{
@ -76,23 +77,35 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
protected virtual async Task<ApplicationAuthConfigurationDto> GetAuthConfigAsync()
{
Logger.LogDebug("Executing AbpApplicationConfigurationAppService.GetAuthConfigAsync()");
var authConfig = new ApplicationAuthConfigurationDto();
foreach (var policyName in await _abpAuthorizationPolicyProvider.GetPoliciesNamesAsync())
var policyNames = await _abpAuthorizationPolicyProvider.GetPoliciesNamesAsync();
Logger.LogDebug($"GetPoliciesNamesAsync returns {policyNames.Count} items.");
foreach (var policyName in policyNames)
{
authConfig.Policies[policyName] = true;
Logger.LogDebug($"_authorizationService.IsGrantedAsync? {policyName}");
if (await _authorizationService.IsGrantedAsync(policyName))
{
authConfig.GrantedPolicies[policyName] = true;
}
}
Logger.LogDebug("Executed AbpApplicationConfigurationAppService.GetAuthConfigAsync()");
return authConfig;
}
protected virtual async Task<ApplicationLocalizationConfigurationDto> GetLocalizationConfigAsync()
{
Logger.LogDebug("Executing AbpApplicationConfigurationAppService.GetLocalizationConfigAsync()");
var localizationConfig = new ApplicationLocalizationConfigurationDto();
localizationConfig.Languages.AddRange(await _languageProvider.GetLanguagesAsync());
@ -115,12 +128,14 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
localizationConfig.CurrentCulture = GetCurrentCultureInfo();
Logger.LogDebug("Executed AbpApplicationConfigurationAppService.GetLocalizationConfigAsync()");
return localizationConfig;
}
private static CurrentCultureDto GetCurrentCultureInfo()
{
return new CurrentCultureDto
return new CurrentCultureDto
{
Name = CultureInfo.CurrentUICulture.Name,
DisplayName = CultureInfo.CurrentUICulture.DisplayName,
@ -145,6 +160,8 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
private async Task<ApplicationSettingConfigurationDto> GetSettingConfigAsync()
{
Logger.LogDebug("Executing AbpApplicationConfigurationAppService.GetSettingConfigAsync()");
var result = new ApplicationSettingConfigurationDto
{
Values = new Dictionary<string, string>()
@ -160,11 +177,15 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
result.Values[settingDefinition.Name] = await _settingProvider.GetOrNullAsync(settingDefinition.Name);
}
Logger.LogDebug("Executed AbpApplicationConfigurationAppService.GetSettingConfigAsync()");
return result;
}
protected virtual async Task<ApplicationFeatureConfigurationDto> GetFeaturesConfigAsync()
{
Logger.LogDebug("Executing AbpApplicationConfigurationAppService.GetFeaturesConfigAsync()");
var result = new ApplicationFeatureConfigurationDto();
foreach (var featureDefinition in _featureDefinitionManager.GetAll())
@ -177,6 +198,8 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
result.Values[featureDefinition.Name] = await FeatureChecker.GetOrNullAsync(featureDefinition.Name);
}
Logger.LogDebug("Executed AbpApplicationConfigurationAppService.GetFeaturesConfigAsync()");
return result;
}
}

4
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationController.cs

@ -15,9 +15,9 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
}
[HttpGet]
public Task<ApplicationConfigurationDto> GetAsync()
public async Task<ApplicationConfigurationDto> GetAsync()
{
return _applicationConfigurationAppService.GetAsync();
return await _applicationConfigurationAppService.GetAsync();
}
}
}

14
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationScriptController.cs

@ -2,6 +2,7 @@
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Volo.Abp.Auditing;
using Volo.Abp.Http;
using Volo.Abp.Json;
@ -28,12 +29,15 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
[Produces(MimeTypes.Application.Javascript, MimeTypes.Text.Plain)]
public async Task<ActionResult> Get()
{
return Content(
CreateAbpExtendScript(
await _configurationAppService.GetAsync()
),
MimeTypes.Application.Javascript
Logger.LogDebug("Executing AbpApplicationConfigurationScriptController.Get()");
var result = CreateAbpExtendScript(
await _configurationAppService.GetAsync()
);
Logger.LogDebug("Executed AbpApplicationConfigurationScriptController.Get()");
return Content(result, MimeTypes.Application.Javascript);
}
private string CreateAbpExtendScript(ApplicationConfigurationDto config)

4
framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs

@ -25,7 +25,9 @@ namespace Microsoft.AspNetCore.RequestLocalization
{
var middleware = new RequestLocalizationMiddleware(
next,
new OptionsWrapper<RequestLocalizationOptions>(_requestLocalizationOptionsProvider.GetLocalizationOptions()),
new OptionsWrapper<RequestLocalizationOptions>(
await _requestLocalizationOptionsProvider.GetLocalizationOptionsAsync()
),
_loggerFactory
);

79
framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs

@ -2,67 +2,76 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Localization;
using Microsoft.Extensions.DependencyInjection;
using Nito.AsyncEx;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Localization;
using Volo.Abp.Settings;
using Volo.Abp.Threading;
namespace Microsoft.AspNetCore.RequestLocalization
{
public class DefaultAbpRequestLocalizationOptionsProvider : IAbpRequestLocalizationOptionsProvider, ISingletonDependency
{
private readonly IServiceProvider _serviceProvider;
private Lazy<RequestLocalizationOptions> _lazyRequestLocalizationOptions;
private readonly IServiceScopeFactory _serviceProviderFactory;
private readonly SemaphoreSlim _syncSemaphore;
private Action<RequestLocalizationOptions> _optionsAction;
private RequestLocalizationOptions _requestLocalizationOptions;
public DefaultAbpRequestLocalizationOptionsProvider(IServiceProvider serviceProvider)
public DefaultAbpRequestLocalizationOptionsProvider(IServiceScopeFactory serviceProviderFactory)
{
_serviceProvider = serviceProvider;
_serviceProviderFactory = serviceProviderFactory;
_syncSemaphore = new SemaphoreSlim(1, 1);
}
public void InitLocalizationOptions(Action<RequestLocalizationOptions> optionsAction = null)
{
_lazyRequestLocalizationOptions = new Lazy<RequestLocalizationOptions>(() =>
_optionsAction = optionsAction;
}
public async Task<RequestLocalizationOptions> GetLocalizationOptionsAsync()
{
if (_requestLocalizationOptions == null)
{
using (var serviceScope = _serviceProvider.CreateScope())
using (await _syncSemaphore.LockAsync())
{
var languageProvider = serviceScope.ServiceProvider.GetRequiredService<ILanguageProvider>();
var settingProvider = serviceScope.ServiceProvider.GetRequiredService<ISettingProvider>();
using (var serviceScope = _serviceProviderFactory.CreateScope())
{
var languageProvider = serviceScope.ServiceProvider.GetRequiredService<ILanguageProvider>();
var settingProvider = serviceScope.ServiceProvider.GetRequiredService<ISettingProvider>();
var languages = AsyncHelper.RunSync(languageProvider.GetLanguagesAsync);
var defaultLanguage = AsyncHelper.RunSync(() =>
settingProvider.GetOrNullAsync(LocalizationSettingNames.DefaultLanguage));
var languages = await languageProvider.GetLanguagesAsync();
var defaultLanguage = await settingProvider.GetOrNullAsync(LocalizationSettingNames.DefaultLanguage);
var options = !languages.Any()
? new RequestLocalizationOptions()
: new RequestLocalizationOptions
{
DefaultRequestCulture = DefaultGetRequestCulture(defaultLanguage, languages),
var options = !languages.Any()
? new RequestLocalizationOptions()
: new RequestLocalizationOptions
{
DefaultRequestCulture = DefaultGetRequestCulture(defaultLanguage, languages),
SupportedCultures = languages
.Select(l => l.CultureName)
.Distinct()
.Select(c => new CultureInfo(c))
.ToArray(),
SupportedCultures = languages
.Select(l => l.CultureName)
.Distinct()
.Select(c => new CultureInfo(c))
.ToArray(),
SupportedUICultures = languages
.Select(l => l.UiCultureName)
.Distinct()
.Select(c => new CultureInfo(c))
.ToArray()
};
SupportedUICultures = languages
.Select(l => l.UiCultureName)
.Distinct()
.Select(c => new CultureInfo(c))
.ToArray()
};
optionsAction?.Invoke(options);
return options;
_optionsAction?.Invoke(options);
_requestLocalizationOptions = options;
}
}
}, true);
}
}
public RequestLocalizationOptions GetLocalizationOptions()
{
return _lazyRequestLocalizationOptions.Value;
return _requestLocalizationOptions;
}
private static RequestCulture DefaultGetRequestCulture(string defaultLanguage, IReadOnlyList<LanguageInfo> languages)

3
framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/IAbpRequestLocalizationOptionsProvider.cs

@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
namespace Microsoft.AspNetCore.RequestLocalization
@ -7,6 +8,6 @@ namespace Microsoft.AspNetCore.RequestLocalization
{
void InitLocalizationOptions(Action<RequestLocalizationOptions> optionsAction = null);
RequestLocalizationOptions GetLocalizationOptions();
Task<RequestLocalizationOptions> GetLocalizationOptionsAsync();
}
}

27
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptor.cs

@ -18,33 +18,6 @@ namespace Volo.Abp.Auditing
_auditingManager = auditingManager;
}
public override void Intercept(IAbpMethodInvocation invocation)
{
if (!ShouldIntercept(invocation, out var auditLog, out var auditLogAction))
{
invocation.Proceed();
return;
}
var stopwatch = Stopwatch.StartNew();
try
{
invocation.Proceed();
}
catch (Exception ex)
{
auditLog.Exceptions.Add(ex);
throw;
}
finally
{
stopwatch.Stop();
auditLogAction.ExecutionDuration = Convert.ToInt32(stopwatch.Elapsed.TotalMilliseconds);
auditLog.Actions.Add(auditLogAction);
}
}
public override async Task InterceptAsync(IAbpMethodInvocation invocation)
{
if (!ShouldIntercept(invocation, out var auditLog, out var auditLogAction))

15
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingManager.cs

@ -120,16 +120,6 @@ namespace Volo.Abp.Auditing
}
}
protected virtual void Save(DisposableSaveHandle saveHandle)
{
BeforeSave(saveHandle);
if (ShouldSave(saveHandle.AuditLog))
{
_auditingStore.Save(saveHandle.AuditLog);
}
}
protected bool ShouldSave(AuditLogInfo auditLog)
{
if (!auditLog.Actions.Any() && !auditLog.EntityChanges.Any())
@ -165,11 +155,6 @@ namespace Volo.Abp.Auditing
await _auditingManager.SaveAsync(this);
}
public void Save()
{
_auditingManager.Save(this);
}
public void Dispose()
{
_scope.Dispose();

2
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditLogSaveHandle.cs

@ -5,8 +5,6 @@ namespace Volo.Abp.Auditing
{
public interface IAuditLogSaveHandle : IDisposable
{
void Save();
Task SaveAsync();
}
}

2
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditingStore.cs

@ -4,8 +4,6 @@ namespace Volo.Abp.Auditing
{
public interface IAuditingStore
{
void Save(AuditLogInfo auditInfo);
Task SaveAsync(AuditLogInfo auditInfo);
}
}

7
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/SimpleLogAuditingStore.cs

@ -15,14 +15,9 @@ namespace Volo.Abp.Auditing
Logger = NullLogger<SimpleLogAuditingStore>.Instance;
}
public void Save(AuditLogInfo auditInfo)
{
Logger.LogInformation(auditInfo.ToString());
}
public Task SaveAsync(AuditLogInfo auditInfo)
{
Save(auditInfo);
Logger.LogInformation(auditInfo.ToString());
return Task.FromResult(0);
}
}

28
framework/src/Volo.Abp.Authorization/Microsoft/AspNetCore/Authorization/AbpAuthorizationServiceExtensions.cs

@ -7,52 +7,54 @@ namespace Microsoft.AspNetCore.Authorization
{
public static class AbpAuthorizationServiceExtensions
{
public static Task<AuthorizationResult> AuthorizeAsync(this IAuthorizationService authorizationService, string policyName)
public static async Task<AuthorizationResult> AuthorizeAsync(this IAuthorizationService authorizationService, string policyName)
{
return AuthorizeAsync(
return await AuthorizeAsync(
authorizationService,
authorizationService.AsAbpAuthorizationService().CurrentPrincipal,
null,
policyName
);
}
public static Task<AuthorizationResult> AuthorizeAsync(this IAuthorizationService authorizationService, object resource, IAuthorizationRequirement requirement)
public static async Task<AuthorizationResult> AuthorizeAsync(this IAuthorizationService authorizationService, object resource, IAuthorizationRequirement requirement)
{
return authorizationService.AuthorizeAsync(
return await authorizationService.AuthorizeAsync(
authorizationService.AsAbpAuthorizationService().CurrentPrincipal,
resource,
requirement
);
}
public static Task<AuthorizationResult> AuthorizeAsync(this IAuthorizationService authorizationService, object resource, AuthorizationPolicy policy)
public static async Task<AuthorizationResult> AuthorizeAsync(this IAuthorizationService authorizationService, object resource, AuthorizationPolicy policy)
{
return authorizationService.AuthorizeAsync(
return await authorizationService.AuthorizeAsync(
authorizationService.AsAbpAuthorizationService().CurrentPrincipal,
resource,
policy
);
}
public static Task<AuthorizationResult> AuthorizeAsync(this IAuthorizationService authorizationService, AuthorizationPolicy policy)
public static async Task<AuthorizationResult> AuthorizeAsync(this IAuthorizationService authorizationService, AuthorizationPolicy policy)
{
return AuthorizeAsync(authorizationService, authorizationService.AsAbpAuthorizationService().CurrentPrincipal,
return await AuthorizeAsync(
authorizationService,
null,
policy
);
}
public static Task<AuthorizationResult> AuthorizeAsync(this IAuthorizationService authorizationService, object resource, IEnumerable<IAuthorizationRequirement> requirements)
public static async Task<AuthorizationResult> AuthorizeAsync(this IAuthorizationService authorizationService, object resource, IEnumerable<IAuthorizationRequirement> requirements)
{
return authorizationService.AuthorizeAsync(
return await authorizationService.AuthorizeAsync(
authorizationService.AsAbpAuthorizationService().CurrentPrincipal,
resource,
requirements
);
}
public static Task<AuthorizationResult> AuthorizeAsync(this IAuthorizationService authorizationService, object resource, string policyName)
public static async Task<AuthorizationResult> AuthorizeAsync(this IAuthorizationService authorizationService, object resource, string policyName)
{
return authorizationService.AuthorizeAsync(
return await authorizationService.AuthorizeAsync(
authorizationService.AsAbpAuthorizationService().CurrentPrincipal,
resource,
policyName

7
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AuthorizationInterceptor.cs

@ -1,7 +1,6 @@
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.DynamicProxy;
using Volo.Abp.Threading;
namespace Volo.Abp.Authorization
{
@ -14,12 +13,6 @@ namespace Volo.Abp.Authorization
_methodInvocationAuthorizationService = methodInvocationAuthorizationService;
}
public override void Intercept(IAbpMethodInvocation invocation)
{
AsyncHelper.RunSync(() => AuthorizeAsync(invocation));
invocation.Proceed();
}
public override async Task InterceptAsync(IAbpMethodInvocation invocation)
{
await AuthorizeAsync(invocation);

4
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionChecker.cs

@ -27,9 +27,9 @@ namespace Volo.Abp.Authorization.Permissions
PermissionValueProviderManager = permissionValueProviderManager;
}
public virtual Task<bool> IsGrantedAsync(string name)
public virtual async Task<bool> IsGrantedAsync(string name)
{
return IsGrantedAsync(PrincipalAccessor.Principal, name);
return await IsGrantedAsync(PrincipalAccessor.Principal, name);
}
public virtual async Task<bool> IsGrantedAsync(ClaimsPrincipal claimsPrincipal, string name)

2
framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs

@ -89,7 +89,7 @@ namespace Autofac.Builder
foreach (var interceptor in interceptors)
{
registrationBuilder.InterceptedBy(
typeof(CastleAbpInterceptorAdapter<>).MakeGenericType(interceptor)
typeof(AbpAsyncDeterminationInterceptor<>).MakeGenericType(interceptor)
);
}

5
framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/IJobQueueManager.cs

@ -1,9 +1,10 @@
using Volo.Abp.Threading;
using System.Threading.Tasks;
using Volo.Abp.Threading;
namespace Volo.Abp.BackgroundJobs.RabbitMQ
{
public interface IJobQueueManager : IRunnable
{
IJobQueue<TArgs> Get<TArgs>();
Task<IJobQueue<TArgs>> GetAsync<TArgs>();
}
}

31
framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueueManager.cs

@ -4,6 +4,7 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Nito.AsyncEx;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Threading;
@ -17,6 +18,8 @@ namespace Volo.Abp.BackgroundJobs.RabbitMQ
protected AbpBackgroundJobOptions Options { get; }
protected SemaphoreSlim SyncSemaphore { get; }
public JobQueueManager(
IOptions<AbpBackgroundJobOptions> options,
IServiceProvider serviceProvider)
@ -24,6 +27,7 @@ namespace Volo.Abp.BackgroundJobs.RabbitMQ
ServiceProvider = serviceProvider;
Options = options.Value;
JobQueues = new ConcurrentDictionary<string, IRunnable>();
SyncSemaphore = new SemaphoreSlim(1, 1);
}
public async Task StartAsync(CancellationToken cancellationToken = default)
@ -51,20 +55,31 @@ namespace Volo.Abp.BackgroundJobs.RabbitMQ
JobQueues.Clear();
}
public IJobQueue<TArgs> Get<TArgs>()
public async Task<IJobQueue<TArgs>> GetAsync<TArgs>()
{
var jobConfiguration = Options.GetJob(typeof(TArgs));
return (IJobQueue<TArgs>)JobQueues.GetOrAdd(jobConfiguration.JobName, _ =>
if (JobQueues.TryGetValue(jobConfiguration.JobName, out var jobQueue))
{
return (IJobQueue<TArgs>)jobQueue;
}
using (await SyncSemaphore.LockAsync())
{
var jobQueue = (IRunnable) ServiceProvider
.GetRequiredService(typeof(IJobQueue<>)
.MakeGenericType(typeof(TArgs)));
if (JobQueues.TryGetValue(jobConfiguration.JobName, out jobQueue))
{
return (IJobQueue<TArgs>)jobQueue;
}
AsyncHelper.RunSync(() => jobQueue.StartAsync());
jobQueue = (IJobQueue<TArgs>)ServiceProvider
.GetRequiredService(typeof(IJobQueue<>).MakeGenericType(typeof(TArgs)));
return jobQueue;
});
await jobQueue.StartAsync();
JobQueues.TryAdd(jobConfiguration.JobName, jobQueue);
return (IJobQueue<TArgs>)jobQueue;
}
}
}
}

7
framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/RabbitMqBackgroundJobManager.cs

@ -14,14 +14,13 @@ namespace Volo.Abp.BackgroundJobs.RabbitMQ
_jobQueueManager = jobQueueManager;
}
public Task<string> EnqueueAsync<TArgs>(
public async Task<string> EnqueueAsync<TArgs>(
TArgs args,
BackgroundJobPriority priority = BackgroundJobPriority.Normal,
TimeSpan? delay = null)
{
return _jobQueueManager
.Get<TArgs>()
.EnqueueAsync(args, priority, delay);
var jobQueue = await _jobQueueManager.GetAsync<TArgs>();
return await jobQueue.EnqueueAsync(args, priority, delay);
}
}
}

6
framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs

@ -36,7 +36,7 @@ namespace Volo.Abp.BackgroundJobs
{
var store = scope.ServiceProvider.GetRequiredService<IBackgroundJobStore>();
var waitingJobs = store.GetWaitingJobs(WorkerOptions.MaxJobFetchCount);
var waitingJobs = AsyncHelper.RunSync(() => store.GetWaitingJobsAsync(WorkerOptions.MaxJobFetchCount));
if (!waitingJobs.Any())
{
@ -62,7 +62,7 @@ namespace Volo.Abp.BackgroundJobs
{
jobExecuter.Execute(context);
store.Delete(jobInfo.Id);
AsyncHelper.RunSync(() => store.DeleteAsync(jobInfo.Id));
}
catch (BackgroundJobExecutionException)
{
@ -94,7 +94,7 @@ namespace Volo.Abp.BackgroundJobs
{
try
{
store.Update(jobInfo);
AsyncHelper.RunSync(() => store.UpdateAsync(jobInfo));
}
catch (Exception updateEx)
{

34
framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/IBackgroundJobStore.cs

@ -9,13 +9,6 @@ namespace Volo.Abp.BackgroundJobs
/// </summary>
public interface IBackgroundJobStore
{
/// <summary>
/// Gets a BackgroundJobInfo based on the given jobId.
/// </summary>
/// <param name="jobId">The Job Unique Identifier.</param>
/// <returns>The BackgroundJobInfo object.</returns>
BackgroundJobInfo Find(Guid jobId);
/// <summary>
/// Gets a BackgroundJobInfo based on the given jobId.
/// </summary>
@ -23,27 +16,12 @@ namespace Volo.Abp.BackgroundJobs
/// <returns>The BackgroundJobInfo object.</returns>
Task<BackgroundJobInfo> FindAsync(Guid jobId);
/// <summary>
/// Inserts a background job.
/// </summary>
/// <param name="jobInfo">Job information.</param>
void Insert(BackgroundJobInfo jobInfo);
/// <summary>
/// Inserts a background job.
/// </summary>
/// <param name="jobInfo">Job information.</param>
Task InsertAsync(BackgroundJobInfo jobInfo);
/// <summary>
/// Gets waiting jobs. It should get jobs based on these:
/// Conditions: !IsAbandoned And NextTryTime &lt;= Clock.Now.
/// Order by: Priority DESC, TryCount ASC, NextTryTime ASC.
/// Maximum result: <paramref name="maxResultCount"/>.
/// </summary>
/// <param name="maxResultCount">Maximum result count.</param>
List<BackgroundJobInfo> GetWaitingJobs(int maxResultCount);
/// <summary>
/// Gets waiting jobs. It should get jobs based on these:
/// Conditions: !IsAbandoned And NextTryTime &lt;= Clock.Now.
@ -53,24 +31,12 @@ namespace Volo.Abp.BackgroundJobs
/// <param name="maxResultCount">Maximum result count.</param>
Task<List<BackgroundJobInfo>> GetWaitingJobsAsync(int maxResultCount);
/// <summary>
/// Deletes a job.
/// </summary>
/// <param name="jobId">The Job Unique Identifier.</param>
void Delete(Guid jobId);
/// <summary>
/// Deletes a job.
/// </summary>
/// <param name="jobId">The Job Unique Identifier.</param>
Task DeleteAsync(Guid jobId);
/// <summary>
/// Updates a job.
/// </summary>
/// <param name="jobInfo">Job information.</param>
void Update(BackgroundJobInfo jobInfo);
/// <summary>
/// Updates a job.
/// </summary>

35
framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/InMemoryBackgroundJobStore.cs

@ -23,21 +23,11 @@ namespace Volo.Abp.BackgroundJobs
_jobs = new ConcurrentDictionary<Guid, BackgroundJobInfo>();
}
public BackgroundJobInfo Find(Guid jobId)
{
return _jobs.GetOrDefault(jobId);
}
public virtual Task<BackgroundJobInfo> FindAsync(Guid jobId)
{
return Task.FromResult(_jobs.GetOrDefault(jobId));
}
public void Insert(BackgroundJobInfo jobInfo)
{
_jobs[jobInfo.Id] = jobInfo;
}
public virtual Task InsertAsync(BackgroundJobInfo jobInfo)
{
_jobs[jobInfo.Id] = jobInfo;
@ -45,17 +35,6 @@ namespace Volo.Abp.BackgroundJobs
return Task.FromResult(0);
}
public List<BackgroundJobInfo> GetWaitingJobs(int maxResultCount)
{
return _jobs.Values
.Where(t => !t.IsAbandoned && t.NextTryTime <= Clock.Now)
.OrderByDescending(t => t.Priority)
.ThenBy(t => t.TryCount)
.ThenBy(t => t.NextTryTime)
.Take(maxResultCount)
.ToList();
}
public virtual Task<List<BackgroundJobInfo>> GetWaitingJobsAsync(int maxResultCount)
{
var waitingJobs = _jobs.Values
@ -69,10 +48,6 @@ namespace Volo.Abp.BackgroundJobs
return Task.FromResult(waitingJobs);
}
public void Delete(Guid jobId)
{
_jobs.TryRemove(jobId, out _);
}
public virtual Task DeleteAsync(Guid jobId)
{
@ -80,15 +55,7 @@ namespace Volo.Abp.BackgroundJobs
return Task.FromResult(0);
}
public void Update(BackgroundJobInfo jobInfo)
{
if (jobInfo.IsAbandoned)
{
DeleteAsync(jobInfo.Id);
}
}
public virtual Task UpdateAsync(BackgroundJobInfo jobInfo)
{
if (jobInfo.IsAbandoned)

1
framework/src/Volo.Abp.Castle.Core/Volo.Abp.Castle.Core.csproj

@ -15,6 +15,7 @@
<ItemGroup>
<PackageReference Include="Castle.Core" Version="4.4.0" />
<PackageReference Include="Castle.Core.AsyncInterceptor" Version="2.0.21-alpha" />
</ItemGroup>
<ItemGroup>

2
framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/AbpCastleCoreModule.cs

@ -8,7 +8,7 @@ namespace Volo.Abp.Castle
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddTransient(typeof(CastleAbpInterceptorAdapter<>));
context.Services.AddTransient(typeof(AbpAsyncDeterminationInterceptor<>));
}
}
}

15
framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/AbpAsyncDeterminationInterceptor.cs

@ -0,0 +1,15 @@
using Castle.DynamicProxy;
using Volo.Abp.DynamicProxy;
namespace Volo.Abp.Castle.DynamicProxy
{
public class AbpAsyncDeterminationInterceptor<TInterceptor> : AsyncDeterminationInterceptor
where TInterceptor : IAbpInterceptor
{
public AbpAsyncDeterminationInterceptor(TInterceptor abpInterceptor)
: base(new CastleAsyncAbpInterceptorAdapter<TInterceptor>(abpInterceptor))
{
}
}
}

89
framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpInterceptorAdapter.cs

@ -1,89 +0,0 @@
using System.Reflection;
using System.Threading.Tasks;
using Castle.DynamicProxy;
using Volo.Abp.DynamicProxy;
using Volo.Abp.Threading;
namespace Volo.Abp.Castle.DynamicProxy
{
public class CastleAbpInterceptorAdapter<TInterceptor> : IInterceptor
where TInterceptor : IAbpInterceptor
{
private static readonly MethodInfo MethodExecuteWithoutReturnValueAsync =
typeof(CastleAbpInterceptorAdapter<TInterceptor>)
.GetMethod(
nameof(ExecuteWithoutReturnValueAsync),
BindingFlags.NonPublic | BindingFlags.Instance
);
private static readonly MethodInfo MethodExecuteWithReturnValueAsync =
typeof(CastleAbpInterceptorAdapter<TInterceptor>)
.GetMethod(
nameof(ExecuteWithReturnValueAsync),
BindingFlags.NonPublic | BindingFlags.Instance
);
private readonly TInterceptor _abpInterceptor;
public CastleAbpInterceptorAdapter(TInterceptor abpInterceptor)
{
_abpInterceptor = abpInterceptor;
}
public void Intercept(IInvocation invocation)
{
var proceedInfo = invocation.CaptureProceedInfo();
var method = invocation.MethodInvocationTarget ?? invocation.Method;
if (method.IsAsync())
{
InterceptAsyncMethod(invocation, proceedInfo);
}
else
{
InterceptSyncMethod(invocation, proceedInfo);
}
}
private void InterceptSyncMethod(IInvocation invocation, IInvocationProceedInfo proceedInfo)
{
_abpInterceptor.Intercept(new CastleAbpMethodInvocationAdapter(invocation, proceedInfo));
}
private void InterceptAsyncMethod(IInvocation invocation, IInvocationProceedInfo proceedInfo)
{
if (invocation.Method.ReturnType == typeof(Task))
{
invocation.ReturnValue = MethodExecuteWithoutReturnValueAsync
.Invoke(this, new object[] { invocation, proceedInfo });
}
else
{
invocation.ReturnValue = MethodExecuteWithReturnValueAsync
.MakeGenericMethod(invocation.Method.ReturnType.GenericTypeArguments[0])
.Invoke(this, new object[] {invocation, proceedInfo});
}
}
private async Task ExecuteWithoutReturnValueAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo)
{
await Task.Yield();
await _abpInterceptor.InterceptAsync(
new CastleAbpMethodInvocationAdapter(invocation, proceedInfo)
);
}
private async Task<T> ExecuteWithReturnValueAsync<T>(IInvocation invocation, IInvocationProceedInfo proceedInfo)
{
await Task.Yield();
await _abpInterceptor.InterceptAsync(
new CastleAbpMethodInvocationAdapter(invocation, proceedInfo)
);
return await (Task<T>)invocation.ReturnValue;
}
}
}

67
framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapter.cs

@ -1,77 +1,26 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
using Castle.DynamicProxy;
using Volo.Abp.DynamicProxy;
using Volo.Abp.Threading;
namespace Volo.Abp.Castle.DynamicProxy
{
public class CastleAbpMethodInvocationAdapter : IAbpMethodInvocation
public class CastleAbpMethodInvocationAdapter : CastleAbpMethodInvocationAdapterBase, IAbpMethodInvocation
{
public object[] Arguments => Invocation.Arguments;
public IReadOnlyDictionary<string, object> ArgumentsDictionary => _lazyArgumentsDictionary.Value;
private readonly Lazy<IReadOnlyDictionary<string, object>> _lazyArgumentsDictionary;
public Type[] GenericArguments => Invocation.GenericArguments;
public object TargetObject => Invocation.InvocationTarget ?? Invocation.MethodInvocationTarget;
public MethodInfo Method => Invocation.MethodInvocationTarget ?? Invocation.Method;
public object ReturnValue
{
get => _actualReturnValue ?? Invocation.ReturnValue;
set => Invocation.ReturnValue = value;
}
private object _actualReturnValue;
protected IInvocation Invocation { get; }
protected IInvocationProceedInfo ProceedInfo { get; }
protected Func<IInvocation, IInvocationProceedInfo, Task> Proceed { get; }
public CastleAbpMethodInvocationAdapter(IInvocation invocation, IInvocationProceedInfo proceedInfo)
public CastleAbpMethodInvocationAdapter(IInvocation invocation, IInvocationProceedInfo proceedInfo,
Func<IInvocation, IInvocationProceedInfo, Task> proceed)
: base(invocation)
{
Invocation = invocation;
ProceedInfo = proceedInfo;
_lazyArgumentsDictionary = new Lazy<IReadOnlyDictionary<string, object>>(GetArgumentsDictionary);
Proceed = proceed;
}
public void Proceed()
public override async Task ProceedAsync()
{
ProceedInfo.Invoke();
if (Invocation.Method.IsAsync())
{
AsyncHelper.RunSync(() => (Task)Invocation.ReturnValue);
}
}
public Task ProceedAsync()
{
ProceedInfo.Invoke();
_actualReturnValue = Invocation.ReturnValue;
return Invocation.Method.IsAsync()
? (Task)_actualReturnValue
: Task.FromResult(_actualReturnValue);
}
private IReadOnlyDictionary<string, object> GetArgumentsDictionary()
{
var dict = new Dictionary<string, object>();
var methodParameters = Method.GetParameters();
for (int i = 0; i < methodParameters.Length; i++)
{
dict[methodParameters[i].Name] = Invocation.Arguments[i];
}
return dict;
await Proceed(Invocation, ProceedInfo);
}
}
}

48
framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapterBase.cs

@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
using Castle.DynamicProxy;
using Volo.Abp.DynamicProxy;
namespace Volo.Abp.Castle.DynamicProxy
{
public abstract class CastleAbpMethodInvocationAdapterBase : IAbpMethodInvocation
{
public object[] Arguments => Invocation.Arguments;
public IReadOnlyDictionary<string, object> ArgumentsDictionary => _lazyArgumentsDictionary.Value;
private readonly Lazy<IReadOnlyDictionary<string, object>> _lazyArgumentsDictionary;
public Type[] GenericArguments => Invocation.GenericArguments;
public object TargetObject => Invocation.InvocationTarget ?? Invocation.MethodInvocationTarget;
public MethodInfo Method => Invocation.MethodInvocationTarget ?? Invocation.Method;
public object ReturnValue { get; set; }
protected IInvocation Invocation { get; }
protected CastleAbpMethodInvocationAdapterBase(IInvocation invocation)
{
Invocation = invocation;
_lazyArgumentsDictionary = new Lazy<IReadOnlyDictionary<string, object>>(GetArgumentsDictionary);
}
public abstract Task ProceedAsync();
private IReadOnlyDictionary<string, object> GetArgumentsDictionary()
{
var dict = new Dictionary<string, object>();
var methodParameters = Method.GetParameters();
for (int i = 0; i < methodParameters.Length; i++)
{
dict[methodParameters[i].Name] = Invocation.Arguments[i];
}
return dict;
}
}
}

27
framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapterWithReturnValue.cs

@ -0,0 +1,27 @@
using System;
using System.Threading.Tasks;
using Castle.DynamicProxy;
using Volo.Abp.DynamicProxy;
namespace Volo.Abp.Castle.DynamicProxy
{
public class CastleAbpMethodInvocationAdapterWithReturnValue<TResult> : CastleAbpMethodInvocationAdapterBase, IAbpMethodInvocation
{
protected IInvocationProceedInfo ProceedInfo { get; }
protected Func<IInvocation, IInvocationProceedInfo, Task<TResult>> Proceed { get; }
public CastleAbpMethodInvocationAdapterWithReturnValue(IInvocation invocation,
IInvocationProceedInfo proceedInfo,
Func<IInvocation, IInvocationProceedInfo, Task<TResult>> proceed)
: base(invocation)
{
ProceedInfo = proceedInfo;
Proceed = proceed;
}
public override async Task ProceedAsync()
{
ReturnValue = await Proceed(Invocation, ProceedInfo);
}
}
}

36
framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAsyncAbpInterceptorAdapter.cs

@ -0,0 +1,36 @@
using System;
using System.Threading.Tasks;
using Castle.DynamicProxy;
using Volo.Abp.DynamicProxy;
namespace Volo.Abp.Castle.DynamicProxy
{
public class CastleAsyncAbpInterceptorAdapter<TInterceptor> : AsyncInterceptorBase
where TInterceptor : IAbpInterceptor
{
private readonly TInterceptor _abpInterceptor;
public CastleAsyncAbpInterceptorAdapter(TInterceptor abpInterceptor)
{
_abpInterceptor = abpInterceptor;
}
protected override async Task InterceptAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func<IInvocation, IInvocationProceedInfo, Task> proceed)
{
await _abpInterceptor.InterceptAsync(
new CastleAbpMethodInvocationAdapter(invocation, proceedInfo, proceed)
);
}
protected override async Task<TResult> InterceptAsync<TResult>(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func<IInvocation, IInvocationProceedInfo, Task<TResult>> proceed)
{
var adapter = new CastleAbpMethodInvocationAdapterWithReturnValue<TResult>(invocation, proceedInfo, proceed);
await _abpInterceptor.InterceptAsync(
adapter
);
return (TResult)adapter.ReturnValue;
}
}
}

2
framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj

@ -19,6 +19,8 @@
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.7.0" />
<PackageReference Include="System.Security.Permissions" Version="4.6.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.3.1" />
<PackageReference Include="Polly" Version="7.2.0" />
<PackageReference Include="Polly.Extensions.Http" Version="3.0.0" />
</ItemGroup>
<ItemGroup>

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

@ -19,10 +19,6 @@ namespace Volo.Abp.Cli
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
// TODO: workaround until subsequent issues of https://github.com/dotnet/corefx/issues/30166 are resolved
// a permanent fix will probably be published with the release of .net core 3.0: https://github.com/dotnet/corefx/issues/36553
AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false);
Configure<AbpCliOptions>(options =>
{
options.Commands["help"] = typeof(HelpCommand);
@ -33,6 +29,7 @@ namespace Volo.Abp.Cli
options.Commands["add-module"] = typeof(AddModuleCommand);
options.Commands["login"] = typeof(LoginCommand);
options.Commands["logout"] = typeof(LogoutCommand);
options.Commands["suite"] = typeof(SuiteCommand);
});
}
}

23
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs

@ -69,7 +69,7 @@ namespace Volo.Abp.Cli
{
var assembly = typeof(CliService).Assembly;
var toolPath = GetToolPath(assembly);
var currentCliVersion = await GetCurrentCliVersion(toolPath, assembly);
var currentCliVersion = await GetCurrentCliVersion(assembly);
var updateChannel = GetUpdateChannel(currentCliVersion);
Logger.LogInformation($"Version {currentCliVersion} ({updateChannel} channel)");
@ -100,26 +100,25 @@ namespace Volo.Abp.Cli
return assembly.Location.Substring(0, assembly.Location.IndexOf(".store", StringComparison.Ordinal));
}
private async Task<SemanticVersion> GetCurrentCliVersion(string toolPath, Assembly assembly)
private static async Task<SemanticVersion> GetCurrentCliVersion(Assembly assembly)
{
SemanticVersion currentCliVersion = default;
if (!string.IsNullOrEmpty(toolPath))
var consoleOutput = new StringReader(CmdHelper.RunCmdAndGetOutput($"dotnet tool list -g"));
string line;
while ((line = await consoleOutput.ReadLineAsync()) != null)
{
var consoleOutput = new StringReader(CmdHelper.RunCmdAndGetOutput($"dotnet tool list --tool-path {toolPath}"));
string line;
while ((line = await consoleOutput.ReadLineAsync()) != null)
if (line.StartsWith("volo.abp.cli", StringComparison.InvariantCultureIgnoreCase))
{
if (line.StartsWith("Volo.Abp.Cli", StringComparison.InvariantCultureIgnoreCase))
{
var version = line.Split(new char[0], StringSplitOptions.RemoveEmptyEntries)[1];
var version = line.Split(new char[0], StringSplitOptions.RemoveEmptyEntries)[1];
SemanticVersion.TryParse(version, out currentCliVersion);
SemanticVersion.TryParse(version, out currentCliVersion);
break;
}
break;
}
}
if (currentCliVersion == null)
{
// If not a tool executable, fallback to assembly version and treat as dev without updates

11
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliUrls.cs

@ -4,10 +4,21 @@
{
#if DEBUG
public const string WwwAbpIo = "https://localhost:44328/";
public const string AccountAbpIo = "https://localhost:44333/";
public const string NuGetRootPath = "https://localhost:44373/";
#else
public const string WwwAbpIo = "https://abp.io/";
public const string AccountAbpIo = "https://account.abp.io/";
public const string NuGetRootPath = "https://nuget.abp.io/";
#endif
public static string GetNuGetServiceIndexUrl(string apiKey)
{
return NuGetRootPath + apiKey + "/v3/index.json";
}
}
}

5
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs

@ -75,9 +75,8 @@ namespace Volo.Abp.Cli.Commands
public string GetShortDescription()
{
return "Adds a multi-package module to a solution by finding all packages of the module, " +
"finding related projects in the solution and adding each package to the" +
" corresponding project in the solution.";
return "Add a multi-package module to a solution by finding all packages of the module, " +
"finding related projects in the solution and adding each package to the corresponding project in the solution.";
}
protected virtual string GetSolutionFile(CommandLineArgs commandLineArgs)

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs

@ -68,9 +68,7 @@ namespace Volo.Abp.Cli.Commands
public string GetShortDescription()
{
return "Adds a new ABP package to a project by adding related nuget package" +
" as a dependency to the project and adding [DependsOn(...)] attribute to" +
" the module class in the project.";
return "Add a new ABP package to a project by adding related NuGet package dependencies and [DependsOn(...)] attributes.";
}
protected virtual string GetProjectFile(CommandLineArgs commandLineArgs)

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

@ -143,7 +143,7 @@ namespace Volo.Abp.Cli.Commands
public string GetShortDescription()
{
return "Downloads the source code of the specified module.";
return "Download the source code of the specified module.";
}
public static class Options

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/HelpCommand.cs

@ -82,7 +82,7 @@ namespace Volo.Abp.Cli.Commands
public string GetShortDescription()
{
return string.Empty;
return "Show command line help. Write ` abp help <command> `";
}
}
}

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs

@ -72,7 +72,7 @@ namespace Volo.Abp.Cli.Commands
public string GetShortDescription()
{
return string.Empty;
return "Sign in to " + CliUrls.AccountAbpIo + ".";
}
public static class Options

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LogoutCommand.cs

@ -31,7 +31,7 @@ namespace Volo.Abp.Cli.Commands
public string GetShortDescription()
{
return string.Empty;
return "Sign out from " + CliUrls.AccountAbpIo + ".";
}
}
}

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

@ -165,7 +165,7 @@ namespace Volo.Abp.Cli.Commands
sb.AppendLine(" abp new Acme.BookStore -d mongodb");
sb.AppendLine(" abp new Acme.BookStore -d mongodb -o d:\\my-project");
sb.AppendLine(" abp new Acme.BookStore -t module");
sb.AppendLine(" abp new Acme.BookStore -t module no-ui");
sb.AppendLine(" abp new Acme.BookStore -t module --no-ui");
sb.AppendLine(" abp new Acme.BookStore --local-framework-ref --abp-path \"D:\\github\\abp\"");
sb.AppendLine("");
sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI");
@ -175,7 +175,7 @@ namespace Volo.Abp.Cli.Commands
public string GetShortDescription()
{
return "Generates a new solution based on the ABP startup templates.";
return "Generate a new solution based on the ABP startup templates.";
}
protected virtual DatabaseProvider GetDatabaseProvider(CommandLineArgs commandLineArgs)
@ -246,4 +246,4 @@ namespace Volo.Abp.Cli.Commands
}
}
}
}
}

156
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SuiteCommand.cs

@ -0,0 +1,156 @@
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Cli.Args;
using Volo.Abp.Cli.Licensing;
using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.Commands
{
public class SuiteCommand : IConsoleCommand, ITransientDependency
{
private const string SuitePackageName = "Volo.Abp.Suite";
public ILogger<SuiteCommand> Logger { get; set; }
private readonly IApiKeyService _apiKeyService;
public SuiteCommand(IApiKeyService apiKeyService)
{
_apiKeyService = apiKeyService;
Logger = NullLogger<SuiteCommand>.Instance;
}
public async Task ExecuteAsync(CommandLineArgs commandLineArgs)
{
var operationType = NamespaceHelper.NormalizeNamespace(commandLineArgs.Target);
switch (operationType)
{
case "":
case null:
RunSuite();
break;
case "install":
Logger.LogInformation("Installing ABP Suite...");
await InstallSuiteAsync();
break;
case "update":
Logger.LogInformation("Updating ABP Suite...");
await UpdateSuiteAsync();
break;
case "remove":
Logger.LogInformation("Removing ABP Suite...");
RemoveSuite();
break;
}
}
private async Task InstallSuiteAsync()
{
var nugetIndexUrl = await GetNuGetIndexUrlAsync();
if (nugetIndexUrl == null)
{
return;
}
var result = CmdHelper.RunCmd("dotnet tool install " + SuitePackageName + " --add-source " + nugetIndexUrl + " -g");
if (result == 0)
{
Logger.LogInformation("ABP Suite has been successfully installed.");
Logger.LogInformation("You can run it with the CLI command \"abp suite\"");
}
}
private async Task UpdateSuiteAsync()
{
var nugetIndexUrl = await GetNuGetIndexUrlAsync();
if (nugetIndexUrl == null)
{
return;
}
CmdHelper.RunCmd("dotnet tool update " + SuitePackageName + " --add-source " + nugetIndexUrl + " -g");
}
private static void RemoveSuite()
{
CmdHelper.RunCmd("dotnet tool uninstall " + SuitePackageName + " -g");
}
private void RunSuite()
{
try
{
if (!GlobalToolHelper.IsGlobalToolInstalled("abp-suite"))
{
Logger.LogWarning("ABP Suite is not installed! To install it you can run the command: \"abp suite install\"");
return;
}
}
catch (Exception ex)
{
Logger.LogWarning("Couldn't check ABP Suite installed status: " + ex.Message);
}
CmdHelper.RunCmd("abp-suite");
}
private async Task<string> GetNuGetIndexUrlAsync()
{
var apiKeyResult = await _apiKeyService.GetApiKeyOrNullAsync();
if (apiKeyResult == null || string.IsNullOrEmpty(apiKeyResult.ApiKey))
{
Logger.LogError("Couldn't retrieve your NuGet API key!");
Logger.LogWarning(File.Exists(CliPaths.AccessToken)
? "Make sure you have an active session and license on commercial.abp.io. To re-sign in you can use the CLI command \"abp login <username>\"."
: "You are not signed in to commercial.abp.io. Use the CLI command \"abp login <username>\" to sign in.");
return null;
}
return CliUrls.GetNuGetServiceIndexUrl(apiKeyResult.ApiKey);
}
public string GetUsageInfo()
{
var sb = new StringBuilder();
sb.AppendLine("");
sb.AppendLine("Usage:");
sb.AppendLine("");
sb.AppendLine(" abp suite [options]");
sb.AppendLine("");
sb.AppendLine("Options:");
sb.AppendLine("");
sb.AppendLine("<no argument> (run ABP Suite)");
sb.AppendLine("install (install ABP Suite as a dotnet global tool)");
sb.AppendLine("update (update ABP Suite to the latest)");
sb.AppendLine("remove (uninstall ABP Suite)");
sb.AppendLine("");
sb.AppendLine("Examples:");
sb.AppendLine("");
sb.AppendLine(" abp suite");
sb.AppendLine(" abp suite install");
sb.AppendLine(" abp suite update");
sb.AppendLine(" abp suite remove");
sb.AppendLine("");
return sb.ToString();
}
public string GetShortDescription()
{
return "Install, update, remove or start ABP Suite. See https://commercial.abp.io/tools/suite.";
}
}
}

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

@ -5,12 +5,9 @@ using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Volo.Abp.Cli.Args;
using Volo.Abp.Cli.ProjectBuilding.Analyticses;
using Volo.Abp.Cli.ProjectModification;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Json;
namespace Volo.Abp.Cli.Commands
{
@ -20,21 +17,12 @@ namespace Volo.Abp.Cli.Commands
private readonly VoloNugetPackagesVersionUpdater _nugetPackagesVersionUpdater;
private readonly NpmPackagesUpdater _npmPackagesUpdater;
private readonly ICliAnalyticsCollect _cliAnalyticsCollect;
private readonly AbpCliOptions _options;
private readonly IJsonSerializer _jsonSerializer;
public UpdateCommand(VoloNugetPackagesVersionUpdater nugetPackagesVersionUpdater,
NpmPackagesUpdater npmPackagesUpdater,
ICliAnalyticsCollect cliAnalyticsCollect,
IJsonSerializer jsonSerializer,
IOptions<AbpCliOptions> options)
NpmPackagesUpdater npmPackagesUpdater)
{
_nugetPackagesVersionUpdater = nugetPackagesVersionUpdater;
_npmPackagesUpdater = npmPackagesUpdater;
_cliAnalyticsCollect = cliAnalyticsCollect;
_jsonSerializer = jsonSerializer;
_options = options.Value;
Logger = NullLogger<UpdateCommand>.Instance;
}
@ -44,24 +32,18 @@ namespace Volo.Abp.Cli.Commands
var updateNpm = commandLineArgs.Options.ContainsKey(Options.Packages.Npm);
var updateNuget = commandLineArgs.Options.ContainsKey(Options.Packages.NuGet);
var directory = commandLineArgs.Options.GetOrNull(Options.SolutionPath.Short, Options.SolutionPath.Long);
if (directory == null)
{
directory = Directory.GetCurrentDirectory();
}
var directory = commandLineArgs.Options.GetOrNull(Options.SolutionPath.Short, Options.SolutionPath.Long) ??
Directory.GetCurrentDirectory();
var both = (updateNuget && updateNpm) || (!updateNuget && !updateNpm);
if (updateNuget || both)
if (updateNuget || !updateNpm)
{
await UpdateNugetPackages(commandLineArgs, directory);
}
if (updateNpm || both)
if (updateNpm || !updateNuget)
{
UpdateNpmPackages(directory);
}
}
private void UpdateNpmPackages(string directory)
@ -131,8 +113,7 @@ namespace Volo.Abp.Cli.Commands
public string GetShortDescription()
{
return "Automatically updates all ABP related NuGet packages and NPM packages in a" +
" solution or project to the latest versions";
return "Update all ABP related NuGet packages and NPM packages in a solution or project to the latest version.";
}
public static class Options

28
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Http/CliHttpClient.cs

@ -8,22 +8,36 @@ namespace Volo.Abp.Cli.Http
{
public class CliHttpClient : HttpClient
{
public static TimeSpan DefaultTimeout { get; set; } = TimeSpan.FromMinutes(1);
public CliHttpClient(TimeSpan? timeout = null) : base(new CliHttpClientHandler())
{
Timeout = timeout ?? TimeSpan.FromMinutes(1);
Timeout = timeout ?? DefaultTimeout;
AddAuthentication(this);
}
public CliHttpClient(bool setBearerToken) : base(new CliHttpClientHandler())
{
Timeout = DefaultTimeout;
if (setBearerToken)
{
AddAuthentication(this);
}
}
private static void AddAuthentication(HttpClient client)
{
if (File.Exists(CliPaths.AccessToken))
if (!File.Exists(CliPaths.AccessToken))
{
return;
}
var accessToken = File.ReadAllText(CliPaths.AccessToken, Encoding.UTF8);
if (!accessToken.IsNullOrEmpty())
{
var accessToken = File.ReadAllText(CliPaths.AccessToken, Encoding.UTF8);
if (!accessToken.IsNullOrEmpty())
{
client.SetBearerToken(accessToken);
}
client.SetBearerToken(accessToken);
}
}
}

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

@ -1,5 +1,12 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Polly;
using Polly.Extensions.Http;
using Volo.Abp.Cli.Http;
using Volo.Abp.Cli.ProjectBuilding;
using Volo.Abp.DependencyInjection;
@ -10,22 +17,45 @@ namespace Volo.Abp.Cli.Licensing
public class AbpIoApiKeyService : IApiKeyService, ITransientDependency
{
protected IJsonSerializer JsonSerializer { get; }
protected IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; }
private readonly ILogger<AbpIoApiKeyService> _logger;
public AbpIoApiKeyService(IJsonSerializer jsonSerializer, IRemoteServiceExceptionHandler remoteServiceExceptionHandler)
public AbpIoApiKeyService(IJsonSerializer jsonSerializer, IRemoteServiceExceptionHandler remoteServiceExceptionHandler, ILogger<AbpIoApiKeyService> logger)
{
JsonSerializer = jsonSerializer;
RemoteServiceExceptionHandler = remoteServiceExceptionHandler;
_logger = logger;
}
public async Task<DeveloperApiKeyResult> GetApiKeyOrNullAsync()
{
using (var client = new CliHttpClient())
{
var url = $"{CliUrls.WwwAbpIo}api/license/api-key";
var response = await client.GetAsync(url);
var response = await HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(msg => !msg.IsSuccessStatusCode)
.WaitAndRetryAsync(new[]
{
TimeSpan.FromSeconds(1),
TimeSpan.FromSeconds(3),
TimeSpan.FromSeconds(7)
},
(responseMessage, timeSpan, retryCount, context) =>
{
if (responseMessage.Exception != null)
{
_logger.LogWarning(
$"{retryCount}. request attempt failed with an error: \"{responseMessage.Exception.Message}\". " +
$"Waiting {timeSpan.TotalSeconds} secs for the next try...");
}
else if (responseMessage.Result != null)
{
_logger.LogWarning(
$"{retryCount}. request attempt failed with {responseMessage.Result.StatusCode}-{responseMessage.Result.ReasonPhrase}. " +
$"Waiting {timeSpan.TotalSeconds} secs for the next try...");
}
})
.ExecuteAsync(async () => await client.GetAsync($"{CliUrls.WwwAbpIo}api/license/api-key"));
if (!response.IsSuccessStatusCode)
{

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

@ -32,7 +32,7 @@ namespace Volo.Abp.Cli.NuGet
public async Task<SemanticVersion> GetLatestVersionOrNullAsync(string packageId, bool includePreviews = false, bool includeNightly = false)
{
using (var client = new CliHttpClient())
using (var client = new CliHttpClient(setBearerToken: false))
{
var url = includeNightly ?
$"https://www.myget.org/F/abp-nightly/api/v3/flatcontainer/{packageId.ToLowerInvariant()}/index.json" :

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

@ -32,7 +32,8 @@ namespace Volo.Abp.Cli.ProjectBuilding
return;
}
var exceptionMessage = "Remote server returns '" + (int)responseMessage.StatusCode + "-" + responseMessage.ReasonPhrase + "'. ";
var exceptionMessage = "Remote server returns '" + (int) responseMessage.StatusCode + "-" +
responseMessage.ReasonPhrase + "'. ";
var remoteServiceErrorMessage = await GetAbpRemoteServiceErrorAsync(responseMessage);
if (remoteServiceErrorMessage != null)
@ -45,10 +46,18 @@ namespace Volo.Abp.Cli.ProjectBuilding
public async Task<string> GetAbpRemoteServiceErrorAsync(HttpResponseMessage responseMessage)
{
var errorResult = _jsonSerializer.Deserialize<RemoteServiceErrorResponse>
(
await responseMessage.Content.ReadAsStringAsync()
);
RemoteServiceErrorResponse errorResult;
try
{
errorResult = _jsonSerializer.Deserialize<RemoteServiceErrorResponse>
(
await responseMessage.Content.ReadAsStringAsync()
);
}
catch (JsonReaderException)
{
return null;
}
if (errorResult?.Error == null)
{
@ -82,7 +91,8 @@ namespace Volo.Abp.Cli.ProjectBuilding
for (var i = 0; i < errorResult.Error.ValidationErrors.Length; i++)
{
var validationError = errorResult.Error.ValidationErrors[i];
sbError.AppendLine("Validation error #" + i + ": " + validationError.Message + " - Members: " + validationError.Members.JoinAsString(", ") + ".");
sbError.AppendLine("Validation error #" + i + ": " + validationError.Message + " - Members: " +
validationError.Members.JoinAsString(", ") + ".");
}
}

8
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/CmdHelper.cs

@ -11,10 +11,12 @@ namespace Volo.Abp.Cli.Utils
Process.Start(procStartInfo).WaitForExit();
}
public static void RunCmd(string command)
public static int RunCmd(string command)
{
var procStartInfo = new ProcessStartInfo(GetFileName(), GetArguments(command));
Process.Start(procStartInfo).WaitForExit();
var process = Process.Start(procStartInfo);
process?.WaitForExit();
return process?.ExitCode ?? 0;
}
public static string RunCmdAndGetOutput(string command)
@ -66,7 +68,7 @@ namespace Volo.Abp.Cli.Utils
}
//Windows default.
return "cmd.exe";
return "cmd.exe";
}
}
}

34
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/GlobalToolHelper.cs

@ -0,0 +1,34 @@
using System;
using System.IO;
namespace Volo.Abp.Cli.Utils
{
public class GlobalToolHelper
{
/// <summary>
/// Checks whether the tool is installed or not.
/// </summary>
/// <param name="toolCommandName">Eg: For AbpSuite tool it's "abp-suite", for ABP CLI tool it's "abp"</param>
public static bool IsGlobalToolInstalled(string toolCommandName)
{
string suitePath;
if (PlatformHelper.GetPlatform() == RuntimePlatform.LinuxOrMacOs)
{
suitePath = Environment
.ExpandEnvironmentVariables(
Path.Combine("%HOME%", ".dotnet", "tools", toolCommandName)
);
}
else
{
suitePath = Environment
.ExpandEnvironmentVariables(
Path.Combine(@"%USERPROFILE%", ".dotnet", "tools", toolCommandName + ".exe")
);
}
return File.Exists(suitePath);
}
}
}

51
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/PlatformHelper.cs

@ -0,0 +1,51 @@
using System;
using System.Runtime.InteropServices;
namespace Volo.Abp.Cli.Utils
{
public class PlatformHelper
{
public static OSPlatform GetOperatingSystem()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
//MAC
return OSPlatform.OSX;
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return OSPlatform.Linux;
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return OSPlatform.Windows;
}
throw new Exception("Cannot determine operating system!");
}
public static RuntimePlatform GetPlatform()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ||
RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return RuntimePlatform.LinuxOrMacOs;
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return RuntimePlatform.Windows;
}
throw new Exception("Cannot determine runtime platform!");
}
}
public enum RuntimePlatform
{
Windows = 1,
LinuxOrMacOs = 2
}
}

7
framework/src/Volo.Abp.Cli/Properties/launchSettings.json

@ -0,0 +1,7 @@
{
"profiles": {
"Volo.Abp.Cli": {
"commandName": "Project"
}
}
}

12
framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/AbpInterceptor.cs

@ -3,13 +3,7 @@
namespace Volo.Abp.DynamicProxy
{
public abstract class AbpInterceptor : IAbpInterceptor
{
public abstract void Intercept(IAbpMethodInvocation invocation);
public virtual Task InterceptAsync(IAbpMethodInvocation invocation)
{
Intercept(invocation);
return Task.CompletedTask;
}
}
{
public abstract Task InterceptAsync(IAbpMethodInvocation invocation);
}
}

2
framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/IAbpInterceptor.cs

@ -4,8 +4,6 @@ namespace Volo.Abp.DynamicProxy
{
public interface IAbpInterceptor
{
void Intercept(IAbpMethodInvocation invocation);
Task InterceptAsync(IAbpMethodInvocation invocation);
}
}

2
framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/IAbpMethodInvocation.cs

@ -19,8 +19,6 @@ namespace Volo.Abp.DynamicProxy
object ReturnValue { get; set; }
void Proceed();
Task ProceedAsync();
}
}

6
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo.Abp.Ddd.Application.Contracts.csproj

@ -13,8 +13,14 @@
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Volo\Abp\Application\Localization\Resources\AbpDdd\*.json" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Auditing\Volo.Abp.Auditing.csproj" />
<ProjectReference Include="..\Volo.Abp.Localization\Volo.Abp.Localization.csproj" />
</ItemGroup>
</Project>

22
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/AbpDddApplicationContractsModule.cs

@ -1,12 +1,30 @@
using Volo.Abp.Auditing;
using Volo.Abp.Application.Localization.Resources.AbpDdd;
using Volo.Abp.Auditing;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.Application
{
[DependsOn(
typeof(AbpAuditingModule)
typeof(AbpAuditingModule),
typeof(AbpLocalizationModule)
)]
public class AbpDddApplicationContractsModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpDddApplicationContractsModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<AbpDddResource>("en")
.AddVirtualJson("/Volo/Abp/Application/Localization/Resources/AbpDdd");
});
}
}
}

3
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/ILimitedResultRequest.cs

@ -6,7 +6,8 @@ namespace Volo.Abp.Application.Dtos
public interface ILimitedResultRequest
{
/// <summary>
/// Max expected result count.
/// Maximum result count should be returned.
/// This is generally used to limit result count on paging.
/// </summary>
int MaxResultCount { get; set; }
}

30
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/LimitedResultRequestDto.cs

@ -1,5 +1,8 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Microsoft.Extensions.Localization;
using Volo.Abp.Application.Localization.Resources.AbpDdd;
namespace Volo.Abp.Application.Dtos
{
@ -7,11 +10,36 @@ namespace Volo.Abp.Application.Dtos
/// Simply implements <see cref="ILimitedResultRequest"/>.
/// </summary>
[Serializable]
public class LimitedResultRequestDto : ILimitedResultRequest
public class LimitedResultRequestDto : ILimitedResultRequest, IValidatableObject
{
/// <summary>
/// Default value: 10.
/// </summary>
public static int DefaultMaxResultCount { get; set; } = 10;
/// <summary>
/// Maximum possible value of the <see cref="MaxResultCount"/>.
/// Default value: 1,000.
/// </summary>
public static int MaxMaxResultCount { get; set; } = 1000;
/// <summary>
/// Maximum result count should be returned.
/// This is generally used to limit result count on paging.
/// </summary>
[Range(1, int.MaxValue)]
public virtual int MaxResultCount { get; set; } = DefaultMaxResultCount;
public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var l = validationContext.GetService(typeof(IStringLocalizer<AbpDddResource>)) as IStringLocalizer<AbpDddResource>;
if (MaxResultCount > MaxMaxResultCount)
{
yield return new ValidationResult(
errorMessage:l?["MaxResultCountExceededExceptionMessage", nameof(MaxResultCount), MaxMaxResultCount, typeof(LimitedResultRequestDto).FullName, nameof(MaxMaxResultCount)],
new []{nameof(MaxResultCount)});
}
}
}
}

9
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/AbpDddResource.cs

@ -0,0 +1,9 @@
using Volo.Abp.Localization;
namespace Volo.Abp.Application.Localization.Resources.AbpDdd
{
[LocalizationResourceName("AbpDdd")]
public class AbpDddResource
{
}
}

6
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/en.json

@ -0,0 +1,6 @@
{
"culture": "en",
"texts": {
"MaxResultCountExceededExceptionMessage": "{0} can not be more than {1}! Increase {2}.{3} on the server side to allow more results."
}
}

6
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/tr.json

@ -0,0 +1,6 @@
{
"culture": "tr",
"texts": {
"MaxResultCountExceededExceptionMessage": "{0} en fazla {1} olabilir, daha büyük olamaz! Daha fazla sonuca izin vermek için {2}.{3}'ü sunucu tarafında artırın."
}
}

6
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/zh-Hans.json

@ -0,0 +1,6 @@
{
"culture": "zh-Hans",
"texts": {
"MaxResultCountExceededExceptionMessage": "{0}不能超过 {1}! 在服务器端增加{2}.{3}以获得更多结果."
}
}

70
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/BasicRepositoryBase.cs

@ -25,54 +25,28 @@ namespace Volo.Abp.Domain.Repositories
CancellationTokenProvider = NullCancellationTokenProvider.Instance;
}
public abstract TEntity Insert(TEntity entity, bool autoSave = false);
public abstract Task<TEntity> InsertAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default);
public virtual Task<TEntity> InsertAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
{
return Task.FromResult(Insert(entity, autoSave));
}
public abstract Task<TEntity> UpdateAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default);
public abstract TEntity Update(TEntity entity, bool autoSave = false);
public abstract Task DeleteAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default);
public virtual Task<TEntity> UpdateAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
{
return Task.FromResult(Update(entity));
}
public abstract Task<List<TEntity>> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default);
public abstract void Delete(TEntity entity, bool autoSave = false);
public virtual Task DeleteAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
{
Delete(entity);
return Task.CompletedTask;
}
public abstract Task<long> GetCountAsync(CancellationToken cancellationToken = default);
protected virtual CancellationToken GetCancellationToken(CancellationToken prefferedValue = default)
protected virtual CancellationToken GetCancellationToken(CancellationToken preferredValue = default)
{
return CancellationTokenProvider.FallbackToProvider(prefferedValue);
}
public abstract List<TEntity> GetList(bool includeDetails = false);
public virtual Task<List<TEntity>> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default)
{
return Task.FromResult(GetList(includeDetails));
}
public abstract long GetCount();
public virtual Task<long> GetCountAsync(CancellationToken cancellationToken = default)
{
return Task.FromResult(GetCount());
return CancellationTokenProvider.FallbackToProvider(preferredValue);
}
}
public abstract class BasicRepositoryBase<TEntity, TKey> : BasicRepositoryBase<TEntity>, IBasicRepository<TEntity, TKey>
where TEntity : class, IEntity<TKey>
{
public virtual TEntity Get(TKey id, bool includeDetails = true)
public virtual async Task<TEntity> GetAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default)
{
var entity = Find(id, includeDetails);
var entity = await FindAsync(id, includeDetails, cancellationToken);
if (entity == null)
{
@ -82,33 +56,17 @@ namespace Volo.Abp.Domain.Repositories
return entity;
}
public virtual Task<TEntity> GetAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default)
{
return Task.FromResult(Get(id, includeDetails));
}
public abstract TEntity Find(TKey id, bool includeDetails = true);
public virtual Task<TEntity> FindAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default)
{
return Task.FromResult(Find(id, includeDetails));
}
public virtual void Delete(TKey id, bool autoSave = false)
public abstract Task<TEntity> FindAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default);
public virtual async Task DeleteAsync(TKey id, bool autoSave = false, CancellationToken cancellationToken = default)
{
var entity = Find(id);
var entity = await FindAsync(id, cancellationToken: cancellationToken);
if (entity == null)
{
return;
}
Delete(entity);
}
public virtual Task DeleteAsync(TKey id, bool autoSave = false, CancellationToken cancellationToken = default)
{
Delete(id);
return Task.CompletedTask;
await DeleteAsync(entity, autoSave, cancellationToken);
}
}
}

42
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IBasicRepository.cs

@ -8,17 +8,6 @@ namespace Volo.Abp.Domain.Repositories
public interface IBasicRepository<TEntity> : IReadOnlyBasicRepository<TEntity>
where TEntity : class, IEntity
{
/// <summary>
/// Inserts a new entity.
/// </summary>
/// <param name="entity">Inserted entity</param>
/// <param name="autoSave">
/// Set true to automatically save entity to database.
/// This is useful for ORMs / database APIs those only save changes with an explicit method call, but you need to immediately save changes to the database.
/// </param>
[NotNull]
TEntity Insert([NotNull] TEntity entity, bool autoSave = false);
/// <summary>
/// Inserts a new entity.
/// </summary>
@ -31,17 +20,6 @@ namespace Volo.Abp.Domain.Repositories
[NotNull]
Task<TEntity> InsertAsync([NotNull] TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default);
/// <summary>
/// Updates an existing entity.
/// </summary>
/// <param name="entity">Entity</param>
/// <param name="autoSave">
/// Set true to automatically save changes to database.
/// This is useful for ORMs / database APIs those only save changes with an explicit method call, but you need to immediately save changes to the database.
/// </param>
[NotNull]
TEntity Update([NotNull] TEntity entity, bool autoSave = false);
/// <summary>
/// Updates an existing entity.
/// </summary>
@ -54,16 +32,6 @@ namespace Volo.Abp.Domain.Repositories
[NotNull]
Task<TEntity> UpdateAsync([NotNull] TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default);
/// <summary>
/// Deletes an entity.
/// </summary>
/// <param name="entity">Entity to be deleted</param>
/// <param name="autoSave">
/// Set true to automatically save changes to database.
/// This is useful for ORMs / database APIs those only save changes with an explicit method call, but you need to immediately save changes to the database.
/// </param>
void Delete([NotNull] TEntity entity, bool autoSave = false);
/// <summary>
/// Deletes an entity.
/// </summary>
@ -79,16 +47,6 @@ namespace Volo.Abp.Domain.Repositories
public interface IBasicRepository<TEntity, TKey> : IBasicRepository<TEntity>, IReadOnlyBasicRepository<TEntity, TKey>
where TEntity : class, IEntity<TKey>
{
/// <summary>
/// Deletes an entity by primary key.
/// </summary>
/// <param name="id">Primary key of the entity</param>
/// <param name="autoSave">
/// Set true to automatically save changes to database.
/// This is useful for ORMs / database APIs those only save changes with an explicit method call, but you need to immediately save changes to the database.
/// </param>
void Delete(TKey id, bool autoSave = false); //TODO: Return true if deleted
/// <summary>
/// Deletes an entity by primary key.
/// </summary>

31
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IReadOnlyBasicRepository.cs

@ -9,13 +9,6 @@ namespace Volo.Abp.Domain.Repositories
public interface IReadOnlyBasicRepository<TEntity> : IRepository
where TEntity : class, IEntity
{
/// <summary>
/// Gets a list of all the entities.
/// </summary>
/// <param name="includeDetails">Set true to include all children of this entity</param>
/// <returns>Entity</returns>
List<TEntity> GetList(bool includeDetails = false);
/// <summary>
/// Gets a list of all the entities.
/// </summary>
@ -24,11 +17,6 @@ namespace Volo.Abp.Domain.Repositories
/// <returns>Entity</returns>
Task<List<TEntity>> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default);
/// <summary>
/// Gets total count of all entities.
/// </summary>
long GetCount();
/// <summary>
/// Gets total count of all entities.
/// </summary>
@ -38,16 +26,6 @@ namespace Volo.Abp.Domain.Repositories
public interface IReadOnlyBasicRepository<TEntity, TKey> : IReadOnlyBasicRepository<TEntity>
where TEntity : class, IEntity<TKey>
{
/// <summary>
/// Gets an entity with given primary key.
/// Throws <see cref="EntityNotFoundException"/> if can not find an entity with given id.
/// </summary>
/// <param name="id">Primary key of the entity to get</param>
/// <param name="includeDetails">Set true to include all children of this entity</param>
/// <returns>Entity</returns>
[NotNull]
TEntity Get(TKey id, bool includeDetails = true);
/// <summary>
/// Gets an entity with given primary key.
/// Throws <see cref="EntityNotFoundException"/> if can not find an entity with given id.
@ -59,15 +37,6 @@ namespace Volo.Abp.Domain.Repositories
[NotNull]
Task<TEntity> GetAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default);
/// <summary>
/// Gets an entity with given primary key or null if not found.
/// </summary>
/// <param name="id">Primary key of the entity to get</param>
/// <param name="includeDetails">Set true to include all children of this entity</param>
/// <returns>Entity or null</returns>
[CanBeNull]
TEntity Find(TKey id, bool includeDetails = true);
/// <summary>
/// Gets an entity with given primary key or null if not found.
/// </summary>

13
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IRepository.cs

@ -18,19 +18,6 @@ namespace Volo.Abp.Domain.Repositories
public interface IRepository<TEntity> : IReadOnlyRepository<TEntity>, IBasicRepository<TEntity>
where TEntity : class, IEntity
{
/// <summary>
/// Deletes many entities by function.
/// Notice that: All entities fits to given predicate are retrieved and deleted.
/// This may cause major performance problems if there are too many entities with
/// given predicate.
/// </summary>
/// <param name="predicate">A condition to filter entities</param>
/// <param name="autoSave">
/// Set true to automatically save changes to database.
/// This is useful for ORMs / database APIs those only save changes with an explicit method call, but you need to immediately save changes to the database.
/// </param>
void Delete([NotNull] Expression<Func<TEntity, bool>> predicate, bool autoSave = false);
/// <summary>
/// Deletes many entities by function.
/// Notice that: All entities fits to given predicate are retrieved and deleted.

55
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryBase.cs

@ -46,19 +46,7 @@ namespace Volo.Abp.Domain.Repositories
protected abstract IQueryable<TEntity> GetQueryable();
public virtual void Delete(Expression<Func<TEntity, bool>> predicate, bool autoSave = false)
{
foreach (var entity in GetQueryable().Where(predicate).ToList())
{
Delete(entity, autoSave);
}
}
public virtual Task DeleteAsync(Expression<Func<TEntity, bool>> predicate, bool autoSave = false, CancellationToken cancellationToken = default)
{
Delete(predicate, autoSave);
return Task.CompletedTask;
}
public abstract Task DeleteAsync(Expression<Func<TEntity, bool>> predicate, bool autoSave = false, CancellationToken cancellationToken = default);
protected virtual TQueryable ApplyDataFilters<TQueryable>(TQueryable query)
where TQueryable : IQueryable<TEntity>
@ -81,50 +69,19 @@ namespace Volo.Abp.Domain.Repositories
public abstract class RepositoryBase<TEntity, TKey> : RepositoryBase<TEntity>, IRepository<TEntity, TKey>
where TEntity : class, IEntity<TKey>
{
public virtual TEntity Find(TKey id, bool includeDetails = true)
{
return includeDetails
? WithDetails().FirstOrDefault(EntityHelper.CreateEqualityExpressionForId<TEntity, TKey>(id))
: GetQueryable().FirstOrDefault(EntityHelper.CreateEqualityExpressionForId<TEntity, TKey>(id));
}
public abstract Task<TEntity> GetAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default);
public virtual TEntity Get(TKey id, bool includeDetails = true)
{
var entity = Find(id, includeDetails);
public abstract Task<TEntity> FindAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default);
if (entity == null)
{
throw new EntityNotFoundException(typeof(TEntity), id);
}
return entity;
}
public virtual Task<TEntity> GetAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default)
{
return Task.FromResult(Get(id, includeDetails));
}
public virtual Task<TEntity> FindAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default)
public virtual async Task DeleteAsync(TKey id, bool autoSave = false, CancellationToken cancellationToken = default)
{
return Task.FromResult(Find(id, includeDetails));
}
public virtual void Delete(TKey id, bool autoSave = false)
{
var entity = Find(id, includeDetails: false);
var entity = await FindAsync(id, cancellationToken: cancellationToken);
if (entity == null)
{
return;
}
Delete(entity, autoSave);
}
public virtual Task DeleteAsync(TKey id, bool autoSave = false, CancellationToken cancellationToken = default)
{
Delete(id, autoSave);
return Task.CompletedTask;
await DeleteAsync(entity, autoSave, cancellationToken);
}
}
}

73
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs

@ -40,18 +40,6 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore
);
}
public override TEntity Insert(TEntity entity, bool autoSave = false)
{
var savedEntity = DbSet.Add(entity).Entity;
if (autoSave)
{
DbContext.SaveChanges();
}
return savedEntity;
}
public override async Task<TEntity> InsertAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
{
var savedEntity = DbSet.Add(entity).Entity;
@ -64,20 +52,6 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore
return savedEntity;
}
public override TEntity Update(TEntity entity, bool autoSave = false)
{
DbContext.Attach(entity);
var updatedEntity = DbContext.Update(entity).Entity;
if (autoSave)
{
DbContext.SaveChanges();
}
return updatedEntity;
}
public override async Task<TEntity> UpdateAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
{
DbContext.Attach(entity);
@ -91,17 +65,7 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore
return updatedEntity;
}
public override void Delete(TEntity entity, bool autoSave = false)
{
DbSet.Remove(entity);
if (autoSave)
{
DbContext.SaveChanges();
}
}
public override async Task DeleteAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
{
DbSet.Remove(entity);
@ -112,13 +76,6 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore
}
}
public override List<TEntity> GetList(bool includeDetails = false)
{
return includeDetails
? WithDetails().ToList()
: DbSet.ToList();
}
public override async Task<List<TEntity>> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default)
{
return includeDetails
@ -126,11 +83,6 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore
: await DbSet.ToListAsync(GetCancellationToken(cancellationToken));
}
public override long GetCount()
{
return DbSet.LongCount();
}
public override async Task<long> GetCountAsync(CancellationToken cancellationToken = default)
{
return await DbSet.LongCountAsync(GetCancellationToken(cancellationToken));
@ -141,16 +93,6 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore
return DbSet.AsQueryable();
}
public override void Delete(Expression<Func<TEntity, bool>> predicate, bool autoSave = false)
{
base.Delete(predicate, autoSave);
if (autoSave)
{
DbContext.SaveChanges();
}
}
public override async Task DeleteAsync(Expression<Func<TEntity, bool>> predicate, bool autoSave = false, CancellationToken cancellationToken = default)
{
var entities = await GetQueryable()
@ -269,20 +211,9 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore
: await DbSet.FindAsync(new object[] { id }, GetCancellationToken(cancellationToken));
}
public virtual void Delete(TKey id, bool autoSave = false)
{
var entity = Find(id, includeDetails: false);
if (entity == null)
{
return;
}
Delete(entity, autoSave);
}
public virtual async Task DeleteAsync(TKey id, bool autoSave = false, CancellationToken cancellationToken = default)
{
var entity = await FindAsync(id, includeDetails: false, cancellationToken: cancellationToken);
var entity = await FindAsync(id, cancellationToken: cancellationToken);
if (entity == null)
{
return;

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

Loading…
Cancel
Save