diff --git a/.github/labeler.yml b/.github/labeler.yml
index 738b727317..cb0c9cddbd 100644
--- a/.github/labeler.yml
+++ b/.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/**/**/**/*
diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml
index e70e966d4a..f24ba57949 100644
--- a/.github/workflows/labeler.yml
+++ b/.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 }}
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
index 3ca5aa1e97..c83e5aa6a9 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
+++ b/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!"
}
}
\ No newline at end of file
diff --git a/common.props b/common.props
index 228cdcfbe2..1a273a3efe 100644
--- a/common.props
+++ b/common.props
@@ -1,7 +1,7 @@
latest
- 1.1.1
+ 2.0.0
$(NoWarn);CS1591
https://abp.io/assets/abp_nupkg.png
https://abp.io
diff --git a/docs/cs/Best-Practices/PostgreSQL-Integration.md b/docs/cs/Best-Practices/PostgreSQL-Integration.md
deleted file mode 100644
index 6bf8224f1e..0000000000
--- a/docs/cs/Best-Practices/PostgreSQL-Integration.md
+++ /dev/null
@@ -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`)
-
-
-
-#### 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
-````
-
-
diff --git a/docs/cs/CLI.md b/docs/cs/CLI.md
index cbf8006ad2..2779ba64f3 100644
--- a/docs/cs/CLI.md
+++ b/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.
diff --git a/docs/cs/EntityFrameworkCore-PostgreSQL-Integration.md b/docs/cs/EntityFrameworkCore-PostgreSQL-Integration.md
new file mode 100644
index 0000000000..9d4f685316
--- /dev/null
+++ b/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().UseSqlServer()` za `new DbContextOptionsBuilder().UseNpgsql()`
+
+
+### Odstranění stávajících migrací
+
+Smažte všechny stavající migrační soubory (včetně `DbContextModelSnapshot`)
+
+
+
+### Znovu vygenerujte počáteční migraci
+
+Nastavte správný spouštěcí projekt (obvykle web projekt)
+
+
+
+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**:
+
+
+
+Zmáčkněte F5 (nebo Ctrl+F5) ke spuštění aplikace. Výstup bude vypadat následovně:
+
+
+
+#### 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)
+
+
+
+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.
+
+
+
+> 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.
diff --git a/docs/cs/Getting-Started-Angular-Template.md b/docs/cs/Getting-Started-Angular-Template.md
index 5dfc65c7ec..ea5ef0a4bf 100644
--- a/docs/cs/Getting-Started-Angular-Template.md
+++ b/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**:

