diff --git a/docs/en/Blog-Posts/2024-06-27 v8_2_Release_Stable/POST.md b/docs/en/Blog-Posts/2024-06-27 v8_2_Release_Stable/POST.md
new file mode 100644
index 0000000000..67db40e98a
--- /dev/null
+++ b/docs/en/Blog-Posts/2024-06-27 v8_2_Release_Stable/POST.md
@@ -0,0 +1,67 @@
+# ABP.IO Platform 8.2 Final Has Been Released!
+
+[ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) 8.2 versions have been released today.
+
+## What's New With Version 8.2?
+
+All the new features were explained in detail in the [8.2 RC Announcement Post](https://blog.abp.io/abp/announcing-abp-8-2-release-candidate), so there is no need to review them again. You can check it out for more details.
+
+## Getting Started with 8.2
+
+### Creating New Solutions
+
+You can create a new solution with the ABP Framework version 8.2 by either using the `abp new` command or generating the CLI command on the [get started page](https://abp.io/get-started).
+
+> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for more.
+
+### How to Upgrade an Existing Solution
+
+#### Install/Update the ABP CLI
+
+First, install the ABP CLI or upgrade it to the latest version.
+
+If you haven't installed it yet:
+
+```bash
+dotnet tool install -g Volo.Abp.Cli
+```
+
+To update the existing CLI:
+
+```bash
+dotnet tool update -g Volo.Abp.Cli
+```
+
+#### Upgrading Existing Solutions with the ABP Update Command
+
+[ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides a handy command to update all the ABP related NuGet and NPM packages in your solution with a single command:
+
+```bash
+abp update
+```
+
+Run this command in the root folder of your solution.
+
+## Migration Guides
+
+There are a few breaking changes in this version that may affect your application.
+Please see the following migration documents, if you are upgrading from v8.x or earlier:
+
+* [ABP Framework 8.x to 8.2 Migration Guide](https://docs.abp.io/en/abp/8.2/Migration-Guides/Abp-8_2)
+* [ABP Commercial 8.x to 8.2 Migration Guide](https://docs.abp.io/en/commercial/8.2/migration-guides/v8_2)
+
+## Community News
+
+### New ABP Community Posts
+
+As always, exciting articles have been contributed by the ABP community. I will highlight some of them here:
+
+* [How to use Angular Material with Form Validation on ABP](https://community.abp.io/posts/how-to-use-angular-material-with-form-validation-on-abp-jtheajj3) by [Mahmut Gündoğdu](https://x.com/mahmutgundogdu)
+* [Tunnel your local host address to a public URL with ngrok](https://community.abp.io/posts/tunnel-your-local-host-address-to-a-public-url-with-ngrok-4cywnocj) by [Bart Van Hoey](https://github.com/bartvanhoey)
+* [Antiforgery Token Validation When Angular and HTTP API Runs on the Same Server](https://community.abp.io/posts/antiforgery-token-validation-when-angular-and-http-api-runs-on-the-same-server-mzf5ppdq) by [dignite](https://x.com/dignite_adu)
+
+Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://community.abp.io/articles/submit) to the ABP Community.
+
+## About the Next Version
+
+The next feature version will be 8.3. You can follow the [release planning here](https://github.com/abpframework/abp/milestones). Please [submit an issue](https://github.com/abpframework/abp/issues/new) if you have any problems with this version.
diff --git a/docs/en/Blog-Posts/2024-06-27 v8_2_Release_Stable/cover-image.png b/docs/en/Blog-Posts/2024-06-27 v8_2_Release_Stable/cover-image.png
new file mode 100644
index 0000000000..59689ba490
Binary files /dev/null and b/docs/en/Blog-Posts/2024-06-27 v8_2_Release_Stable/cover-image.png differ
diff --git a/docs/en/Community-Articles/2024-06-27-how-to-use-Aspire-with-ABP-framework/How to use Aspire with ABP framework.md b/docs/en/Community-Articles/2024-06-27-how-to-use-Aspire-with-ABP-framework/How to use Aspire with ABP framework.md
new file mode 100644
index 0000000000..7d78d476c5
--- /dev/null
+++ b/docs/en/Community-Articles/2024-06-27-how-to-use-Aspire-with-ABP-framework/How to use Aspire with ABP framework.md
@@ -0,0 +1,302 @@
+# How to use .NET Aspire with ABP framework
+
+[.NET Aspire](https://learn.microsoft.com/en-us/dotnet/aspire/get-started/aspire-overview) is an opinionated, cloud-ready stack designed for building observable, production-ready, and distributed applications. On the other hand, the [ABP framework](https://docs.abp.io/en/abp/latest) offers a complete, modular and layered software architecture based on Domain Driven Design principles and patterns. This guide explores how to combine .NET Aspire with ABP, enabling developers to create observable, and feature-rich applications.
+
+## When to Use .NET Aspire?
+
+Using .NET Aspire with the ABP framework can be beneficial in various scenarios where you need to combine the strengths of both technologies. Here are some situations when using .NET Aspire with ABP can be advantageous:
+
+- **Enterprise Web Applications:** ABP is well-suited for building enterprise web applications with its opinionated architecture and best practices. When combined with .NET Aspire, you can leverage ABP's features for rapid development of user interfaces, backend services, and business logic while benefiting from .NET Aspire's cloud-native capabilities and observability features.
+- **Observability and Monitoring:** .NET Aspire's emphasis on observability, including logging, monitoring, and tracing, can enhance ABP applications by providing deeper insights into system behavior, performance metrics, and diagnostics, which is key for maintaining and optimizing enterprise-grade applications.
+
+## Creating a new ABP Solution
+
+To demonstrate the usage of .NET Aspire with the ABP framework, I've created an ABP solution. If you want to create the same solution from scratch, follow the steps below:
+
+Install the ABP CLI if you haven't installed it before:
+
+```bash
+dotnet tool install -g Volo.Abp.Cli
+```
+
+Create a new solution with the ABP framework's Application Startup Template with Tiered MVC UI and EF Core database:
+
+```bash
+abp new AspirationalAbp -u mvc --database-provider ef -dbms PostgreSQL --csf --tiered
+```
+
+> The startup template selection matters for this article. I chose these options so that the demo solution can cover complex scenarios.
+
+**Disclaimer-I:** This article is based on version `8.0.1` of .NET Aspire and version `8.2.0` of ABP Framework.
+
+**Disclaimer-II:** ABP and .NET Aspire may not be fully compatible in some respects. This article aims to explain how these two technologies can be used together in the simplest way possible, even if they are not fully compatible.
+## Add .NET Aspire
+
+After creating the solution, run the following commands in the `src` folder of your solution to add .NET Aspire:
+
+```bash
+// Adding AppHost
+dotnet new aspire-apphost -n AspirationalAbp.AppHost
+dotnet sln ../AspirationalAbp.sln add ./AspirationalAbp.AppHost/AspirationalAbp.AppHost.csproj
+
+// Adding ServiceDefaults
+dotnet new aspire-servicedefaults -n AspirationalAbp.ServiceDefaults
+dotnet sln ../AspirationalAbp.sln add ./AspirationalAbp.ServiceDefaults/AspirationalAbp.ServiceDefaults.csproj
+```
+
+These commands add two new projects to the solution:
+- **AspirationalAbp.AppHost**: An orchestrator project designed to connect and configure the different projects and services of your app.
+- **AspirationalAbp.ServiceDefaults**: A .NET Aspire shared project to manage configurations that are reused across the projects in your solution related to [resilience](https://learn.microsoft.com/en-us/dotnet/core/resilience/http-resilience), [service discovery](https://learn.microsoft.com/en-us/dotnet/aspire/service-discovery/overview), and [telemetry](https://learn.microsoft.com/en-us/dotnet/aspire/fundamentals/telemetry).
+
+We have added .NET Aspire to our ABP based solution, but we have not registered our projects in the .NET Aspire orchestration. Now, let's enroll our projects, which implement the db migrator, web user interface, API, and auth, in .NET Aspire orchestration.
+
+## Registering projects to .NET Aspire orchestration
+
+First of all, we need to add the reference of related projects to the `AspirationalAbp.AppHost` project. For this, add the following `ItemGroups` to the `AspirationalAbp.AppHost/AspirationalAbp.AppHost.csproj` file:
+
+```csharp
+
+
+
+
+
+
+
+
+
+
+
+```
+
+With the first `ItemGroup`, we added the references of `AuthServer`, `HttpApi.Host`, `Web`, and `DbMigrator` projects to the app host project. So, we can orchestrate them within the app model.
+
+With the second `ItemGroup`, to model the **PostgreSQL** server resource and **Redis** resource in the app host, installed the `Aspire.Hosting.PostgreSQL` and `Aspire.Hosting.Redis`
+
+Now let's update the `Program` class of the `AspirationalAbp.AppHost` project as follows:
+
+```csharp
+using Microsoft.Extensions.Hosting;
+
+var builder = DistributedApplication.CreateBuilder(args);
+
+var postgres = builder
+ .AddPostgres("postgres")
+ .AddDatabase("AspirationalAbp");
+
+var redis = builder.AddRedis("redis");
+
+// DbMigrator
+if (builder.Environment.IsDevelopment())
+{
+ builder
+ .AddProject("dbMigrator")
+ .WithReference(postgres, "Default")
+ .WithReference(redis, "Redis")
+ .WithReplicas(1);
+}
+
+// AuthServer
+var authServerLaunchProfile = "AspirationalAbp.AuthServer";
+builder
+ .AddProject("authserver", launchProfileName: authServerLaunchProfile)
+ .WithExternalHttpEndpoints()
+ .WithReference(postgres, "Default")
+ .WithReference(redis);
+
+// HttpApi.Host
+var httpApiHostLaunchProfile = "AspirationalAbp.HttpApi.Host";
+builder
+ .AddProject("httpapihost", launchProfileName: httpApiHostLaunchProfile)
+ .WithExternalHttpEndpoints()
+ .WithReference(postgres, "Default")
+ .WithReference(redis);
+
+// Web
+builder
+ .AddProject("web", "AspirationalAbp.Web")
+ .WithReference(redis);
+
+builder.Build().Run();
+```
+
+With the code above, the following operations were performed below:
+
+1. Creates an `IDistributedApplicationBuilder` instance by calling `DistributedApplication.CreateBuilder(args)`.
+2. Adds PostgreSQL and the `AspirationalAbp` database.
+3. Adds Redis.
+4. Adds the `DbMigrator` project with references to PostgreSQL and Redis, ensuring one replica in development.
+5. Adds the `AuthServer` project with external HTTP endpoints, referencing PostgreSQL and Redis.
+6. Adds the `HttpApi.Host` project with external HTTP endpoints, referencing PostgreSQL and Redis.
+7. Adds the `Web` project, referencing Redis.
+8. Builds and runs the application.
+
+Now let's make the projects we added to the app host compatible with .NET Aspire.
+
+## Configuring Projects for Aspire
+
+To make the `AspirationalAbp.DbMigrator`, `AspirationalAbp.AuthServer`, `AspirationalAbp.HttpApi.Host`, and `AspirationalAbp.Web` projects compatible with .NET Aspire, we need to add and configure several packages. For that, we need to add the `Aspire.StackExchange.Redis` package to all these projects and the `Aspire.Npgsql.EntityFrameworkCore.PostgreSQL` package to the `AspirationalAbp.EntityFrameworkCore` project. Additionally, we will add the `AspirationalAbp.ServiceDefaults` reference to host projects except `AspirationalAbp.DbMigrator`. Also, we need to convert [Serilog](https://serilog.net/) events into [OpenTelemetry](https://opentelemetry.io/) `LogRecord`s, for that we will add a `Serilog.Sinks.OpenTelemetry` reference to host projects. Let's begin with configuring `AspirationalAbp.DbMigrator`.
+
+### AspirationalAbp.DbMigrator
+
+First, let's add the `Aspire.StackExchange.Redis`, and `Serilog.Sinks.OpenTelemetry` packages to the `AspirationalAbp.DbMigrator` project. For this, let's run the following .NET CLI command inside the `AspirationalAbp.DbMigrator` project:
+
+```bash
+dotnet add package Aspire.StackExchange.Redis --version 8.0.1
+dotnet add package Serilog.Sinks.OpenTelemetry --version 4.0.0-dev-00313
+```
+
+Then let's override the `PreConfigureServices` method in `AspirationalAbpDbMigratorModule` as below:
+
+```csharp
+public override void PreConfigureServices(ServiceConfigurationContext context)
+{
+ var configuration = context.Services.GetConfiguration();
+ configuration["Redis:Configuration"] = configuration["ConnectionStrings:Redis"];
+}
+```
+
+To use the **OpenTelemetry** sink we have installed the `Serilog.Sinks.OpenTelemetry` package and now let's enable the sink. For this, let's write the following code block just before calling the `CreateLogger` method in the logger configuration in `Program.cs`:
+
+```csharp
+/// .WriteTo.Async(c => c.Console())
+.WriteTo.Async(c => c.OpenTelemetry())
+/// .CreateLogger();
+```
+
+Now let's continue with `AspirationalAbp.EntityFrameworkCore`.
+
+### AspirationalAbp.EntityFrameworkCore
+
+Now let's add the `Aspire.Npgsql.EntityFrameworkCore.PostgreSQL` package to the `AspirationalAbp.EntityFrameworkCore` project. For this, you can run the following command in the `AspirationalAbp.EntityFrameworkCore` project:
+
+```bash
+dotnet add package Aspire.Npgsql.EntityFrameworkCore.PostgreSQL --version 8.0.1
+```
+
+Now let's continue with `AspirationalAbp.AuthServer`.
+
+### AspirationalAbp.AuthServer
+
+First, let's add the `Serilog.Sinks.OpenTelemetry`, `Aspire.StackExchange.Redis` and `AspirationalAbp.ServiceDefaults` packages to the `AspirationalAbp.AuthServer` project. For this, let's run the following .NET CLI command inside the `AspirationalAbp.AuthServer` project:
+
+```bash
+dotnet add package Aspire.StackExchange.Redis --version 8.0.1
+dotnet add reference ../AspirationalAbp.ServiceDefaults/AspirationalAbp.ServiceDefaults.csproj
+dotnet add package Serilog.Sinks.OpenTelemetry --version 4.0.0-dev-00313
+```
+
+Then add the following code block after defining the builder variable in `Program.cs`:
+
+```csharp
+builder.AddServiceDefaults();
+builder.AddRedisClient("redis");
+builder.AddNpgsqlDbContext("Default",
+ options =>
+ {
+ options.DisableRetry = true;
+ });
+```
+
+Then add the following code to the `PreConfigureServices` method in the `AspirationalAbpAuthServerModule` class:
+
+```csharp
+configuration["Redis:Configuration"] = configuration["ConnectionStrings:Redis"];
+```
+
+To use the **OpenTelemetry** sink we have installed the `Serilog.Sinks.OpenTelemetry` package and now let's enable the sink. For this, let's write the following code block just before calling the `CreateLogger` method in logger configuration in `Program.cs`:
+
+```csharp
+/// .WriteTo.Async(c => c.Console())
+.WriteTo.Async(c => c.OpenTelemetry())
+/// .CreateLogger();
+```
+
+So far we have made `AspirationalAbp.DbMigrator`, `AspirationalAbp.EntityFrameworkCore`, and `AspirationalAbp.AuthServer` compatible with .NET Aspire. Now let's continue with `AspirationalAbp.HttpApi.Host`.
+
+### AspirationalAbp.HttpApi.Host
+
+First, let's add the `Serilog.Sinks.OpenTelemetry`, `Aspire.StackExchange.Redis` and `AspirationalAbp.ServiceDefaults` packages to the `AspirationalAbp.HttpApi.Host` project. For this, let's run the following .NET CLI command inside the `AspirationalAbp.HttpApi.Host` project:
+
+```bash
+dotnet add package Aspire.StackExchange.Redis --version 8.0.1
+dotnet add reference ../AspirationalAbp.ServiceDefaults/AspirationalAbp.ServiceDefaults.csproj
+dotnet add package Serilog.Sinks.OpenTelemetry --version 4.0.0-dev-00313
+```
+
+Then add the following code block after defining the builder variable in `Program.cs`:
+
+```csharp
+builder.AddServiceDefaults();
+builder.AddRedisClient("redis");
+builder.AddNpgsqlDbContext("Default",
+ options =>
+ {
+ options.DisableRetry = true;
+ });
+```
+
+Then let's override the `PreConfigureServices` method in `AspirationalAbpHttpApiHostModule` as below:
+
+```csharp
+public override void PreConfigureServices(ServiceConfigurationContext context)
+{
+ var configuration = context.Services.GetConfiguration();
+ configuration["Redis:Configuration"] = configuration["ConnectionStrings:Redis"];
+}
+```
+
+To use the **OpenTelemetry** sink we have installed the `Serilog.Sinks.OpenTelemetry` package and now let's enable the sink. For this, let's write the following code block just before calling the `CreateLogger` method in the logger configuration in `Program.cs`:
+
+```csharp
+/// .WriteTo.Async(c => c.Console())
+.WriteTo.Async(c => c.OpenTelemetry())
+/// .CreateLogger();
+```
+
+Finally, let's make `AspirationalAbp.Web` compatible with .NET Aspire.
+
+### AspirationalAbp.Web
+
+First, let's add the `Serilog.Sinks.OpenTelemetry`, `Aspire.StackExchange.Redis` and `AspirationalAbp.ServiceDefaults` packages to the `AspirationalAbp.Web` project. For this, let's run the following .NET CLI command inside the `AspirationalAbp.Web` project:
+
+```bash
+dotnet add package Aspire.StackExchange.Redis --version 8.0.1
+dotnet add reference ../AspirationalAbp.ServiceDefaults/AspirationalAbp.ServiceDefaults.csproj
+dotnet add package Serilog.Sinks.OpenTelemetry --version 4.0.0-dev-00313
+```
+
+Then add the following code block after defining the builder variable in `Program.cs`:
+
+```csharp
+builder.AddServiceDefaults();
+builder.AddRedisClient("redis");
+```
+
+Then add the following code to the `PreConfigureServices` method in the `AspirationalAbpWebModule` class:
+
+```bash
+var configuration = context.Services.GetConfiguration();
+configuration["Redis:Configuration"] = configuration["ConnectionStrings:Redis"];
+```
+
+To use the **OpenTelemetry** sink we have installed the `Serilog.Sinks.OpenTelemetry` package and now let's enable the sink. For this, let's write the following code block just before calling the `CreateLogger` method in logger configuration in `Program.cs`:
+
+```csharp
+/// .WriteTo.Async(c => c.Console())
+.WriteTo.Async(c => c.OpenTelemetry())
+/// .CreateLogger();
+```
+
+After making all our changes, we can run the `AspirationalAbp.AppHost` project.
+
+
+
+
+
+
+
+
+
+## Conclusion
+
+Combining .NET Aspire with the ABP framework creates a powerful setup for building robust, observable, and feature-rich applications. By integrating Aspire's observability and cloud capabilities with ABP's approach of focusing on your business without repeating yourself, you can develop feature-rich, scalable applications with enhanced monitoring and seamless cloud integration. This guide provides a clear path to set up and configure these technologies, ensuring your applications are well-structured, maintainable, and ready for modern cloud environments.
diff --git a/docs/en/Community-Articles/2024-06-27-how-to-use-Aspire-with-ABP-framework/aspire-dashboard.png b/docs/en/Community-Articles/2024-06-27-how-to-use-Aspire-with-ABP-framework/aspire-dashboard.png
new file mode 100644
index 0000000000..b1141c4644
Binary files /dev/null and b/docs/en/Community-Articles/2024-06-27-how-to-use-Aspire-with-ABP-framework/aspire-dashboard.png differ
diff --git a/docs/en/Community-Articles/2024-06-27-how-to-use-Aspire-with-ABP-framework/aspire-metrics.png b/docs/en/Community-Articles/2024-06-27-how-to-use-Aspire-with-ABP-framework/aspire-metrics.png
new file mode 100644
index 0000000000..ec2c9abda7
Binary files /dev/null and b/docs/en/Community-Articles/2024-06-27-how-to-use-Aspire-with-ABP-framework/aspire-metrics.png differ
diff --git a/docs/en/Community-Articles/2024-06-27-how-to-use-Aspire-with-ABP-framework/aspire-structured-logs.png b/docs/en/Community-Articles/2024-06-27-how-to-use-Aspire-with-ABP-framework/aspire-structured-logs.png
new file mode 100644
index 0000000000..af0b685000
Binary files /dev/null and b/docs/en/Community-Articles/2024-06-27-how-to-use-Aspire-with-ABP-framework/aspire-structured-logs.png differ
diff --git a/docs/en/Community-Articles/2024-06-27-how-to-use-Aspire-with-ABP-framework/aspire-traces.png b/docs/en/Community-Articles/2024-06-27-how-to-use-Aspire-with-ABP-framework/aspire-traces.png
new file mode 100644
index 0000000000..20a5d65d3c
Binary files /dev/null and b/docs/en/Community-Articles/2024-06-27-how-to-use-Aspire-with-ABP-framework/aspire-traces.png differ
diff --git a/docs/en/Community-Articles/2024-07-01-Use_User-Defined_Function_Mapping_For_Global_Filter/POST.md b/docs/en/Community-Articles/2024-07-01-Use_User-Defined_Function_Mapping_For_Global_Filter/POST.md
new file mode 100644
index 0000000000..37171d1219
--- /dev/null
+++ b/docs/en/Community-Articles/2024-07-01-Use_User-Defined_Function_Mapping_For_Global_Filter/POST.md
@@ -0,0 +1,130 @@
+# Use User-Defined Function Mapping for Global Filter
+
+## Introduction
+
+ABP provides data filters that can filter queries automatically based on some rules. This feature is useful for implementing multi-tenancy, soft delete, and other global filters. It uses [EF Core's Global Query Filters system](https://learn.microsoft.com/en-us/ef/core/querying/filters) for the EF Core Integration.
+
+EF Core Global Query Filters generate filter conditions and apply them to SQL queries. ABP controls whether this filter condition takes effect through a variable. However, this variable may cause performance losses in some scenarios.
+
+## The Filter Condition Variable
+
+Think of a scenario with a global filter `IIsActive`, which filters out inactive entities:
+
+```csharp
+public class Book : IIsActive
+{
+ public string Name { get; set; }
+
+ public bool IsActive { get; set; }
+}
+```
+
+The SQL generated by the [EF Core Global Query Filters](https://learn.microsoft.com/en-us/ef/core/querying/filters) is as follows:
+
+```SQL
+SELECT * FROM [AppBooks] AS [a]
+WHERE (@__ef_filter__p_0 = CAST(1 AS bit) OR [a].[IsActive] = CAST(1 AS bit))
+```
+
+> The `__ef_filter__p_0` variable controls whether the filter condition takes effect.
+
+The generated SQL is not optimal, and some databases do not optimize it well.
+
+## Using User-defined function mapping for global filters
+
+In the [upcoming preview version of ABP, v8.3.0-rc.1](https://github.com/abpframework/abp/pull/20065), we start the [User-defined function mapping](https://learn.microsoft.com/en-us/ef/core/querying/user-defined-function-mapping) to implement global filters more efficiently. This feature is enabled by default, so you don't need to make any changes if you create a new solution and start from scratch. Otherwise, you can enable it easily by following the instructions below.
+
+To use this new feature for your custom global filters, you need to change your `DbContext` as follows:
+
+````csharp
+protected bool IsActiveFilterEnabled => DataFilter?.IsEnabled() ?? false;
+
+protected override bool ShouldFilterEntity(IMutableEntityType entityType)
+{
+ if (typeof(IIsActive).IsAssignableFrom(typeof(TEntity)))
+ {
+ return true;
+ }
+
+ return base.ShouldFilterEntity(entityType);
+}
+
+protected override Expression> CreateFilterExpression(ModelBuilder modelBuilder)
+{
+ var expression = base.CreateFilterExpression(modelBuilder);
+
+ if (typeof(IIsActive).IsAssignableFrom(typeof(TEntity)))
+ {
+ Expression> isActiveFilter = e => !IsActiveFilterEnabled || EF.Property(e, "IsActive");
+
+ if (UseDbFunction())
+ {
+ isActiveFilter = e => IsActiveFilter(((IIsActive)e).IsActive, true);
+
+ var abpEfCoreCurrentDbContext = this.GetService();
+ modelBuilder.HasDbFunction(typeof(MyProjectNameDbContext).GetMethod(nameof(IsActiveFilter))!)
+ .HasTranslation(args =>
+ {
+ // (bool isActive, bool boolParam)
+ var isActive = args[0];
+ var boolParam = args[1];
+
+ if (abpEfCoreCurrentDbContext.Context?.DataFilter.IsEnabled() == true)
+ {
+ // isActive == true
+ return new SqlBinaryExpression(
+ ExpressionType.Equal,
+ isActive,
+ new SqlConstantExpression(Expression.Constant(true), boolParam.TypeMapping),
+ boolParam.Type,
+ boolParam.TypeMapping);
+ }
+
+ // empty where sql
+ return new SqlConstantExpression(Expression.Constant(true), boolParam.TypeMapping);
+ });
+ }
+
+ expression = expression == null ? isActiveFilter : QueryFilterExpressionHelper.CombineExpressions(expression, isActiveFilter);
+ }
+
+ return expression;
+}
+
+public static bool IsActiveFilter(bool isActive, bool boolParam)
+{
+ throw new NotSupportedException(AbpEfCoreDataFilterDbFunctionMethods.NotSupportedExceptionMessage);
+}
+
+public override string GetCompiledQueryCacheKey()
+{
+ return $"{base.GetCompiledQueryCacheKey()}:{IsActiveFilterEnabled}";
+}
+````
+
+After these changes, the SQL generated by the EF Core Global Query Filters will be as follows:
+
+Enabling the `IIsActive` filter:
+
+```SQL
+SELECT * FROM [AppBooks] AS [a] WHERE
+[a].[IsActive] = CAST(1 AS bit)
+```
+
+Disabling the `IIsActive` filter:
+
+```SQL
+SELECT * FROM [AppBooks] AS [a]
+```
+
+## Conclusion
+
+We have implemented global filters using [User-defined function mapping](https://learn.microsoft.com/en-us/ef/core/querying/user-defined-function-mapping), which can generate more efficient SQL and thus improve performance.
+
+Upgrade to the latest ABP version and enjoy the performance improvement!
+
+## References
+
+- [ABP Framework Data Filtering](https://docs.abp.io/en/abp/latest/Data-Filtering)
+- [EF Core's Global Query Filters system](https://learn.microsoft.com/en-us/ef/core/querying/filters)
+- [User-defined function mapping](https://learn.microsoft.com/en-us/ef/core/querying/user-defined-function-mapping)
diff --git a/docs/en/UI/Blazor/Pwa-Configuration.md b/docs/en/UI/Blazor/Pwa-Configuration.md
index c687d040ef..01ba497a52 100644
--- a/docs/en/UI/Blazor/Pwa-Configuration.md
+++ b/docs/en/UI/Blazor/Pwa-Configuration.md
@@ -59,7 +59,7 @@ First, you need to create a JSON file named **manifest.json** under the **wwwroo
You can add some icons for your application to be seen in specific screen sizes and define in which screen sizes icons should be displayed in the **manifest.json** file. You can see the **icons** section in the **manifest.json** file as an example above.
-> You can use, default icons from our [template](https://github.com/abpframework/abp/tree/dev/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot).
+> You can use, default icons from our [template](https://github.com/abpframework/abp/tree/dev/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Client/wwwroot).
### 3-) Configure Service Workers
@@ -67,7 +67,7 @@ You can add some icons for your application to be seen in specific screen sizes
You need to create `service-worker.js` and `service-worker.published.js` files under the **wwwroot** folder of your project. These files will be used by your project to determine which PWA features you want to use.
-You can get the simple configurations for the [service-worker.js](https://github.com/abpframework/abp/blob/dev/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/service-worker.js) and [service-worker.published.js](https://github.com/abpframework/abp/blob/dev/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/service-worker.published.js) files from our [template](https://github.com/abpframework/abp/tree/dev/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot).
+You can get the simple configurations for the [service-worker.js](https://github.com/abpframework/abp/tree/dev/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Client/wwwroot/service-worker.js) and [service-worker.published.js](https://github.com/abpframework/abp/tree/dev/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Client/wwwroot/service-worker.published.js) files from our [template](https://github.com/abpframework/abp/tree/dev/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Client/wwwroot).
After the related service worker files are added, then we need to define them in our `.csproj` file to notify our application. So open your `*.csproj` file and add the following content:
diff --git a/docs/en/images/cmskit-module-comments-settings.png b/docs/en/images/cmskit-module-comments-settings.png
index 3c5a60d571..c0b1a4fe48 100644
Binary files a/docs/en/images/cmskit-module-comments-settings.png and b/docs/en/images/cmskit-module-comments-settings.png differ
diff --git a/docs/en/images/db-options.png b/docs/en/images/db-options.png
index 0c581c4883..91d2b51ce7 100644
Binary files a/docs/en/images/db-options.png and b/docs/en/images/db-options.png differ
diff --git a/docs/en/images/ddd-microservice-simple.png b/docs/en/images/ddd-microservice-simple.png
index 6588c2c753..1bdf207317 100644
Binary files a/docs/en/images/ddd-microservice-simple.png and b/docs/en/images/ddd-microservice-simple.png differ
diff --git a/framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/Authentication/AbpAspNetCoreTokenUnauthorizedErrorInfo.cs b/framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/Authentication/AbpAspNetCoreTokenUnauthorizedErrorInfo.cs
new file mode 100644
index 0000000000..2702f4f19f
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/Authentication/AbpAspNetCoreTokenUnauthorizedErrorInfo.cs
@@ -0,0 +1,12 @@
+using Volo.Abp.DependencyInjection;
+
+namespace Volo.Abp.AspNetCore.Authentication;
+
+public class AbpAspNetCoreTokenUnauthorizedErrorInfo : IScopedDependency
+{
+ public string? Error { get; set; }
+
+ public string? ErrorDescription { get; set; }
+
+ public string? ErrorUri { get; set; }
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Microsoft/Extensions/DependencyInjection/AbpJwtBearerExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Microsoft/Extensions/DependencyInjection/AbpJwtBearerExtensions.cs
index 5f48cc92d5..8973b68a1f 100644
--- a/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Microsoft/Extensions/DependencyInjection/AbpJwtBearerExtensions.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Microsoft/Extensions/DependencyInjection/AbpJwtBearerExtensions.cs
@@ -1,6 +1,7 @@
using System;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
+using Volo.Abp.AspNetCore.Authentication;
using Volo.Abp.Security.Claims;
namespace Microsoft.Extensions.DependencyInjection;
@@ -31,6 +32,33 @@ public static class AbpJwtBearerExtensions
return builder.AddJwtBearer(authenticationScheme, displayName, options =>
{
configureOptions?.Invoke(options);
+
+ options.Events ??= new JwtBearerEvents();
+ var previousOnChallenge = options.Events.OnChallenge;
+ options.Events.OnChallenge = async eventContext =>
+ {
+ await previousOnChallenge(eventContext);
+
+ if (eventContext.Handled ||
+ !string.IsNullOrEmpty(eventContext.Error) ||
+ !string.IsNullOrEmpty(eventContext.ErrorDescription) ||
+ !string.IsNullOrEmpty(eventContext.ErrorUri))
+ {
+ return;
+ }
+
+ var tokenUnauthorizedErrorInfo = eventContext.HttpContext.RequestServices.GetRequiredService();
+ if (string.IsNullOrEmpty(tokenUnauthorizedErrorInfo.Error) &&
+ string.IsNullOrEmpty(tokenUnauthorizedErrorInfo.ErrorDescription) &&
+ string.IsNullOrEmpty(tokenUnauthorizedErrorInfo.ErrorUri))
+ {
+ return;
+ }
+
+ eventContext.Error = tokenUnauthorizedErrorInfo.Error;
+ eventContext.ErrorDescription = tokenUnauthorizedErrorInfo.ErrorDescription;
+ eventContext.ErrorUri = tokenUnauthorizedErrorInfo.ErrorUri;
+ };
});
}
}
diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj b/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj
index 4d7b852b9c..839053bc90 100644
--- a/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj
+++ b/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj
@@ -19,6 +19,7 @@
+
diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo/Abp/AspNetCore/Authentication/JwtBearer/AbpAspNetCoreAuthenticationJwtBearerModule.cs b/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo/Abp/AspNetCore/Authentication/JwtBearer/AbpAspNetCoreAuthenticationJwtBearerModule.cs
index 89d957fe57..c0b9122b7d 100644
--- a/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo/Abp/AspNetCore/Authentication/JwtBearer/AbpAspNetCoreAuthenticationJwtBearerModule.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo/Abp/AspNetCore/Authentication/JwtBearer/AbpAspNetCoreAuthenticationJwtBearerModule.cs
@@ -7,7 +7,7 @@ using Volo.Abp.Security.Claims;
namespace Volo.Abp.AspNetCore.Authentication.JwtBearer;
-[DependsOn(typeof(AbpSecurityModule), typeof(AbpCachingModule))]
+[DependsOn(typeof(AbpSecurityModule), typeof(AbpCachingModule), typeof(AbpAspNetCoreAbstractionsModule))]
public class AbpAspNetCoreAuthenticationJwtBearerModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
@@ -21,5 +21,6 @@ public class AbpAspNetCoreAuthenticationJwtBearerModule : AbpModule
context.Services.AddTransient();
context.Services.AddTransient();
}
+
}
}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBodyTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBodyTagHelperService.cs
index e50d0a791a..b8462f4b5b 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBodyTagHelperService.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBodyTagHelperService.cs
@@ -32,7 +32,7 @@ public class AbpCardBodyTagHelperService : AbpTagHelperService
var small = new TagBuilder("small");
small.Attributes.Add("id", idAttr?.Value?.ToString() + "InfoText");
- small.AddCssClass("form-text text-muted");
+ small.AddCssClass("form-text");
small.InnerHtml.Append(localizedText);
return small.ToHtmlString();
diff --git a/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs b/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs
index 53216b03b9..2ab98adbb4 100644
--- a/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs
+++ b/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs
@@ -50,14 +50,18 @@ public static class AbpRegistrationBuilderExtensions
ServiceDescriptor serviceDescriptor)
where TActivatorData : ReflectionActivatorData
{
- registrationBuilder.OnActivated(context =>
+ var actions = activatedActionList.GetActions(serviceDescriptor);
+ if (actions.Any())
{
- var serviceActivatedContext = new OnServiceActivatedContext(context.Instance!);
- foreach (var action in activatedActionList.GetActions(serviceDescriptor))
+ registrationBuilder.OnActivated(context =>
{
- action.Invoke(serviceActivatedContext);
- }
- });
+ var serviceActivatedContext = new OnServiceActivatedContext(context.Instance!);
+ foreach (var action in actions)
+ {
+ action.Invoke(serviceActivatedContext);
+ }
+ });
+ }
return registrationBuilder;
}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs
index b068890b97..82ed962a4f 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs
@@ -80,7 +80,16 @@ public class DefaultExceptionToErrorInfoConverter : IExceptionToErrorInfoConvert
if (exception is AbpRemoteCallException remoteCallException && remoteCallException.Error != null)
{
- return remoteCallException.Error;
+ var remoteServiceErrorInfo = remoteCallException.Error;
+ if (remoteServiceErrorInfo.Message == AbpExceptionHandlingConsts.Unauthorized)
+ {
+ remoteServiceErrorInfo.Message = L[AbpExceptionHandlingConsts.Unauthorized];
+ }
+ if (remoteServiceErrorInfo.Details == AbpExceptionHandlingConsts.SessionExpired)
+ {
+ remoteServiceErrorInfo.Details = L[AbpExceptionHandlingConsts.SessionExpired];
+ }
+ return remoteServiceErrorInfo;
}
if (exception is AbpDbConcurrencyException)
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/AbpExceptionHandlingConsts.cs b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/AbpExceptionHandlingConsts.cs
new file mode 100644
index 0000000000..a571dabe38
--- /dev/null
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/AbpExceptionHandlingConsts.cs
@@ -0,0 +1,8 @@
+namespace Volo.Abp.ExceptionHandling;
+
+public static class AbpExceptionHandlingConsts
+{
+ public const string Unauthorized = "Unauthorized";
+ public const string InvalidToken = "invalid_token";
+ public const string SessionExpired = "SessionExpired";
+}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/ar.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/ar.json
index 0c5c74f95c..56af354487 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/ar.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/ar.json
@@ -21,6 +21,9 @@
"404Message": "الصفحة غير موجودة",
"500Message": "خطأ في الخادم الداخلي",
"403MessageDetail": "أنت غير مصرح لك لإجراء هذه العملية!",
- "404MessageDetail": "عذرا ، لا يوجد شيء في هذا العنوان."
+ "404MessageDetail": "عذرا ، لا يوجد شيء في هذا العنوان.",
+ "Unauthorized": "غير مصرح",
+ "invalid_token": "الرمز غير صالح",
+ "SessionExpired": "انتهت جلستك. يرجى تسجيل الدخول مرة أخرى لمتابعة التطبيق."
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/cs.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/cs.json
index 43e47ed12a..f5e9f08f49 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/cs.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/cs.json
@@ -21,6 +21,9 @@
"404Message": "Stránka nenalezena",
"500Message": "Interní chyba serveru",
"403MessageDetail": "K provedení této operace nemáte oprávnění!",
- "404MessageDetail": "Je nám líto, na této adrese nic není."
+ "404MessageDetail": "Je nám líto, na této adrese nic není.",
+ "Unauthorized": "Neoprávněno",
+ "invalid_token": "Neplatný token",
+ "SessionExpired": "Vaše relace vypršela. Přihlaste se znovu, abyste mohli pokračovat v aplikaci."
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/de.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/de.json
index 20f01e3bd2..1642f8b3a3 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/de.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/de.json
@@ -21,6 +21,9 @@
"404Message": "Seite nicht gefunden",
"500Message": "Interner Serverfehler",
"403MessageDetail": "Sie sind nicht berechtigt, diesen Vorgang durchzuführen!",
- "404MessageDetail": "Entschuldigung, unter dieser Adresse ist nichts."
+ "404MessageDetail": "Entschuldigung, unter dieser Adresse ist nichts.",
+ "Unauthorized": "Nicht autorisiert",
+ "invalid_token": "Ungültiges Token",
+ "SessionExpired": "Ihre Sitzung ist abgelaufen. Bitte melden Sie sich erneut an, um in der Anwendung fortzufahren."
}
}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/el.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/el.json
index 3b51a842ed..16648ef43e 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/el.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/el.json
@@ -21,6 +21,9 @@
"404Message": "Η σελίδα δεν βρέθηκε",
"500Message": "Εσωτερικό Σφάλμα Διακομιστή",
"403MessageDetail": "Δεν είστε εξουσιοδοτημένοι να εκτελέσετε αυτήν τη λειτουργία!",
- "404MessageDetail": "Λυπούμαστε, δεν υπάρχει τίποτα σε αυτή τη διεύθυνση."
+ "404MessageDetail": "Λυπούμαστε, δεν υπάρχει τίποτα σε αυτή τη διεύθυνση.",
+ "Unauthorized": "Μη εξουσιοδοτημένος",
+ "invalid_token": "Το token δ",
+ "SessionExpired": "Η συνεδρία σας έχει λήξει. Παρακαλώ συνδεθείτε ξανά για να συνεχίσετε στην εφαρμογή."
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/en-GB.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/en-GB.json
index 6ce1b857a4..1ee0703ee0 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/en-GB.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/en-GB.json
@@ -20,6 +20,9 @@
"404Message": "Page not found",
"500Message": "Internal Server Error",
"403MessageDetail": "You are not authorised to perform this operation!",
- "404MessageDetail": "Sorry, there's nothing at this address."
+ "404MessageDetail": "Sorry, there's nothing at this address.",
+ "Unauthorized": "Unauthorized",
+ "invalid_token": "Invalid token",
+ "SessionExpired": "Your session has expired. Please login again to continue in the application."
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/en.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/en.json
index de8d72e413..7d867c643f 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/en.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/en.json
@@ -5,7 +5,7 @@
"ValidationErrorMessage": "Your request is not valid!",
"ValidationNarrativeErrorMessageTitle": "The following errors were detected during validation.",
"DefaultErrorMessage": "An error has occurred!",
- "DefaultErrorMessageDetail": "Error detail not sent by server.",
+ "DefaultErrorMessageDetail": "Error detail not sent by the server.",
"DefaultErrorMessage401": "You are not authenticated!",
"DefaultErrorMessage401Detail": "You should sign in to perform this operation.",
"DefaultErrorMessage403": "You are not authorized!",
@@ -13,7 +13,7 @@
"DefaultErrorMessage404": "Resource not found!",
"DefaultErrorMessage404Detail": "The resource requested could not be found on the server!",
"EntityNotFoundErrorMessage": "There is no entity {0} with id = {1}!",
- "AbpDbConcurrencyErrorMessage": "The data you have submitted has already changed by another user/client. Please discard the changes you've done and try from the beginning.",
+ "AbpDbConcurrencyErrorMessage": "The data you have submitted has already been changed by another user. Discard your changes and try again.",
"Error": "Error",
"UnhandledException": "Unhandled exception!",
"401Message": "Unauthorized",
@@ -21,6 +21,9 @@
"404Message": "Page not found",
"500Message": "Internal Server Error",
"403MessageDetail": "You are not authorized to perform this operation!",
- "404MessageDetail": "Sorry, there's nothing at this address."
+ "404MessageDetail": "Sorry, there's nothing at this address.",
+ "Unauthorized": "Unauthorized",
+ "invalid_token": "Invalid token",
+ "SessionExpired": "Your session has expired. Please login again to continue in the application."
}
}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/es.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/es.json
index a62d214403..c8c9f0dd70 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/es.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/es.json
@@ -21,6 +21,9 @@
"404Message": "Página no encontrada",
"500Message": "Error interno de servidor",
"403MessageDetail": "Tu no estás autorizado para realizar esta operación!",
- "404MessageDetail": "Disculpa, no hay nada en esta dirección."
+ "404MessageDetail": "Disculpa, no hay nada en esta dirección.",
+ "Unauthorized": "No autorizado",
+ "invalid_token": "El token no es válido.",
+ "SessionExpired": "Tu sesión ha expirado. Por favor inicia sesión de nuevo para continuar en la aplicación."
}
}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/fa.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/fa.json
index 2e58d9d0ca..40309cbb9e 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/fa.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/fa.json
@@ -21,6 +21,9 @@
"404Message": "صفحه موردنظر یافت نشد",
"500Message": "خطای داخلی رخ داد",
"403MessageDetail": "شما مجاز به انجام این عملیات نمی باشید!",
- "404MessageDetail": "با عرض پورش، در این آدرس هیچ محتوایی وجود ندارد."
+ "404MessageDetail": "با عرض پورش، در این آدرس هیچ محتوایی وجود ندارد.",
+ "Unauthorized": "غیر مجاز",
+ "invalid_token": "توکن نامعتبر است",
+ "SessionExpired": "جلسه شما منقضی شده است. لطفاً مجددا وارد شوید تا در برنامه ادامه دهید."
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/fi.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/fi.json
index d0fb4fa795..778d33e81a 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/fi.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/fi.json
@@ -21,6 +21,9 @@
"404Message": "Sivua ei löydetty",
"500Message": "Sisäinen palvelinvirhe",
"403MessageDetail": "Sinulla ei ole oikeutta suorittaa tätä toimintoa!",
- "404MessageDetail": "Valitettavasti tässä osoitteessa ei ole mitään."
+ "404MessageDetail": "Valitettavasti tässä osoitteessa ei ole mitään.",
+ "Unauthorized": "Sinulla ei ole oikeutta suorittaa tätä toimintoa!",
+ "invalid_token": "Virheellinen token",
+ "SessionExpired": "Istuntosi on vanhentunut. Kirjaudu sisään jatkaaksesi sovelluksessa."
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/fr.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/fr.json
index 9ba1284260..61035b9e49 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/fr.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/fr.json
@@ -21,6 +21,9 @@
"404Message": "Page introuvable",
"500Message": "Erreur Interne du Serveur",
"403MessageDetail": "Vous n'êtes pas autorisé à effectuer cette opération!",
- "404MessageDetail": "Désolé, il n'y a rien à cette adresse."
+ "404MessageDetail": "Désolé, il n'y a rien à cette adresse.",
+ "Unauthorized": "Non autorisé",
+ "invalid_token": "Le jeton n'est pas valide.",
+ "SessionExpired": "Votre session a expiré. Veuillez vous reconnecter pour continuer dans l'application."
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/hi.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/hi.json
index 3bd5efa168..3344030e33 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/hi.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/hi.json
@@ -21,6 +21,9 @@
"404Message": "पृष्ठ नहीं मिला",
"500Message": "आंतरिक सर्वर त्रुटि",
"403MessageDetail": "आप इस ऑपरेशन को करने के लिए अधिकृत नहीं हैं!",
- "404MessageDetail": "क्षमा करें, इस पते पर कुछ भी नहीं है।"
+ "404MessageDetail": "क्षमा करें, इस पते पर कुछ भी नहीं है।",
+ "Unauthorized": "अनधिकृत",
+ "invalid_token": "टोकन अमान्य है",
+ "SessionExpired": "आपकी सत्र समाप्त हो गई है। कृपया आवेदन में जारी रखने के लिए फिर से लॉगिन करें।"
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/hr.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/hr.json
index e3a247e093..81681820d3 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/hr.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/hr.json
@@ -21,6 +21,9 @@
"404Message": "Stranica nije pronađena",
"500Message": "Interna pogreška poslužitelja",
"403MessageDetail": "Niste ovlašteni za izvođenje ove operacije!",
- "404MessageDetail": "Nažalost, na ovoj adresi nema ničega."
+ "404MessageDetail": "Nažalost, na ovoj adresi nema ničega.",
+ "Unauthorized": "Niste ovlašteni za izvođenje ove operacije.",
+ "invalid_token": "Neispravan token",
+ "SessionExpired": "Vaša sesija je istekla. Prijavite se ponovno kako biste nastavili s radom u aplikaciji."
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/hu.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/hu.json
index 16113f7d29..93ee7bac72 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/hu.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/hu.json
@@ -21,6 +21,9 @@
"404Message": "Az oldal nem található",
"500Message": "Belső Szerverhiba",
"403MessageDetail": "Ön nem jogosult ennek a műveletnek a végrehajtására!",
- "404MessageDetail": "Sajnos ezen a címen nincs semmi."
+ "404MessageDetail": "Sajnos ezen a címen nincs semmi.",
+ "Unauthorized": "Nem jogosult",
+ "invalid_token": "A token érv",
+ "SessionExpired": "A munkamenete lejárt. Kérjük, jelentkezzen be újra az alkalmazásban való folytatáshoz."
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/is.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/is.json
index e9ac02cab5..3b58238106 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/is.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/is.json
@@ -21,6 +21,9 @@
"404Message": "Síðan fannst ekki",
"500Message": "Villa í netþjóni",
"403MessageDetail": "Þú hefur ekki heimild fyrir þessa aðgerð!",
- "404MessageDetail": "Því miður, það er ekkert á þessu heimilisfangi."
+ "404MessageDetail": "Því miður, það er ekkert á þessu heimilisfangi.",
+ "Unauthorized": "Óheimilt",
+ "invalid_token": "Ógildur auðkenni",
+ "SessionExpired": "Sessían þín er útrunnin. Vinsamlegast skráðu þig inn aftur til að halda áfram í forritinu."
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/it.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/it.json
index c70e01cfd4..8415c7da6b 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/it.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/it.json
@@ -21,6 +21,9 @@
"404Message": "pagina non trovata",
"500Message": "Errore interno del server",
"403MessageDetail": "Non sei autorizzato a eseguire questa operazione!",
- "404MessageDetail": "Spiacenti, non c'è niente a questo indirizzo."
+ "404MessageDetail": "Spiacenti, non c'è niente a questo indirizzo.",
+ "Unauthorized": "Non autorizzato",
+ "invalid_token": "Token non valido",
+ "SessionExpired": "La tua sessione è scaduta. Effettua nuovamente il login per continuare nell'applicazione."
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/nl.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/nl.json
index 1f4be64b8f..2bf4426682 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/nl.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/nl.json
@@ -21,6 +21,9 @@
"404Message": "Pagina niet gevonden",
"500Message": "Interne Server Fout",
"403MessageDetail": "U bent niet bevoegd om deze handeling uit te voeren!",
- "404MessageDetail": "Sorry, op dit adres is niks gevonden."
+ "404MessageDetail": "Sorry, op dit adres is niks gevonden.",
+ "Unauthorized": "Niet geautoriseerd",
+ "invalid_token": "Ongeldig token",
+ "SessionExpired": "Uw sessie is verlopen. Log opnieuw in om door te gaan in de applicatie."
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/pl-PL.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/pl-PL.json
index 652e5e0c05..75f1c5b14b 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/pl-PL.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/pl-PL.json
@@ -21,6 +21,9 @@
"404Message": "Strona nie znaleziona",
"500Message": "Wewnętrzny błąd serwera",
"403MessageDetail": "Nie masz uprawnień do wykonania tej operacji!",
- "404MessageDetail": "Przepraszamy, pod tym adresem nic nie ma."
+ "404MessageDetail": "Przepraszamy, pod tym adresem nic nie ma.",
+ "Unauthorized": "Nieautoryzowany",
+ "invalid_token": "Nieprawidłowy token",
+ "SessionExpired": "Twoja sesja wygasła. Zaloguj się ponownie, aby kontynuować w aplikacji."
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/pt-BR.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/pt-BR.json
index dda12493ce..3cff127de9 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/pt-BR.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/pt-BR.json
@@ -21,6 +21,9 @@
"404Message": "Página não encontrada",
"500Message": "Erro interno do servidor",
"403MessageDetail": "Você não está autorizado a realizar esta operação!",
- "404MessageDetail": "Desculpe, não há nada neste endereço."
+ "404MessageDetail": "Desculpe, não há nada neste endereço.",
+ "Unauthorized": "Não autorizado",
+ "invalid_token": "Token inválido",
+ "SessionExpired": "Sua sessão expirou. Por favor, faça login novamente para continuar na aplicação."
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/ro-RO.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/ro-RO.json
index e04cf971e8..a2eed82369 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/ro-RO.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/ro-RO.json
@@ -21,6 +21,9 @@
"404Message": "Pagina nu a fost găsită",
"500Message": "Eroare internă a serverului",
"403MessageDetail": "Nu sunteţi autorizat să efectuaţi această operaţie!",
- "404MessageDetail": "Ne cerem scuze, nu este nimic la această adresă."
+ "404MessageDetail": "Ne cerem scuze, nu este nimic la această adresă.",
+ "Unauthorized": "Nu sunteţi autorizat să efectuaţi această operaţie.",
+ "invalid_token": "Tokenul nu este valid sau a expirat.",
+ "SessionExpired": "Sesiunea dumneavoastră a expirat. Vă rugăm să vă autentificaţi din nou pentru a continua în aplicaţie."
}
}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/ru.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/ru.json
index d9e86ef626..9c6ffbb784 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/ru.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/ru.json
@@ -21,6 +21,9 @@
"404Message": "Страница не найдена",
"500Message": "Внутренняя ошибка сервера",
"403MessageDetail": "У вас нет прав на выполнение этой операции!",
- "404MessageDetail": "Извините, по этому адресу ничего нет."
+ "404MessageDetail": "Извините, по этому адресу ничего нет.",
+ "Unauthorized": "Неавторизованный",
+ "invalid_token": "Неверный токен",
+ "SessionExpired": "Ваша сессия истекла. Пожалуйста, войдите снова, чтобы продолжить работу в приложении."
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/sk.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/sk.json
index b0f0e896c3..22af7956c8 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/sk.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/sk.json
@@ -21,6 +21,9 @@
"404Message": "Stránka nebola nájdená",
"500Message": "Interná chyba servera",
"403MessageDetail": "Nie ste oprávnený vykonávať túto operáciu!",
- "404MessageDetail": "Je nám ľúto, ale na tejto adrese sa nič nenachádza."
+ "404MessageDetail": "Je nám ľúto, ale na tejto adrese sa nič nenachádza.",
+ "Unauthorized": "Neoprávnený",
+ "invalid_token": "Neplatný token",
+ "SessionExpired": "Vaša relácia vypršala. Prihláste sa znova, aby ste mohli pokračovať v aplikácii."
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/sl.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/sl.json
index 55e1d3320e..fc5f86a8b1 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/sl.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/sl.json
@@ -21,6 +21,9 @@
"404Message": "Strani ni mogoče najti",
"500Message": "Napaka na strani strežnika",
"403MessageDetail": "Niste pooblaščeni za izvajanje te operacije!",
- "404MessageDetail": "Oprostite, na tem naslovu ni ničesar."
+ "404MessageDetail": "Oprostite, na tem naslovu ni ničesar.",
+ "Unauthorized": "Niste prijavljeni!",
+ "invalid_token": "Neveljaven žeton",
+ "SessionExpired": "Vaša seja je potekla. Za nadaljevanje v aplikaciji se ponovno prijavite."
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/tr.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/tr.json
index a75684ff1e..d6144a5548 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/tr.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/tr.json
@@ -21,6 +21,9 @@
"404Message": "Sayfa bulunamadı",
"500Message": "Sunucu tarafında hata",
"403MessageDetail": "Bu işlemi gerçekleştirmek için gereken yetkiye sahip değilsiniz!",
- "404MessageDetail": "Üzgünüz, bu adreste bir şey yok."
+ "404MessageDetail": "Üzgünüz, bu adreste bir şey yok.",
+ "Unauthorized": "Yetkisiz",
+ "invalid_token": "Geçersiz token",
+ "SessionExpired": "Oturumunuz sona erdi. Uygulamaya devam etmek için lütfen tekrar giriş yapın."
}
}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/vi.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/vi.json
index ca29598867..ff6398b08d 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/vi.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/vi.json
@@ -21,6 +21,9 @@
"404Message": "Không tìm thấy trang",
"500Message": "Lỗi máy chủ nội bộ",
"403MessageDetail": "Bạn không được phép thực hiện thao tác này!",
- "404MessageDetail": "Xin lỗi, không có gì ở địa chỉ này."
+ "404MessageDetail": "Xin lỗi, không có gì ở địa chỉ này.",
+ "Unauthorized": "Không được phép",
+ "invalid_token": "Token không hợp lệ",
+ "SessionExpired": "Phiên của bạn đã hết hạn. Vui lòng đăng nhập lại để tiếp tục trong ứng dụng."
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/zh-Hans.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/zh-Hans.json
index cc408a8b75..91b95b1d99 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/zh-Hans.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/zh-Hans.json
@@ -21,6 +21,9 @@
"404Message": "未找到页面",
"500Message": "内部服务器错误",
"403MessageDetail": "您无权执行此操作!",
- "404MessageDetail": "抱歉,这个地址没有任何信息。"
+ "404MessageDetail": "抱歉,这个地址没有任何信息。",
+ "Unauthorized": "未经授权",
+ "invalid_token": "无效的令牌",
+ "SessionExpired": "您的会话已过期。请重新登录以继续应用程序。"
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/zh-Hant.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/zh-Hant.json
index 65d4f657dd..23c6409de4 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/zh-Hant.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/zh-Hant.json
@@ -21,6 +21,9 @@
"404Message": "網頁未找到",
"500Message": "內部伺服器錯誤",
"403MessageDetail": "你不被授權執行此操作",
- "404MessageDetail": "對不起,地址是空的"
+ "404MessageDetail": "對不起,地址是空的",
+ "Unauthorized": "未授權",
+ "invalid_token": "無效的令牌",
+ "SessionExpired": "你的會話已過期.請重新登入以繼續應用程式."
}
}
diff --git a/framework/src/Volo.Abp.Http.Abstractions/Volo/Abp/Http/ClientProxyExceptionEventData.cs b/framework/src/Volo.Abp.Http.Abstractions/Volo/Abp/Http/ClientProxyExceptionEventData.cs
index 029556c00e..9ac2a0b5cd 100644
--- a/framework/src/Volo.Abp.Http.Abstractions/Volo/Abp/Http/ClientProxyExceptionEventData.cs
+++ b/framework/src/Volo.Abp.Http.Abstractions/Volo/Abp/Http/ClientProxyExceptionEventData.cs
@@ -5,4 +5,10 @@ public class ClientProxyExceptionEventData
public int? StatusCode { get; set; }
public string? ReasonPhrase { get; set; }
+
+ public string? Error { get; set; }
+
+ public string? ErrorDescription { get; set; }
+
+ public string? ErrorUri { get; set; }
}
diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs
index 8dee0fcc3e..1cab08f73d 100644
--- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs
+++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs
@@ -4,8 +4,10 @@ using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
+using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
using Volo.Abp.Content;
@@ -218,10 +220,21 @@ public class ClientProxyBase : ITransientDependency
protected virtual async Task ThrowExceptionForResponseAsync(HttpResponseMessage response)
{
+ var wwwAuthenticate = response.Headers.WwwAuthenticate.ToString() ?? string.Empty;
+ var errorMatch = Regex.Match(wwwAuthenticate, "error=\"([^\"]+)\"");
+ var errorDescriptionMatch = Regex.Match(wwwAuthenticate, "error_description=\"([^\"]+)\"");
+ var errorUriMatch = Regex.Match(wwwAuthenticate, "error_uri=\"([^\"]+)\"");
+ var error = errorMatch.Success ? errorMatch.Groups.Count == 2 ? errorMatch.Groups[1].Value : null : null;
+ var errorDescription = errorDescriptionMatch.Success ? errorDescriptionMatch.Groups.Count == 2 ? errorDescriptionMatch.Groups[1].Value : null : null;
+ var errorUri = errorUriMatch.Success ? errorUriMatch.Groups.Count == 2 ? errorUriMatch.Groups[1].Value : null : null;
+
await LocalEventBus.PublishAsync(new ClientProxyExceptionEventData()
{
StatusCode = (int?)response.StatusCode,
- ReasonPhrase = response.ReasonPhrase
+ ReasonPhrase = response.ReasonPhrase,
+ Error = error,
+ ErrorDescription = errorDescription,
+ ErrorUri = errorUri,
});
if (response.Headers.Contains(AbpHttpConsts.AbpErrorFormat))
@@ -239,7 +252,8 @@ public class ClientProxyBase : ITransientDependency
new RemoteServiceErrorInfo
{
Message = response.ReasonPhrase,
- Code = response.StatusCode.ToString()
+ Code = response.StatusCode.ToString(),
+ Details = errorDescription
},
ex
)
@@ -259,7 +273,8 @@ public class ClientProxyBase : ITransientDependency
new RemoteServiceErrorInfo
{
Message = response.ReasonPhrase,
- Code = response.StatusCode.ToString()
+ Code = response.StatusCode.ToString(),
+ Details = errorDescription
}
)
{
diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs
index 3afa1b8bde..498dedd8cd 100644
--- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs
+++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs
@@ -34,7 +34,9 @@ public class AbpJsonSystemTextJsonModule : AbpModule
context.Services.AddOptions()
.Configure((options, rootServiceProvider) =>
{
- options.Modifiers.Add(new AbpDateTimeConverterModifier().CreateModifyAction(rootServiceProvider));
+ options.Modifiers.Add(new AbpDateTimeConverterModifier(
+ rootServiceProvider.GetRequiredService(),
+ rootServiceProvider.GetRequiredService()).CreateModifyAction());
});
}
}
diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpDateTimeConverterModifier.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpDateTimeConverterModifier.cs
index ba19ccfa29..d940a80ea0 100644
--- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpDateTimeConverterModifier.cs
+++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpDateTimeConverterModifier.cs
@@ -10,11 +10,17 @@ namespace Volo.Abp.Json.SystemTextJson.Modifiers;
public class AbpDateTimeConverterModifier
{
- private IServiceProvider _serviceProvider = default!;
+ private readonly AbpDateTimeConverter _abpDateTimeConverter;
+ private readonly AbpNullableDateTimeConverter _abpNullableDateTimeConverter;
- public Action CreateModifyAction(IServiceProvider serviceProvider)
+ public AbpDateTimeConverterModifier(AbpDateTimeConverter abpDateTimeConverter, AbpNullableDateTimeConverter abpNullableDateTimeConverter)
+ {
+ _abpDateTimeConverter = abpDateTimeConverter;
+ _abpNullableDateTimeConverter = abpNullableDateTimeConverter;
+ }
+
+ public Action CreateModifyAction()
{
- _serviceProvider = serviceProvider;
return Modify;
}
@@ -31,8 +37,8 @@ public class AbpDateTimeConverterModifier
!property.AttributeProvider.GetCustomAttributes(typeof(DisableDateTimeNormalizationAttribute), false).Any())
{
property.CustomConverter = property.PropertyType == typeof(DateTime)
- ? _serviceProvider.GetRequiredService()
- : _serviceProvider.GetRequiredService();
+ ? _abpDateTimeConverter
+ : _abpNullableDateTimeConverter;
}
}
}
diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimsPrincipalFactory.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimsPrincipalFactory.cs
index b0e9fea653..b744830e59 100644
--- a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimsPrincipalFactory.cs
+++ b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimsPrincipalFactory.cs
@@ -1,4 +1,5 @@
-using System.Security.Claims;
+using System;
+using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
@@ -10,14 +11,14 @@ public class AbpClaimsPrincipalFactory : IAbpClaimsPrincipalFactory, ITransientD
{
public static string AuthenticationType => "Abp.Application";
- protected IServiceScopeFactory ServiceScopeFactory { get; }
+ protected IServiceProvider ServiceProvider { get; }
protected AbpClaimsPrincipalFactoryOptions Options { get; }
public AbpClaimsPrincipalFactory(
- IServiceScopeFactory serviceScopeFactory,
+ IServiceProvider serviceProvider,
IOptions abpClaimOptions)
{
- ServiceScopeFactory = serviceScopeFactory;
+ ServiceProvider = serviceProvider;
Options = abpClaimOptions.Value;
}
@@ -33,33 +34,30 @@ public class AbpClaimsPrincipalFactory : IAbpClaimsPrincipalFactory, ITransientD
public virtual async Task InternalCreateAsync(AbpClaimsPrincipalFactoryOptions options, ClaimsPrincipal? existsClaimsPrincipal = null, bool isDynamic = false)
{
- using (var scope = ServiceScopeFactory.CreateScope())
- {
- var claimsPrincipal = existsClaimsPrincipal ?? new ClaimsPrincipal(new ClaimsIdentity(
- AuthenticationType,
- AbpClaimTypes.UserName,
- AbpClaimTypes.Role));
+ var claimsPrincipal = existsClaimsPrincipal ?? new ClaimsPrincipal(new ClaimsIdentity(
+ AuthenticationType,
+ AbpClaimTypes.UserName,
+ AbpClaimTypes.Role));
- var context = new AbpClaimsPrincipalContributorContext(claimsPrincipal, scope.ServiceProvider);
+ var context = new AbpClaimsPrincipalContributorContext(claimsPrincipal, ServiceProvider);
- if (!isDynamic)
+ if (!isDynamic)
+ {
+ foreach (var contributorType in options.Contributors)
{
- foreach (var contributorType in options.Contributors)
- {
- var contributor = (IAbpClaimsPrincipalContributor)scope.ServiceProvider.GetRequiredService(contributorType);
- await contributor.ContributeAsync(context);
- }
+ var contributor = (IAbpClaimsPrincipalContributor)ServiceProvider.GetRequiredService(contributorType);
+ await contributor.ContributeAsync(context);
}
- else
+ }
+ else
+ {
+ foreach (var contributorType in options.DynamicContributors)
{
- foreach (var contributorType in options.DynamicContributors)
- {
- var contributor = (IAbpDynamicClaimsPrincipalContributor)scope.ServiceProvider.GetRequiredService(contributorType);
- await contributor.ContributeAsync(context);
- }
+ var contributor = (IAbpDynamicClaimsPrincipalContributor)ServiceProvider.GetRequiredService(contributorType);
+ await contributor.ContributeAsync(context);
}
-
- return context.ClaimsPrincipal;
}
+
+ return context.ClaimsPrincipal;
}
}
diff --git a/framework/src/Volo.Abp.TestBase/Volo/Abp/Testing/AbpAsyncIntegratedTest.cs b/framework/src/Volo.Abp.TestBase/Volo/Abp/Testing/AbpAsyncIntegratedTest.cs
index 4004c110a4..568aee5675 100644
--- a/framework/src/Volo.Abp.TestBase/Volo/Abp/Testing/AbpAsyncIntegratedTest.cs
+++ b/framework/src/Volo.Abp.TestBase/Volo/Abp/Testing/AbpAsyncIntegratedTest.cs
@@ -34,6 +34,10 @@ public class AbpAsyncIntegratedTest : AbpTestBaseWithServiceProv
public virtual async Task DisposeAsync()
{
await Application.ShutdownAsync();
+ if (RootServiceProvider is IDisposable disposable)
+ {
+ disposable.Dispose();
+ }
TestServiceScope.Dispose();
Application.Dispose();
}
diff --git a/framework/src/Volo.Abp.TestBase/Volo/Abp/Testing/AbpIntegratedTest.cs b/framework/src/Volo.Abp.TestBase/Volo/Abp/Testing/AbpIntegratedTest.cs
index 8d8612c5b9..9427c1de85 100644
--- a/framework/src/Volo.Abp.TestBase/Volo/Abp/Testing/AbpIntegratedTest.cs
+++ b/framework/src/Volo.Abp.TestBase/Volo/Abp/Testing/AbpIntegratedTest.cs
@@ -60,6 +60,10 @@ public abstract class AbpIntegratedTest : AbpTestBaseWithService
{
Application.Shutdown();
TestServiceScope.Dispose();
+ if (RootServiceProvider is IDisposable disposable)
+ {
+ disposable.Dispose();
+ }
Application.Dispose();
}
}
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestController_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestController_Tests.cs
index 1b79441de8..40fb77c432 100644
--- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestController_Tests.cs
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestController_Tests.cs
@@ -108,7 +108,7 @@ public class ExceptionTestController_Tests : AspNetCoreMvcTestBase
var result = await GetResponseAsObjectAsync("/api/exception-test/ExceptionOnUowSaveChange", HttpStatusCode.Conflict);
result.Error.ShouldNotBeNull();
- result.Error.Message.ShouldBe("The data you have submitted has already changed by another user/client. Please discard the changes you've done and try from the beginning.");
+ result.Error.Message.ShouldBe("The data you have submitted has already been changed by another user. Discard your changes and try again.");
#pragma warning disable 4014
_fakeExceptionSubscriber
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage_Tests.cs
index 48ccf6499f..c5bce679a0 100644
--- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage_Tests.cs
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage_Tests.cs
@@ -156,7 +156,7 @@ public class ExceptionTestPage_Tests : AspNetCoreMvcTestBase
var result = await GetResponseAsObjectAsync("/api/exception-test/ExceptionOnUowSaveChange", HttpStatusCode.Conflict);
result.Error.ShouldNotBeNull();
- result.Error.Message.ShouldBe("The data you have submitted has already changed by another user/client. Please discard the changes you've done and try from the beginning.");
+ result.Error.Message.ShouldBe("The data you have submitted has already been changed by another user. Discard your changes and try again.");
#pragma warning disable 4014
_fakeExceptionSubscriber
diff --git a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpDateTimeConverter_Tests.cs b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpDateTimeConverter_Tests.cs
index 7b1a0d81ce..f3001d89a0 100644
--- a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpDateTimeConverter_Tests.cs
+++ b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpDateTimeConverter_Tests.cs
@@ -3,6 +3,7 @@ using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization.Metadata;
using Shouldly;
+using Volo.Abp.Json.SystemTextJson.JsonConverters;
using Volo.Abp.Json.SystemTextJson.Modifiers;
using Volo.Abp.Localization;
using Xunit;
@@ -21,7 +22,13 @@ public class AbpDatetimeToEnum_Tests : AbpJsonSystemTextJsonTestBase
{
TypeInfoResolver = new DefaultJsonTypeInfoResolver()
{
- Modifiers = { new AbpDateTimeConverterModifier().CreateModifyAction(ServiceProvider) }
+ Modifiers =
+ {
+ new AbpDateTimeConverterModifier(
+ GetRequiredService(),
+ GetRequiredService())
+ .CreateModifyAction()
+ }
}
};
diff --git a/latest-versions.json b/latest-versions.json
index 82a4ddc6d4..298c513d8d 100644
--- a/latest-versions.json
+++ b/latest-versions.json
@@ -1,6 +1,6 @@
[
{
- "version": "8.1.4",
+ "version": "8.2.0",
"releaseDate": "",
"type": "stable",
"message": ""
diff --git a/npm/packs/sweetalert2/package.json b/npm/packs/sweetalert2/package.json
index 1982c29a18..69f46ed542 100644
--- a/npm/packs/sweetalert2/package.json
+++ b/npm/packs/sweetalert2/package.json
@@ -11,7 +11,8 @@
},
"dependencies": {
"@abp/core": "~8.2.0",
- "sweetalert2": "^11.3.6" // Keep it as the current version
+ "sweetalert2": "^11.3.6",
+ "comment": "Keep the version of sweetalert2 as the current one."
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431",
"homepage": "https://abp.io",
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj
index 3077271ffd..f65ab7f0a5 100644
--- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj
+++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj
@@ -16,9 +16,7 @@
-
-
-
+
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs
index 74c74d8a4e..2c0b3838e0 100644
--- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs
+++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs
@@ -17,6 +17,7 @@ using MyCompanyName.MyProjectName.MultiTenancy;
using StackExchange.Redis;
using Microsoft.OpenApi.Models;
using Volo.Abp;
+using Volo.Abp.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy;
using Volo.Abp.AspNetCore.Serilog;
@@ -39,6 +40,7 @@ namespace MyCompanyName.MyProjectName;
typeof(AbpCachingStackExchangeRedisModule),
typeof(AbpDistributedLockingModule),
typeof(AbpAspNetCoreMvcUiMultiTenancyModule),
+ typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(MyProjectNameApplicationModule),
typeof(MyProjectNameEntityFrameworkCoreModule),
typeof(AbpAspNetCoreSerilogModule),
@@ -101,7 +103,7 @@ public class MyProjectNameHttpApiHostModule : AbpModule
private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
- .AddJwtBearer(options =>
+ .AddAbpJwtBearer(options =>
{
options.Authority = configuration["AuthServer:Authority"];
options.RequireHttpsMetadata = configuration.GetValue("AuthServer:RequireHttpsMetadata");
diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj
index ffa2d840d3..f56f04fccc 100644
--- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj
+++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj
@@ -17,9 +17,7 @@
-
-
-
+
diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs
index bca552e0d0..bb759d2386 100644
--- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs
+++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs
@@ -15,6 +15,7 @@ using MyCompanyName.MyProjectName.MultiTenancy;
using StackExchange.Redis;
using Microsoft.OpenApi.Models;
using Volo.Abp;
+using Volo.Abp.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
using Volo.Abp.AspNetCore.Serilog;
@@ -41,6 +42,7 @@ namespace MyCompanyName.MyProjectName;
typeof(MyProjectNameEntityFrameworkCoreModule),
typeof(MyProjectNameHttpApiModule),
typeof(AbpAspNetCoreMvcUiMultiTenancyModule),
+ typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(AbpAutofacModule),
typeof(AbpCachingStackExchangeRedisModule),
typeof(AbpEntityFrameworkCoreSqlServerModule),
@@ -118,7 +120,7 @@ public class MyProjectNameHttpApiHostModule : AbpModule
});
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
- .AddJwtBearer(options =>
+ .AddAbpJwtBearer(options =>
{
options.Authority = configuration["AuthServer:Authority"];
options.RequireHttpsMetadata = configuration.GetValue("AuthServer:RequireHttpsMetadata");