diff --git a/docs/cs/Getting-Started-AspNetCore-Application.md b/docs/cs/Getting-Started-AspNetCore-Application.md
index ffb2f556c6..0537b01579 100644
--- a/docs/cs/Getting-Started-AspNetCore-Application.md
+++ b/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+):
-
+
-2. Zvolte prázdnou šablonu
+2. Nakonfigurujte váš nový projekt:
-
+
-Můžete zvolit i jinou šablonu, ale pro demonstraci je lepší čístý projekt.
+3. Potvrďte kliknutím na tlačítko vytvořit
+
+
## 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();
-
- 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()`` přidává všechny služby definované ve všech modulech počínaje ``AppModule``.
+``services.AddApplication()`` 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();`` v třídě ``Startup`` následovně:
-
-````C#
-services.AddApplication(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()
- .Build();
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ })
+ .UseAutofac(); // Přidejte tento řádek
+ }
}
````
diff --git a/docs/cs/Index.md b/docs/cs/Index.md
index ac13bcbdb6..0424c7120b 100644
--- a/docs/cs/Index.md
+++ b/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ů:
diff --git a/docs/cs/docs-nav.json b/docs/cs/docs-nav.json
index 91badc73e9..85cbf43c9d 100644
--- a/docs/cs/docs-nav.json
+++ b/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"
}
]
},
diff --git a/docs/cs/images/authorization-new-permission-ui-hierarcy.png b/docs/cs/images/authorization-new-permission-ui-hierarcy.png
new file mode 100644
index 0000000000..078d67d50f
Binary files /dev/null and b/docs/cs/images/authorization-new-permission-ui-hierarcy.png differ
diff --git a/docs/cs/images/authorization-new-permission-ui-localized.png b/docs/cs/images/authorization-new-permission-ui-localized.png
new file mode 100644
index 0000000000..610ce39faf
Binary files /dev/null and b/docs/cs/images/authorization-new-permission-ui-localized.png differ
diff --git a/docs/cs/images/authorization-new-permission-ui.png b/docs/cs/images/authorization-new-permission-ui.png
new file mode 100644
index 0000000000..554f27e78d
Binary files /dev/null and b/docs/cs/images/authorization-new-permission-ui.png differ
diff --git a/docs/cs/images/create-aspnet-core-application.png b/docs/cs/images/create-aspnet-core-application.png
new file mode 100644
index 0000000000..5813cf38e9
Binary files /dev/null and b/docs/cs/images/create-aspnet-core-application.png differ
diff --git a/docs/cs/images/create-new-aspnet-core-application-v2.png b/docs/cs/images/create-new-aspnet-core-application-v2.png
new file mode 100644
index 0000000000..f8274ae2a4
Binary files /dev/null and b/docs/cs/images/create-new-aspnet-core-application-v2.png differ
diff --git a/docs/cs/images/select-empty-web-application-v2.png b/docs/cs/images/select-empty-web-application-v2.png
new file mode 100644
index 0000000000..da32f71857
Binary files /dev/null and b/docs/cs/images/select-empty-web-application-v2.png differ
diff --git a/docs/en/CLI.md b/docs/en/CLI.md
index 57bda25004..a1d3d51138 100644
--- a/docs/en/CLI.md
+++ b/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
+```
+
+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.
diff --git a/docs/en/Best-Practices/PostgreSQL-Integration.md b/docs/en/EntityFrameworkCore-PostgreSQL-Integration.md
similarity index 100%
rename from docs/en/Best-Practices/PostgreSQL-Integration.md
rename to docs/en/EntityFrameworkCore-PostgreSQL-Integration.md
diff --git a/docs/en/Modules/Docs.md b/docs/en/Modules/Docs.md
index ac85978740..0a74d7ebde 100644
--- a/docs/en/Modules/Docs.md
+++ b/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]( ) 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**.
+
+
+
+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]( ) 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.
diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json
index 863290126a..db194177a9 100644
--- a/docs/en/docs-nav.json
+++ b/docs/en/docs-nav.json
@@ -265,7 +265,7 @@
"items": [
{
"text": "PostgreSQL Integration",
- "path": "Best-Practices/PostgreSQL-Integration.md"
+ "path": "EntityFrameworkCore-PostgreSQL-Integration.md"
}
]
},
diff --git a/docs/en/images/docs-section-ui.png b/docs/en/images/docs-section-ui.png
new file mode 100644
index 0000000000..7856454e5d
Binary files /dev/null and b/docs/en/images/docs-section-ui.png differ
diff --git a/docs/pt-BR/docs-nav.json b/docs/pt-BR/docs-nav.json
index 90b29626b8..8e7eaf62af 100644
--- a/docs/pt-BR/docs-nav.json
+++ b/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"
}
]
},
diff --git a/docs/zh-Hans/Best-Practices/PostgreSQL-Integration.md b/docs/zh-Hans/EntityFrameworkCore-PostgreSQL-Integration.md
similarity index 100%
rename from docs/zh-Hans/Best-Practices/PostgreSQL-Integration.md
rename to docs/zh-Hans/EntityFrameworkCore-PostgreSQL-Integration.md
diff --git a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md
index c9a56447ba..f9314e5030 100644
--- a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md
+++ b/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
````
* 框架定义应用程序服务的接口不是必需的. 但是,它被建议作为最佳实践.
-* `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,
IBookAppService
{
@@ -268,7 +268,7 @@ namespace Acme.BookStore
}
````
-* `BookAppService`继承了`AsyncCrudAppService<...>`.`AsyncCrudAppService<...>`实现了上面定义的CRUD方法.
+* `BookAppService`继承了`CrudAppService<...>`.它实现了上面定义的CRUD方法.
* `BookAppService`注入`IRepository `,这是`Book`实体的默认仓储. ABP自动为每个聚合根(或实体)创建默认仓储. 请参阅[仓储文档](../../Repositories.md)
* `BookAppService`使用`IObjectMapper`将`Book`对象转换为`BookDto`对象, 将`CreateUpdateBookDto`对象转换为`Book`对象. 启动模板使用[AutoMapper](http://automapper.org/)库作为对象映射提供程序. 你之前定义了映射, 因此它将按预期工作.
diff --git a/docs/zh-Hans/docs-nav.json b/docs/zh-Hans/docs-nav.json
index 3c6c58cd68..dd740f6c3b 100644
--- a/docs/zh-Hans/docs-nav.json
+++ b/docs/zh-Hans/docs-nav.json
@@ -254,7 +254,7 @@
"items": [
{
"text": "PostgreSQL 集成",
- "path": "Best-Practices/PostgreSQL-Integration.md"
+ "path": "EntityFrameworkCore-PostgreSQL-Integration.md"
}
]
},
diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/MultipleClaimAction.cs b/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/MultipleClaimAction.cs
index 074cc936d0..0c3b05090c 100644
--- a/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/MultipleClaimAction.cs
+++ b/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;
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/CachedApplicationConfigurationClient.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/CachedApplicationConfigurationClient.cs
index 838150fd49..1fbb72bb3e 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/CachedApplicationConfigurationClient.cs
+++ b/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
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteLocalizationContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteLocalizationContributor.cs
index 79033f3679..d60256a501 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteLocalizationContributor.cs
+++ b/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 GetResourceOrNull()
{
- var applicationConfigurationDto = AsyncHelper.RunSync(
- () => _applicationConfigurationClient.GetAsync()
- );
+ var applicationConfigurationDto = AsyncHelper.RunSync(() => _applicationConfigurationClient.GetAsync());
var resource = applicationConfigurationDto
.Localization.Values
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemotePermissionChecker.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemotePermissionChecker.cs
index cbddb7c3c7..18f5272e7b 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemotePermissionChecker.cs
+++ b/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 IsGrantedAsync(ClaimsPrincipal claimsPrincipal, string name)
+ public async Task IsGrantedAsync(ClaimsPrincipal claimsPrincipal, string name)
{
/* This provider always works for the current principal. */
- return IsGrantedAsync(name);
+ return await IsGrantedAsync(name);
}
}
}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteTenantStore.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteTenantStore.cs
index 718abbb6a9..236387823c 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteTenantStore.cs
+++ b/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)
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/cs.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/cs.json
index 7151dc73f3..5887243cb4 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/cs.json
+++ b/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"
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Views/Error/Default.cshtml b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Views/Error/Default.cshtml
index f1c6bb91d3..cfd16a2b8c 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Views/Error/Default.cshtml
+++ b/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 L
@{
var errorMessage = Model.ErrorInfo.Message;
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs
index f3af9182ba..5015d146e8 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs
+++ b/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 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 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 GetSettingConfigAsync()
{
+ Logger.LogDebug("Executing AbpApplicationConfigurationAppService.GetSettingConfigAsync()");
+
var result = new ApplicationSettingConfigurationDto
{
Values = new Dictionary()
@@ -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 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;
}
}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationController.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationController.cs
index 98e09ff9a8..67672986be 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationController.cs
+++ b/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 GetAsync()
+ public async Task GetAsync()
{
- return _applicationConfigurationAppService.GetAsync();
+ return await _applicationConfigurationAppService.GetAsync();
}
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationScriptController.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationScriptController.cs
index bce46bab44..da5dbe902b 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationScriptController.cs
+++ b/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 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)
diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs
index 75d903557e..a7dfa5044c 100644
--- a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs
+++ b/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(_requestLocalizationOptionsProvider.GetLocalizationOptions()),
+ new OptionsWrapper(
+ await _requestLocalizationOptionsProvider.GetLocalizationOptionsAsync()
+ ),
_loggerFactory
);
diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs
index 730f6e3937..c30eafb9d0 100644
--- a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs
+++ b/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 _lazyRequestLocalizationOptions;
+ private readonly IServiceScopeFactory _serviceProviderFactory;
+ private readonly SemaphoreSlim _syncSemaphore;
+ private Action _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 optionsAction = null)
{
- _lazyRequestLocalizationOptions = new Lazy(() =>
+ _optionsAction = optionsAction;
+ }
+
+ public async Task GetLocalizationOptionsAsync()
+ {
+ if (_requestLocalizationOptions == null)
{
- using (var serviceScope = _serviceProvider.CreateScope())
+ using (await _syncSemaphore.LockAsync())
{
- var languageProvider = serviceScope.ServiceProvider.GetRequiredService();
- var settingProvider = serviceScope.ServiceProvider.GetRequiredService();
+ using (var serviceScope = _serviceProviderFactory.CreateScope())
+ {
+ var languageProvider = serviceScope.ServiceProvider.GetRequiredService();
+ var settingProvider = serviceScope.ServiceProvider.GetRequiredService();
- 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 languages)
diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/IAbpRequestLocalizationOptionsProvider.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/IAbpRequestLocalizationOptionsProvider.cs
index 5179bb48ee..86cd3153f7 100644
--- a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/IAbpRequestLocalizationOptionsProvider.cs
+++ b/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 optionsAction = null);
- RequestLocalizationOptions GetLocalizationOptions();
+ Task GetLocalizationOptionsAsync();
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptor.cs b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptor.cs
index 434ddc9d16..5a401a218e 100644
--- a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptor.cs
+++ b/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))
diff --git a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingManager.cs b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingManager.cs
index d314d31799..070684f48a 100644
--- a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingManager.cs
+++ b/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();
diff --git a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditLogSaveHandle.cs b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditLogSaveHandle.cs
index 596f67523a..4709b745d2 100644
--- a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditLogSaveHandle.cs
+++ b/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();
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditingStore.cs b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditingStore.cs
index 101ec8b03e..7166af642b 100644
--- a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditingStore.cs
+++ b/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);
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/SimpleLogAuditingStore.cs b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/SimpleLogAuditingStore.cs
index 8067ede5c5..eeb6c7803c 100644
--- a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/SimpleLogAuditingStore.cs
+++ b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/SimpleLogAuditingStore.cs
@@ -15,14 +15,9 @@ namespace Volo.Abp.Auditing
Logger = NullLogger.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);
}
}
diff --git a/framework/src/Volo.Abp.Authorization/Microsoft/AspNetCore/Authorization/AbpAuthorizationServiceExtensions.cs b/framework/src/Volo.Abp.Authorization/Microsoft/AspNetCore/Authorization/AbpAuthorizationServiceExtensions.cs
index 9d16a6a55c..d682d4f0c8 100644
--- a/framework/src/Volo.Abp.Authorization/Microsoft/AspNetCore/Authorization/AbpAuthorizationServiceExtensions.cs
+++ b/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 AuthorizeAsync(this IAuthorizationService authorizationService, string policyName)
+ public static async Task AuthorizeAsync(this IAuthorizationService authorizationService, string policyName)
{
- return AuthorizeAsync(
+ return await AuthorizeAsync(
authorizationService,
- authorizationService.AsAbpAuthorizationService().CurrentPrincipal,
+ null,
policyName
);
}
- public static Task AuthorizeAsync(this IAuthorizationService authorizationService, object resource, IAuthorizationRequirement requirement)
+ public static async Task AuthorizeAsync(this IAuthorizationService authorizationService, object resource, IAuthorizationRequirement requirement)
{
- return authorizationService.AuthorizeAsync(
+ return await authorizationService.AuthorizeAsync(
authorizationService.AsAbpAuthorizationService().CurrentPrincipal,
resource,
requirement
);
}
- public static Task AuthorizeAsync(this IAuthorizationService authorizationService, object resource, AuthorizationPolicy policy)
+ public static async Task AuthorizeAsync(this IAuthorizationService authorizationService, object resource, AuthorizationPolicy policy)
{
- return authorizationService.AuthorizeAsync(
+ return await authorizationService.AuthorizeAsync(
authorizationService.AsAbpAuthorizationService().CurrentPrincipal,
resource,
policy
);
}
- public static Task AuthorizeAsync(this IAuthorizationService authorizationService, AuthorizationPolicy policy)
+ public static async Task AuthorizeAsync(this IAuthorizationService authorizationService, AuthorizationPolicy policy)
{
- return AuthorizeAsync(authorizationService, authorizationService.AsAbpAuthorizationService().CurrentPrincipal,
+ return await AuthorizeAsync(
+ authorizationService,
+ null,
policy
);
}
- public static Task AuthorizeAsync(this IAuthorizationService authorizationService, object resource, IEnumerable requirements)
+ public static async Task AuthorizeAsync(this IAuthorizationService authorizationService, object resource, IEnumerable requirements)
{
- return authorizationService.AuthorizeAsync(
+ return await authorizationService.AuthorizeAsync(
authorizationService.AsAbpAuthorizationService().CurrentPrincipal,
resource,
requirements
);
}
- public static Task AuthorizeAsync(this IAuthorizationService authorizationService, object resource, string policyName)
+ public static async Task AuthorizeAsync(this IAuthorizationService authorizationService, object resource, string policyName)
{
- return authorizationService.AuthorizeAsync(
+ return await authorizationService.AuthorizeAsync(
authorizationService.AsAbpAuthorizationService().CurrentPrincipal,
resource,
policyName
diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AuthorizationInterceptor.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AuthorizationInterceptor.cs
index 74314e815d..44466884dd 100644
--- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AuthorizationInterceptor.cs
+++ b/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);
diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionChecker.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionChecker.cs
index a87a22fcf5..51c8530ee6 100644
--- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionChecker.cs
+++ b/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 IsGrantedAsync(string name)
+ public virtual async Task IsGrantedAsync(string name)
{
- return IsGrantedAsync(PrincipalAccessor.Principal, name);
+ return await IsGrantedAsync(PrincipalAccessor.Principal, name);
}
public virtual async Task IsGrantedAsync(ClaimsPrincipal claimsPrincipal, string name)
diff --git a/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs b/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs
index 0d5c7612b2..96caf956b1 100644
--- a/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs
+++ b/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)
);
}
diff --git a/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/IJobQueueManager.cs b/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/IJobQueueManager.cs
index da560d1ed2..8cafb8c247 100644
--- a/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/IJobQueueManager.cs
+++ b/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 Get();
+ Task> GetAsync();
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueueManager.cs b/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueueManager.cs
index 73b7c21d2a..f07564ad5a 100644
--- a/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueueManager.cs
+++ b/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 options,
IServiceProvider serviceProvider)
@@ -24,6 +27,7 @@ namespace Volo.Abp.BackgroundJobs.RabbitMQ
ServiceProvider = serviceProvider;
Options = options.Value;
JobQueues = new ConcurrentDictionary();
+ 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 Get()
+ public async Task> GetAsync()
{
var jobConfiguration = Options.GetJob(typeof(TArgs));
- return (IJobQueue)JobQueues.GetOrAdd(jobConfiguration.JobName, _ =>
+ if (JobQueues.TryGetValue(jobConfiguration.JobName, out var jobQueue))
+ {
+ return (IJobQueue)jobQueue;
+ }
+
+ using (await SyncSemaphore.LockAsync())
{
- var jobQueue = (IRunnable) ServiceProvider
- .GetRequiredService(typeof(IJobQueue<>)
- .MakeGenericType(typeof(TArgs)));
+ if (JobQueues.TryGetValue(jobConfiguration.JobName, out jobQueue))
+ {
+ return (IJobQueue)jobQueue;
+ }
- AsyncHelper.RunSync(() => jobQueue.StartAsync());
+ jobQueue = (IJobQueue)ServiceProvider
+ .GetRequiredService(typeof(IJobQueue<>).MakeGenericType(typeof(TArgs)));
- return jobQueue;
- });
+ await jobQueue.StartAsync();
+
+ JobQueues.TryAdd(jobConfiguration.JobName, jobQueue);
+
+ return (IJobQueue)jobQueue;
+ }
}
}
}
diff --git a/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/RabbitMqBackgroundJobManager.cs b/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/RabbitMqBackgroundJobManager.cs
index c2976e43fb..f70d553128 100644
--- a/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/RabbitMqBackgroundJobManager.cs
+++ b/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 EnqueueAsync(
+ public async Task EnqueueAsync(
TArgs args,
BackgroundJobPriority priority = BackgroundJobPriority.Normal,
TimeSpan? delay = null)
{
- return _jobQueueManager
- .Get()
- .EnqueueAsync(args, priority, delay);
+ var jobQueue = await _jobQueueManager.GetAsync();
+ return await jobQueue.EnqueueAsync(args, priority, delay);
}
}
}
diff --git a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs
index 03b5cb73e4..74a3f6128f 100644
--- a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs
+++ b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs
@@ -36,7 +36,7 @@ namespace Volo.Abp.BackgroundJobs
{
var store = scope.ServiceProvider.GetRequiredService();
- 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)
{
diff --git a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/IBackgroundJobStore.cs b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/IBackgroundJobStore.cs
index f909b3846d..839156c225 100644
--- a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/IBackgroundJobStore.cs
+++ b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/IBackgroundJobStore.cs
@@ -9,13 +9,6 @@ namespace Volo.Abp.BackgroundJobs
///
public interface IBackgroundJobStore
{
- ///
- /// Gets a BackgroundJobInfo based on the given jobId.
- ///
- /// The Job Unique Identifier.
- /// The BackgroundJobInfo object.
- BackgroundJobInfo Find(Guid jobId);
-
///
/// Gets a BackgroundJobInfo based on the given jobId.
///
@@ -23,27 +16,12 @@ namespace Volo.Abp.BackgroundJobs
/// The BackgroundJobInfo object.
Task FindAsync(Guid jobId);
- ///
- /// Inserts a background job.
- ///
- /// Job information.
- void Insert(BackgroundJobInfo jobInfo);
-
///
/// Inserts a background job.
///
/// Job information.
Task InsertAsync(BackgroundJobInfo jobInfo);
- ///
- /// Gets waiting jobs. It should get jobs based on these:
- /// Conditions: !IsAbandoned And NextTryTime <= Clock.Now.
- /// Order by: Priority DESC, TryCount ASC, NextTryTime ASC.
- /// Maximum result: .
- ///
- /// Maximum result count.
- List GetWaitingJobs(int maxResultCount);
-
///
/// Gets waiting jobs. It should get jobs based on these:
/// Conditions: !IsAbandoned And NextTryTime <= Clock.Now.
@@ -53,24 +31,12 @@ namespace Volo.Abp.BackgroundJobs
/// Maximum result count.
Task> GetWaitingJobsAsync(int maxResultCount);
- ///
- /// Deletes a job.
- ///
- /// The Job Unique Identifier.
- void Delete(Guid jobId);
-
///
/// Deletes a job.
///
/// The Job Unique Identifier.
Task DeleteAsync(Guid jobId);
- ///
- /// Updates a job.
- ///
- /// Job information.
- void Update(BackgroundJobInfo jobInfo);
-
///
/// Updates a job.
///
diff --git a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/InMemoryBackgroundJobStore.cs b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/InMemoryBackgroundJobStore.cs
index 30dd7fe090..cafe75b539 100644
--- a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/InMemoryBackgroundJobStore.cs
+++ b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/InMemoryBackgroundJobStore.cs
@@ -23,21 +23,11 @@ namespace Volo.Abp.BackgroundJobs
_jobs = new ConcurrentDictionary();
}
- public BackgroundJobInfo Find(Guid jobId)
- {
- return _jobs.GetOrDefault(jobId);
- }
-
public virtual Task 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 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> 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)
diff --git a/framework/src/Volo.Abp.Castle.Core/Volo.Abp.Castle.Core.csproj b/framework/src/Volo.Abp.Castle.Core/Volo.Abp.Castle.Core.csproj
index adcf4f8c2f..3d01363064 100644
--- a/framework/src/Volo.Abp.Castle.Core/Volo.Abp.Castle.Core.csproj
+++ b/framework/src/Volo.Abp.Castle.Core/Volo.Abp.Castle.Core.csproj
@@ -15,6 +15,7 @@
+
diff --git a/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/AbpCastleCoreModule.cs b/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/AbpCastleCoreModule.cs
index 0f9a10bda1..0cb59767a4 100644
--- a/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/AbpCastleCoreModule.cs
+++ b/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<>));
}
}
}
diff --git a/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/AbpAsyncDeterminationInterceptor.cs b/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/AbpAsyncDeterminationInterceptor.cs
new file mode 100644
index 0000000000..4f852ce475
--- /dev/null
+++ b/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 : AsyncDeterminationInterceptor
+ where TInterceptor : IAbpInterceptor
+ {
+ public AbpAsyncDeterminationInterceptor(TInterceptor abpInterceptor)
+ : base(new CastleAsyncAbpInterceptorAdapter(abpInterceptor))
+ {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpInterceptorAdapter.cs b/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpInterceptorAdapter.cs
deleted file mode 100644
index edb52aff86..0000000000
--- a/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpInterceptorAdapter.cs
+++ /dev/null
@@ -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 : IInterceptor
- where TInterceptor : IAbpInterceptor
- {
- private static readonly MethodInfo MethodExecuteWithoutReturnValueAsync =
- typeof(CastleAbpInterceptorAdapter)
- .GetMethod(
- nameof(ExecuteWithoutReturnValueAsync),
- BindingFlags.NonPublic | BindingFlags.Instance
- );
-
- private static readonly MethodInfo MethodExecuteWithReturnValueAsync =
- typeof(CastleAbpInterceptorAdapter)
- .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 ExecuteWithReturnValueAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo)
- {
- await Task.Yield();
-
- await _abpInterceptor.InterceptAsync(
- new CastleAbpMethodInvocationAdapter(invocation, proceedInfo)
- );
-
- return await (Task)invocation.ReturnValue;
- }
- }
-}
diff --git a/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapter.cs b/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapter.cs
index 0963da406b..89f3713521 100644
--- a/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapter.cs
+++ b/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 ArgumentsDictionary => _lazyArgumentsDictionary.Value;
- private readonly Lazy> _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 Proceed { get; }
- public CastleAbpMethodInvocationAdapter(IInvocation invocation, IInvocationProceedInfo proceedInfo)
+ public CastleAbpMethodInvocationAdapter(IInvocation invocation, IInvocationProceedInfo proceedInfo,
+ Func proceed)
+ : base(invocation)
{
- Invocation = invocation;
ProceedInfo = proceedInfo;
-
- _lazyArgumentsDictionary = new Lazy>(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 GetArgumentsDictionary()
- {
- var dict = new Dictionary();
-
- 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);
}
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapterBase.cs b/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapterBase.cs
new file mode 100644
index 0000000000..09609699a8
--- /dev/null
+++ b/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 ArgumentsDictionary => _lazyArgumentsDictionary.Value;
+ private readonly Lazy> _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>(GetArgumentsDictionary);
+ }
+
+ public abstract Task ProceedAsync();
+
+ private IReadOnlyDictionary GetArgumentsDictionary()
+ {
+ var dict = new Dictionary();
+
+ var methodParameters = Method.GetParameters();
+ for (int i = 0; i < methodParameters.Length; i++)
+ {
+ dict[methodParameters[i].Name] = Invocation.Arguments[i];
+ }
+
+ return dict;
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapterWithReturnValue.cs b/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapterWithReturnValue.cs
new file mode 100644
index 0000000000..bf91102337
--- /dev/null
+++ b/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 : CastleAbpMethodInvocationAdapterBase, IAbpMethodInvocation
+ {
+ protected IInvocationProceedInfo ProceedInfo { get; }
+ protected Func> Proceed { get; }
+
+ public CastleAbpMethodInvocationAdapterWithReturnValue(IInvocation invocation,
+ IInvocationProceedInfo proceedInfo,
+ Func> proceed)
+ : base(invocation)
+ {
+ ProceedInfo = proceedInfo;
+ Proceed = proceed;
+ }
+
+ public override async Task ProceedAsync()
+ {
+ ReturnValue = await Proceed(Invocation, ProceedInfo);
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAsyncAbpInterceptorAdapter.cs b/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAsyncAbpInterceptorAdapter.cs
new file mode 100644
index 0000000000..8a0c4fdd45
--- /dev/null
+++ b/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 : AsyncInterceptorBase
+ where TInterceptor : IAbpInterceptor
+ {
+ private readonly TInterceptor _abpInterceptor;
+
+ public CastleAsyncAbpInterceptorAdapter(TInterceptor abpInterceptor)
+ {
+ _abpInterceptor = abpInterceptor;
+ }
+
+ protected override async Task InterceptAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func proceed)
+ {
+ await _abpInterceptor.InterceptAsync(
+ new CastleAbpMethodInvocationAdapter(invocation, proceedInfo, proceed)
+ );
+ }
+
+ protected override async Task InterceptAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func> proceed)
+ {
+ var adapter = new CastleAbpMethodInvocationAdapterWithReturnValue(invocation, proceedInfo, proceed);
+
+ await _abpInterceptor.InterceptAsync(
+ adapter
+ );
+
+ return (TResult)adapter.ReturnValue;
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj b/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj
index 46f3d32d6a..37a9f54748 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj
+++ b/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj
@@ -19,6 +19,8 @@
+
+
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs
index a616d29409..34bf95fdf1 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs
+++ b/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(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);
});
}
}
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs
index f02f03d502..436e169aad 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs
+++ b/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 GetCurrentCliVersion(string toolPath, Assembly assembly)
+ private static async Task 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
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliUrls.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliUrls.cs
index 3c034d5702..3081c77cb5 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliUrls.cs
+++ b/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";
+ }
}
}
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs
index a7afbfa87d..58adc65fc4 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs
+++ b/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)
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs
index 211d20d5e1..03e228f255 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs
+++ b/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)
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GetSourceCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GetSourceCommand.cs
index 97dfe23944..e1536c2973 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GetSourceCommand.cs
+++ b/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
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/HelpCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/HelpCommand.cs
index dd9145e8db..2da6b82c8a 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/HelpCommand.cs
+++ b/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 `";
}
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs
index 5efbc358f0..fe9ed2d98f 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs
+++ b/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
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LogoutCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LogoutCommand.cs
index d3024635fb..464d40e74d 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LogoutCommand.cs
+++ b/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 + ".";
}
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs
index 44c1789907..9cfa702fd7 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs
+++ b/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
}
}
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SuiteCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SuiteCommand.cs
new file mode 100644
index 0000000000..a47a865617
--- /dev/null
+++ b/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 Logger { get; set; }
+ private readonly IApiKeyService _apiKeyService;
+
+ public SuiteCommand(IApiKeyService apiKeyService)
+ {
+ _apiKeyService = apiKeyService;
+ Logger = NullLogger.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 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 \"."
+ : "You are not signed in to commercial.abp.io. Use the CLI command \"abp login \" 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(" (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.";
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs
index a1775bb987..d201790c94 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs
+++ b/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 options)
+ NpmPackagesUpdater npmPackagesUpdater)
{
_nugetPackagesVersionUpdater = nugetPackagesVersionUpdater;
_npmPackagesUpdater = npmPackagesUpdater;
- _cliAnalyticsCollect = cliAnalyticsCollect;
- _jsonSerializer = jsonSerializer;
- _options = options.Value;
Logger = NullLogger.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
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Http/CliHttpClient.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Http/CliHttpClient.cs
index bc0b39a85a..81c64a3b5f 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Http/CliHttpClient.cs
+++ b/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);
}
}
}
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/AbpIoApiKeyService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/AbpIoApiKeyService.cs
index c8f221b73c..1b9539d012 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/AbpIoApiKeyService.cs
+++ b/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 _logger;
- public AbpIoApiKeyService(IJsonSerializer jsonSerializer, IRemoteServiceExceptionHandler remoteServiceExceptionHandler)
+ public AbpIoApiKeyService(IJsonSerializer jsonSerializer, IRemoteServiceExceptionHandler remoteServiceExceptionHandler, ILogger logger)
{
JsonSerializer = jsonSerializer;
RemoteServiceExceptionHandler = remoteServiceExceptionHandler;
+ _logger = logger;
}
public async Task 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)
{
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs
index 700303006b..1a067243d5 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs
@@ -32,7 +32,7 @@ namespace Volo.Abp.Cli.NuGet
public async Task 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" :
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/RemoteServiceExceptionHandler.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/RemoteServiceExceptionHandler.cs
index fe41577583..744641bb8a 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/RemoteServiceExceptionHandler.cs
+++ b/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 GetAbpRemoteServiceErrorAsync(HttpResponseMessage responseMessage)
{
- var errorResult = _jsonSerializer.Deserialize
- (
- await responseMessage.Content.ReadAsStringAsync()
- );
+ RemoteServiceErrorResponse errorResult;
+ try
+ {
+ errorResult = _jsonSerializer.Deserialize
+ (
+ 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(", ") + ".");
}
}
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/CmdHelper.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/CmdHelper.cs
index 0c7c9fc6c0..b871c295f6 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/CmdHelper.cs
+++ b/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";
}
}
}
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/GlobalToolHelper.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/GlobalToolHelper.cs
new file mode 100644
index 0000000000..8424262324
--- /dev/null
+++ b/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
+ {
+ ///
+ /// Checks whether the tool is installed or not.
+ ///
+ /// Eg: For AbpSuite tool it's "abp-suite", for ABP CLI tool it's "abp"
+ 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);
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/PlatformHelper.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/PlatformHelper.cs
new file mode 100644
index 0000000000..09d2481782
--- /dev/null
+++ b/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
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Cli/Properties/launchSettings.json b/framework/src/Volo.Abp.Cli/Properties/launchSettings.json
new file mode 100644
index 0000000000..e7f99eea04
--- /dev/null
+++ b/framework/src/Volo.Abp.Cli/Properties/launchSettings.json
@@ -0,0 +1,7 @@
+{
+ "profiles": {
+ "Volo.Abp.Cli": {
+ "commandName": "Project"
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/AbpInterceptor.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/AbpInterceptor.cs
index 8874beafcf..51ab36efc4 100644
--- a/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/AbpInterceptor.cs
+++ b/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);
+ }
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/IAbpInterceptor.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/IAbpInterceptor.cs
index 0d953d9c73..c20cb01277 100644
--- a/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/IAbpInterceptor.cs
+++ b/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);
}
}
diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/IAbpMethodInvocation.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/IAbpMethodInvocation.cs
index 37a36ac05f..17a89be467 100644
--- a/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/IAbpMethodInvocation.cs
+++ b/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();
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo.Abp.Ddd.Application.Contracts.csproj b/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo.Abp.Ddd.Application.Contracts.csproj
index 0b6eaee362..6f1674f8ce 100644
--- a/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo.Abp.Ddd.Application.Contracts.csproj
+++ b/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo.Abp.Ddd.Application.Contracts.csproj
@@ -13,8 +13,14 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/AbpDddApplicationContractsModule.cs b/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/AbpDddApplicationContractsModule.cs
index e107072221..3166152e89 100644
--- a/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/AbpDddApplicationContractsModule.cs
+++ b/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(options =>
+ {
+ options.FileSets.AddEmbedded();
+ });
+
+ Configure(options =>
+ {
+ options.Resources
+ .Add("en")
+ .AddVirtualJson("/Volo/Abp/Application/Localization/Resources/AbpDdd");
+ });
+ }
}
}
diff --git a/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/ILimitedResultRequest.cs b/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/ILimitedResultRequest.cs
index d0088fe155..36af42363c 100644
--- a/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/ILimitedResultRequest.cs
+++ b/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
{
///
- /// Max expected result count.
+ /// Maximum result count should be returned.
+ /// This is generally used to limit result count on paging.
///
int MaxResultCount { get; set; }
}
diff --git a/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/LimitedResultRequestDto.cs b/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/LimitedResultRequestDto.cs
index 0931d090f3..9e4375051d 100644
--- a/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/LimitedResultRequestDto.cs
+++ b/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 .
///
[Serializable]
- public class LimitedResultRequestDto : ILimitedResultRequest
+ public class LimitedResultRequestDto : ILimitedResultRequest, IValidatableObject
{
+ ///
+ /// Default value: 10.
+ ///
public static int DefaultMaxResultCount { get; set; } = 10;
+ ///
+ /// Maximum possible value of the .
+ /// Default value: 1,000.
+ ///
+ public static int MaxMaxResultCount { get; set; } = 1000;
+
+ ///
+ /// Maximum result count should be returned.
+ /// This is generally used to limit result count on paging.
+ ///
[Range(1, int.MaxValue)]
public virtual int MaxResultCount { get; set; } = DefaultMaxResultCount;
+
+ public virtual IEnumerable Validate(ValidationContext validationContext)
+ {
+ var l = validationContext.GetService(typeof(IStringLocalizer)) as IStringLocalizer;
+
+ if (MaxResultCount > MaxMaxResultCount)
+ {
+ yield return new ValidationResult(
+ errorMessage:l?["MaxResultCountExceededExceptionMessage", nameof(MaxResultCount), MaxMaxResultCount, typeof(LimitedResultRequestDto).FullName, nameof(MaxMaxResultCount)],
+ new []{nameof(MaxResultCount)});
+ }
+ }
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/AbpDddResource.cs b/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/AbpDddResource.cs
new file mode 100644
index 0000000000..666a962a22
--- /dev/null
+++ b/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
+ {
+ }
+}
diff --git a/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/en.json b/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/en.json
new file mode 100644
index 0000000000..2c514e6c18
--- /dev/null
+++ b/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."
+ }
+}
diff --git a/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/tr.json b/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/tr.json
new file mode 100644
index 0000000000..428f348427
--- /dev/null
+++ b/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."
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/zh-Hans.json b/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/zh-Hans.json
new file mode 100644
index 0000000000..0bc563e702
--- /dev/null
+++ b/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}以获得更多结果."
+ }
+}
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/BasicRepositoryBase.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/BasicRepositoryBase.cs
index 05fc760182..d13d52ed97 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/BasicRepositoryBase.cs
+++ b/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 InsertAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default);
- public virtual Task InsertAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
- {
- return Task.FromResult(Insert(entity, autoSave));
- }
+ public abstract Task 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 UpdateAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
- {
- return Task.FromResult(Update(entity));
- }
+ public abstract Task> 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 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 GetList(bool includeDetails = false);
-
- public virtual Task> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default)
- {
- return Task.FromResult(GetList(includeDetails));
- }
-
- public abstract long GetCount();
-
- public virtual Task GetCountAsync(CancellationToken cancellationToken = default)
- {
- return Task.FromResult(GetCount());
+ return CancellationTokenProvider.FallbackToProvider(preferredValue);
}
}
public abstract class BasicRepositoryBase : BasicRepositoryBase, IBasicRepository
where TEntity : class, IEntity
{
- public virtual TEntity Get(TKey id, bool includeDetails = true)
+ public virtual async Task 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 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 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 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);
}
}
}
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IBasicRepository.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IBasicRepository.cs
index f3644bbe4a..6b62691ed8 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IBasicRepository.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IBasicRepository.cs
@@ -8,17 +8,6 @@ namespace Volo.Abp.Domain.Repositories
public interface IBasicRepository : IReadOnlyBasicRepository
where TEntity : class, IEntity
{
- ///
- /// Inserts a new entity.
- ///
- /// Inserted entity
- ///
- /// 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.
- ///
- [NotNull]
- TEntity Insert([NotNull] TEntity entity, bool autoSave = false);
-
///
/// Inserts a new entity.
///
@@ -31,17 +20,6 @@ namespace Volo.Abp.Domain.Repositories
[NotNull]
Task InsertAsync([NotNull] TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default);
- ///
- /// Updates an existing entity.
- ///
- /// Entity
- ///
- /// 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.
- ///
- [NotNull]
- TEntity Update([NotNull] TEntity entity, bool autoSave = false);
-
///
/// Updates an existing entity.
///
@@ -54,16 +32,6 @@ namespace Volo.Abp.Domain.Repositories
[NotNull]
Task UpdateAsync([NotNull] TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default);
- ///
- /// Deletes an entity.
- ///
- /// Entity to be deleted
- ///
- /// 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.
- ///
- void Delete([NotNull] TEntity entity, bool autoSave = false);
-
///
/// Deletes an entity.
///
@@ -79,16 +47,6 @@ namespace Volo.Abp.Domain.Repositories
public interface IBasicRepository : IBasicRepository, IReadOnlyBasicRepository
where TEntity : class, IEntity
{
- ///
- /// Deletes an entity by primary key.
- ///
- /// Primary key of the entity
- ///
- /// 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.
- ///
- void Delete(TKey id, bool autoSave = false); //TODO: Return true if deleted
-
///
/// Deletes an entity by primary key.
///
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IReadOnlyBasicRepository.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IReadOnlyBasicRepository.cs
index c67b35794b..828e305ff8 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IReadOnlyBasicRepository.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IReadOnlyBasicRepository.cs
@@ -9,13 +9,6 @@ namespace Volo.Abp.Domain.Repositories
public interface IReadOnlyBasicRepository : IRepository
where TEntity : class, IEntity
{
- ///
- /// Gets a list of all the entities.
- ///
- /// Set true to include all children of this entity
- /// Entity
- List GetList(bool includeDetails = false);
-
///
/// Gets a list of all the entities.
///
@@ -24,11 +17,6 @@ namespace Volo.Abp.Domain.Repositories
/// Entity
Task> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default);
- ///
- /// Gets total count of all entities.
- ///
- long GetCount();
-
///
/// Gets total count of all entities.
///
@@ -38,16 +26,6 @@ namespace Volo.Abp.Domain.Repositories
public interface IReadOnlyBasicRepository : IReadOnlyBasicRepository
where TEntity : class, IEntity
{
- ///
- /// Gets an entity with given primary key.
- /// Throws if can not find an entity with given id.
- ///
- /// Primary key of the entity to get
- /// Set true to include all children of this entity
- /// Entity
- [NotNull]
- TEntity Get(TKey id, bool includeDetails = true);
-
///
/// Gets an entity with given primary key.
/// Throws if can not find an entity with given id.
@@ -59,15 +37,6 @@ namespace Volo.Abp.Domain.Repositories
[NotNull]
Task GetAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default);
- ///
- /// Gets an entity with given primary key or null if not found.
- ///
- /// Primary key of the entity to get
- /// Set true to include all children of this entity
- /// Entity or null
- [CanBeNull]
- TEntity Find(TKey id, bool includeDetails = true);
-
///
/// Gets an entity with given primary key or null if not found.
///
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IRepository.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IRepository.cs
index a77dc4acb7..2ac16ec229 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IRepository.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IRepository.cs
@@ -18,19 +18,6 @@ namespace Volo.Abp.Domain.Repositories
public interface IRepository : IReadOnlyRepository, IBasicRepository
where TEntity : class, IEntity
{
- ///
- /// 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.
- ///
- /// A condition to filter entities
- ///
- /// 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.
- ///
- void Delete([NotNull] Expression> predicate, bool autoSave = false);
-
///
/// Deletes many entities by function.
/// Notice that: All entities fits to given predicate are retrieved and deleted.
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryBase.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryBase.cs
index 139f4ff999..29814f4de6 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryBase.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryBase.cs
@@ -46,19 +46,7 @@ namespace Volo.Abp.Domain.Repositories
protected abstract IQueryable GetQueryable();
- public virtual void Delete(Expression> predicate, bool autoSave = false)
- {
- foreach (var entity in GetQueryable().Where(predicate).ToList())
- {
- Delete(entity, autoSave);
- }
- }
-
- public virtual Task DeleteAsync(Expression> predicate, bool autoSave = false, CancellationToken cancellationToken = default)
- {
- Delete(predicate, autoSave);
- return Task.CompletedTask;
- }
+ public abstract Task DeleteAsync(Expression> predicate, bool autoSave = false, CancellationToken cancellationToken = default);
protected virtual TQueryable ApplyDataFilters(TQueryable query)
where TQueryable : IQueryable
@@ -81,50 +69,19 @@ namespace Volo.Abp.Domain.Repositories
public abstract class RepositoryBase : RepositoryBase, IRepository
where TEntity : class, IEntity
{
- public virtual TEntity Find(TKey id, bool includeDetails = true)
- {
- return includeDetails
- ? WithDetails().FirstOrDefault(EntityHelper.CreateEqualityExpressionForId(id))
- : GetQueryable().FirstOrDefault(EntityHelper.CreateEqualityExpressionForId(id));
- }
+ public abstract Task 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 FindAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default);
- if (entity == null)
- {
- throw new EntityNotFoundException(typeof(TEntity), id);
- }
-
- return entity;
- }
-
- public virtual Task GetAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default)
- {
- return Task.FromResult(Get(id, includeDetails));
- }
-
- public virtual Task 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);
}
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs
index bfedcf2d66..4131a774b5 100644
--- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs
+++ b/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 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 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 GetList(bool includeDetails = false)
- {
- return includeDetails
- ? WithDetails().ToList()
- : DbSet.ToList();
- }
-
public override async Task> 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 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> predicate, bool autoSave = false)
- {
- base.Delete(predicate, autoSave);
-
- if (autoSave)
- {
- DbContext.SaveChanges();
- }
- }
-
public override async Task DeleteAsync(Expression> 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;
diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
index 18758d98e3..bcd21149da 100644
--- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
+++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
@@ -22,7 +22,6 @@ using Volo.Abp.EntityFrameworkCore.ValueConverters;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Reflection;
-using Volo.Abp.Threading;
using Volo.Abp.Timing;
namespace Volo.Abp.EntityFrameworkCore
@@ -92,46 +91,7 @@ namespace Volo.Abp.EntityFrameworkCore
.Invoke(this, new object[] { modelBuilder, entityType });
}
}
-
- public override int SaveChanges(bool acceptAllChangesOnSuccess)
- {
- //TODO: Reduce duplications with SaveChangesAsync
- //TODO: Instead of adding entity changes to audit log, write them to uow and add to audit log only if uow succeed
-
- try
- {
- var auditLog = AuditingManager?.Current?.Log;
-
- List entityChangeList = null;
- if (auditLog != null)
- {
- entityChangeList = EntityHistoryHelper.CreateChangeList(ChangeTracker.Entries().ToList());
- }
-
- var changeReport = ApplyAbpConcepts();
-
- var result = base.SaveChanges(acceptAllChangesOnSuccess);
-
- AsyncHelper.RunSync(() => EntityChangeEventHelper.TriggerEventsAsync(changeReport));
-
- if (auditLog != null)
- {
- EntityHistoryHelper.UpdateChangeList(entityChangeList);
- auditLog.EntityChanges.AddRange(entityChangeList);
- }
-
- return result;
- }
- catch (DbUpdateConcurrencyException ex)
- {
- throw new AbpDbConcurrencyException(ex.Message, ex);
- }
- finally
- {
- ChangeTracker.AutoDetectChangesEnabled = true;
- }
- }
-
+
public override async Task SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default)
{
try
diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DependencyInjection/AbpDbContextConfigurationContext.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DependencyInjection/AbpDbContextConfigurationContext.cs
index 1a21e129f3..b9cf4e3ceb 100644
--- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DependencyInjection/AbpDbContextConfigurationContext.cs
+++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DependencyInjection/AbpDbContextConfigurationContext.cs
@@ -2,6 +2,8 @@
using System.Data.Common;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.EntityFrameworkCore.DependencyInjection
@@ -29,7 +31,8 @@ namespace Volo.Abp.EntityFrameworkCore.DependencyInjection
ConnectionStringName = connectionStringName;
ExistingConnection = existingConnection;
- DbContextOptions = new DbContextOptionsBuilder();
+ DbContextOptions = new DbContextOptionsBuilder()
+ .UseLoggerFactory(serviceProvider.GetRequiredService());
}
}
@@ -49,7 +52,8 @@ namespace Volo.Abp.EntityFrameworkCore.DependencyInjection
connectionStringName,
existingConnection)
{
- base.DbContextOptions = new DbContextOptionsBuilder();
+ base.DbContextOptions = new DbContextOptionsBuilder()
+ .UseLoggerFactory(serviceProvider.GetRequiredService());
}
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureInterceptor.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureInterceptor.cs
index 5fb7c54293..9986af6275 100644
--- a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureInterceptor.cs
+++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureInterceptor.cs
@@ -2,7 +2,6 @@
using Volo.Abp.Aspects;
using Volo.Abp.DependencyInjection;
using Volo.Abp.DynamicProxy;
-using Volo.Abp.Threading;
namespace Volo.Abp.Features
{
@@ -16,18 +15,6 @@ namespace Volo.Abp.Features
_methodInvocationFeatureCheckerService = methodInvocationFeatureCheckerService;
}
- public override void Intercept(IAbpMethodInvocation invocation)
- {
- if (AbpCrossCuttingConcerns.IsApplied(invocation.TargetObject, AbpCrossCuttingConcerns.FeatureChecking))
- {
- invocation.Proceed();
- return;
- }
-
- AsyncHelper.RunSync(() => CheckFeaturesAsync(invocation));
- invocation.Proceed();
- }
-
public override async Task InterceptAsync(IAbpMethodInvocation invocation)
{
if (AbpCrossCuttingConcerns.IsApplied(invocation.TargetObject, AbpCrossCuttingConcerns.FeatureChecking))
diff --git a/framework/src/Volo.Abp.Http.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionDynamicHttpClientProxyExtensions.cs b/framework/src/Volo.Abp.Http.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionDynamicHttpClientProxyExtensions.cs
index 54387d2871..f34a732cb0 100644
--- a/framework/src/Volo.Abp.Http.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionDynamicHttpClientProxyExtensions.cs
+++ b/framework/src/Volo.Abp.Http.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionDynamicHttpClientProxyExtensions.cs
@@ -53,7 +53,7 @@ namespace Microsoft.Extensions.DependencyInjection
foreach (var serviceType in serviceTypes)
{
services.AddHttpClientProxy(
- serviceType,
+ serviceType,
remoteServiceConfigurationName,
asDefaultServices
);
@@ -153,7 +153,7 @@ namespace Microsoft.Extensions.DependencyInjection
var interceptorType = typeof(DynamicHttpProxyInterceptor<>).MakeGenericType(type);
services.AddTransient(interceptorType);
- var interceptorAdapterType = typeof(CastleAbpInterceptorAdapter<>).MakeGenericType(interceptorType);
+ var interceptorAdapterType = typeof(AbpAsyncDeterminationInterceptor<>).MakeGenericType(interceptorType);
if (asDefaultService)
{
@@ -174,7 +174,7 @@ namespace Microsoft.Extensions.DependencyInjection
var service = ProxyGeneratorInstance
.CreateInterfaceProxyWithoutTarget(
type,
- (IInterceptor) serviceProvider.GetRequiredService(interceptorAdapterType)
+ (IInterceptor)serviceProvider.GetRequiredService(interceptorAdapterType)
);
return Activator.CreateInstance(
diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs
index d2b57d32ef..3e0124237f 100644
--- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs
+++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs
@@ -74,43 +74,33 @@ namespace Volo.Abp.Http.Client.DynamicProxying
Logger = NullLogger>.Instance;
}
- public override void Intercept(IAbpMethodInvocation invocation)
+ public override async Task InterceptAsync(IAbpMethodInvocation invocation)
{
- if (invocation.Method.ReturnType == typeof(void))
+ if (invocation.Method.ReturnType.GenericTypeArguments.IsNullOrEmpty())
{
- AsyncHelper.RunSync(() => MakeRequestAsync(invocation));
+ await MakeRequestAsync(invocation);
}
else
{
- var responseAsString = AsyncHelper.RunSync(() => MakeRequestAsync(invocation));
+ var result = (Task)GenericInterceptAsyncMethod
+ .MakeGenericMethod(invocation.Method.ReturnType.GenericTypeArguments[0])
+ .Invoke(this, new object[] { invocation });
- //TODO: Think on that
- if (TypeHelper.IsPrimitiveExtended(invocation.Method.ReturnType, true))
- {
- invocation.ReturnValue = Convert.ChangeType(responseAsString, invocation.Method.ReturnType);
- }
- else
- {
- invocation.ReturnValue = JsonSerializer.Deserialize(
- invocation.Method.ReturnType,
- responseAsString
- );
- }
+ invocation.ReturnValue = await GetResultAsync(
+ result,
+ invocation.Method.ReturnType.GetGenericArguments()[0]
+ );
}
+
}
- public override Task InterceptAsync(IAbpMethodInvocation invocation)
+ private async Task