mirror of https://github.com/abpframework/abp.git
445 changed files with 399584 additions and 569 deletions
@ -0,0 +1,84 @@ |
|||
# ABP.IO Platform 8.0 Has Been Released Based on .NET 8.0 |
|||
|
|||
Today, [ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) 8.0 versions have been released based on [.NET 8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0). |
|||
|
|||
## What's New With Version 8.0? |
|||
|
|||
All the new features were explained in detail in the [8.0 RC Announcement Post](https://blog.abp.io/abp/announcing-abp-8-0-release-candidate), so there is no need to review them again. You can check it out for more details. |
|||
|
|||
## Getting Started with 8.0 |
|||
|
|||
### Creating New Solutions |
|||
|
|||
You can create a new solution with the ABP Framework version 8.0 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 breaking changes in this version that may affect your application. |
|||
Please see the following migration documents if you are upgrading from v7.x or earlier: |
|||
|
|||
* [ABP Framework 7.x to 8.0 Migration Guide](https://docs.abp.io/en/abp/8.0/Migration-Guides/Abp-8_0) |
|||
* [ABP Commercial 7.x to 8.0 Migration Guide](https://docs.abp.io/en/commercial/8.0/migration-guides/v8_0) |
|||
|
|||
## Community News |
|||
|
|||
### We were at China .NET Conf 2023 |
|||
|
|||
China's most influential .NET event officially kicked off on December 16, 2023. The conference has invited 30+ technical experts from various fields to share the new features of .NET 8, full-stack Blazor, AI, .NET MAUI, and more... |
|||
|
|||
 |
|||
|
|||
As one of the community partners of .NET Conf China 2023, our ABP.IO China team was at the event. At the event, we showed developers the latest news and related updates on ABP.IO. |
|||
|
|||
Through this event, we gained a lot and felt the enthusiasm and support of the developers community for ABP.IO. If you want to learn more, we have shared our impressions and takeaways in a blog post, which you can find at [https://blog.abp.io/abp/ABP-at-China-NET-Conf-2023](https://blog.abp.io/abp/ABP-at-China-NET-Conf-2023). |
|||
|
|||
### ABP Commercial Won 5 Recognitions from Gartner |
|||
|
|||
 |
|||
|
|||
2023 was the year for ABP.IO to strive with the community. On top of last year's [Software Advice's Front Runner of Application Development in 2022](https://blog.abp.io/abp/abpcommercial-2022-front-runner-in-app-development-category) and [GetApp's Application Development Category Leader in 2022](https://blog.abp.io/abp/abpcommercial-2022-category-leader-in-app-development-category), we won **5 awards** this year from **Gartner**! |
|||
|
|||
> If you are interested in these awards and want to learn more, you can check out our [blog post](https://blog.abp.io/abp/ABP-Commercial-Won-5-Recognitions-from-Gartner-in-2023)! |
|||
|
|||
### New ABP Community Posts |
|||
|
|||
There are exciting articles contributed by the ABP community, as always. I will highlight some of them here: |
|||
|
|||
* [Performance Optimization of .NET-based application](https://community.abp.io/posts/performance-optimization-of-.netbased-and-also-abpbased-application-pmdwhwxc) by [Leon Košak](https://github.com/leonkosak) |
|||
* [Video: ABP Framework Consuming HTTP APIs from a .NET Client](https://community.abp.io/videos/abp-framework-consuming-http-apis-from-a-.net-client-uzul9og4) by [Hamza Albreem](https://github.com/braim23) |
|||
|
|||
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.1. 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. |
|||
|
After Width: | Height: | Size: 237 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 235 KiB |
@ -0,0 +1,49 @@ |
|||
using System; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using System.Threading.Tasks; |
|||
using NuGet.Versioning; |
|||
using Volo.Abp.Cli.Utils; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.Cli.Version; |
|||
|
|||
public class CliVersionService : ITransientDependency |
|||
{ |
|||
private CmdHelper CmdHelper { get; } |
|||
|
|||
public CliVersionService(CmdHelper cmdHelper) |
|||
{ |
|||
CmdHelper = cmdHelper; |
|||
} |
|||
|
|||
public async Task<SemanticVersion> GetCurrentCliVersionAsync() |
|||
{ |
|||
SemanticVersion currentCliVersion = default; |
|||
|
|||
var consoleOutput = new StringReader(CmdHelper.RunCmdAndGetOutput($"dotnet tool list -g", out int exitCode)); |
|||
string line; |
|||
while ((line = await consoleOutput.ReadLineAsync()) != null) |
|||
{ |
|||
if (line.StartsWith("volo.abp.cli", StringComparison.InvariantCultureIgnoreCase)) |
|||
{ |
|||
var version = line.Split(new char[0], StringSplitOptions.RemoveEmptyEntries)[1]; |
|||
|
|||
SemanticVersion.TryParse(version, out currentCliVersion); |
|||
|
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (currentCliVersion == null) |
|||
{ |
|||
// If not a tool executable, fallback to assembly version and treat as dev without updates
|
|||
// Assembly revisions are not supported by SemVer scheme required for NuGet, trim to {major}.{minor}.{patch}
|
|||
var assemblyVersion = string.Join(".", Assembly.GetExecutingAssembly().GetFileVersion().Split('.').Take(3)); |
|||
return SemanticVersion.Parse(assemblyVersion + "-dev"); |
|||
} |
|||
|
|||
return currentCliVersion; |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.MultiTenancy; |
|||
|
|||
public interface IMultiTenantUrlProvider |
|||
{ |
|||
Task<string> GetUrlAsync(string templateUrl); |
|||
} |
|||
@ -0,0 +1,78 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.MultiTenancy; |
|||
|
|||
public class MultiTenantUrlProvider : IMultiTenantUrlProvider , ITransientDependency |
|||
{ |
|||
public const string TenantPlaceHolder = "{0}"; |
|||
public const string TenantIdPlaceHolder = "{{tenantId}}"; |
|||
public const string TenantNamePlaceHolder = "{{tenantName}}"; |
|||
|
|||
protected ICurrentTenant CurrentTenant { get; } |
|||
protected ITenantStore TenantStore { get; } |
|||
|
|||
public MultiTenantUrlProvider( |
|||
ICurrentTenant currentTenant, |
|||
ITenantStore tenantStore) |
|||
{ |
|||
CurrentTenant = currentTenant; |
|||
TenantStore = tenantStore; |
|||
} |
|||
|
|||
public virtual async Task<string> GetUrlAsync(string templateUrl) |
|||
{ |
|||
return await ReplacePlaceHoldersAsync(templateUrl); |
|||
} |
|||
|
|||
protected virtual async Task<string> ReplacePlaceHoldersAsync(string templateUrl) |
|||
{ |
|||
templateUrl = await ReplacePlaceHolderAsync(templateUrl, TenantIdPlaceHolder); |
|||
|
|||
templateUrl = await ReplacePlaceHolderAsync(templateUrl, TenantNamePlaceHolder); |
|||
|
|||
templateUrl = await ReplacePlaceHolderAsync(templateUrl, TenantPlaceHolder); |
|||
|
|||
return templateUrl; |
|||
} |
|||
|
|||
protected virtual async Task<string> ReplacePlaceHolderAsync(string templateUrl, string placeHolder) |
|||
{ |
|||
if (!templateUrl.Contains(placeHolder)) |
|||
{ |
|||
return templateUrl; |
|||
} |
|||
|
|||
var placeHolderValue = string.Empty; |
|||
if (CurrentTenant.IsAvailable) |
|||
{ |
|||
placeHolderValue = (placeHolder == TenantIdPlaceHolder ? CurrentTenant.Id!.Value.ToString() : await GetCurrentTenantNameAsync()) + "."; |
|||
} |
|||
|
|||
if (templateUrl.Contains(placeHolder + '.')) |
|||
{ |
|||
placeHolder += '.'; |
|||
} |
|||
|
|||
templateUrl = templateUrl.Replace( |
|||
placeHolder, |
|||
placeHolderValue |
|||
); |
|||
|
|||
return templateUrl; |
|||
} |
|||
|
|||
protected virtual async Task<string> GetCurrentTenantNameAsync() |
|||
{ |
|||
if (CurrentTenant.Id.HasValue && CurrentTenant.Name.IsNullOrEmpty()) |
|||
{ |
|||
var tenantConfiguration = await TenantStore.FindAsync(CurrentTenant.Id.Value); |
|||
return tenantConfiguration!.Name; |
|||
} |
|||
|
|||
return CurrentTenant.Name!; |
|||
} |
|||
} |
|||
@ -1,25 +1,54 @@ |
|||
using System.Threading.Tasks; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace Volo.Abp.Http.Client; |
|||
|
|||
public class RemoteServiceConfigurationProvider : IRemoteServiceConfigurationProvider, IScopedDependency |
|||
{ |
|||
protected AbpRemoteServiceOptions Options { get; } |
|||
protected IMultiTenantUrlProvider MultiTenantUrlProvider { get; } |
|||
protected ICurrentTenant CurrentTenant { get; } |
|||
|
|||
public RemoteServiceConfigurationProvider(IOptionsMonitor<AbpRemoteServiceOptions> options) |
|||
public RemoteServiceConfigurationProvider( |
|||
IOptionsMonitor<AbpRemoteServiceOptions> options, |
|||
IMultiTenantUrlProvider multiTenantUrlProvider, |
|||
ICurrentTenant currentTenant) |
|||
{ |
|||
MultiTenantUrlProvider = multiTenantUrlProvider; |
|||
CurrentTenant = currentTenant; |
|||
Options = options.CurrentValue; |
|||
} |
|||
|
|||
public Task<RemoteServiceConfiguration> GetConfigurationOrDefaultAsync(string name) |
|||
public virtual async Task<RemoteServiceConfiguration> GetConfigurationOrDefaultAsync(string name) |
|||
{ |
|||
return Task.FromResult(Options.RemoteServices.GetConfigurationOrDefault(name)); |
|||
return (await GetMultiTenantConfigurationAsync(Options.RemoteServices.GetConfigurationOrDefault(name)))!; |
|||
} |
|||
|
|||
public Task<RemoteServiceConfiguration?> GetConfigurationOrDefaultOrNullAsync(string name) |
|||
public virtual async Task<RemoteServiceConfiguration?> GetConfigurationOrDefaultOrNullAsync(string name) |
|||
{ |
|||
return Task.FromResult(Options.RemoteServices.GetConfigurationOrDefaultOrNull(name)); |
|||
return await GetMultiTenantConfigurationAsync(Options.RemoteServices.GetConfigurationOrDefaultOrNull(name)); |
|||
} |
|||
|
|||
protected virtual async Task<RemoteServiceConfiguration?> GetMultiTenantConfigurationAsync(RemoteServiceConfiguration? configuration) |
|||
{ |
|||
if (configuration == null) |
|||
{ |
|||
return configuration; |
|||
} |
|||
|
|||
var baseUrl = await MultiTenantUrlProvider.GetUrlAsync(configuration.BaseUrl); |
|||
if (baseUrl == configuration.BaseUrl) |
|||
{ |
|||
return configuration; |
|||
} |
|||
|
|||
var multiTenantConfiguration = new RemoteServiceConfiguration(configuration) |
|||
{ |
|||
BaseUrl = baseUrl |
|||
}; |
|||
|
|||
return multiTenantConfiguration; |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,57 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Shouldly; |
|||
using Volo.Abp.MultiTenancy.ConfigurationStore; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.MultiTenancy; |
|||
|
|||
public class MultiTenantUrlProivder_Tests : MultiTenancyTestBase |
|||
{ |
|||
private readonly ICurrentTenant _currentTenant; |
|||
private readonly IMultiTenantUrlProvider _multiTenantUrlProvider; |
|||
|
|||
private readonly Guid _tenantAId = Guid.NewGuid(); |
|||
|
|||
public MultiTenantUrlProivder_Tests() |
|||
{ |
|||
_currentTenant = ServiceProvider.GetRequiredService<ICurrentTenant>(); |
|||
_multiTenantUrlProvider = ServiceProvider.GetRequiredService<IMultiTenantUrlProvider>(); |
|||
} |
|||
protected override void BeforeAddApplication(IServiceCollection services) |
|||
{ |
|||
services.Configure<AbpDefaultTenantStoreOptions>(options => |
|||
{ |
|||
options.Tenants = |
|||
[ |
|||
new TenantConfiguration(_tenantAId, "TenantA") |
|||
]; |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task GetUrlAsync() |
|||
{ |
|||
var tenantNameHolderUrl = "https://{{tenantName}}.abp.io"; |
|||
var tenantIdHolderUrl = "https://{{tenantId}}.abp.io"; |
|||
var tenantHolderUrl = "https://{0}.abp.io"; |
|||
var hostUrl = "https://abp.io"; |
|||
|
|||
_currentTenant.Id.ShouldBeNull(); |
|||
(await _multiTenantUrlProvider.GetUrlAsync(tenantNameHolderUrl)).ShouldBe(hostUrl); |
|||
(await _multiTenantUrlProvider.GetUrlAsync(tenantIdHolderUrl)).ShouldBe(hostUrl); |
|||
(await _multiTenantUrlProvider.GetUrlAsync(tenantHolderUrl)).ShouldBe(hostUrl); |
|||
(await _multiTenantUrlProvider.GetUrlAsync(hostUrl)).ShouldBe(hostUrl); |
|||
|
|||
using (_currentTenant.Change(_tenantAId)) |
|||
{ |
|||
_currentTenant.Id.ShouldBe(_tenantAId); |
|||
(await _multiTenantUrlProvider.GetUrlAsync(tenantNameHolderUrl)).ShouldBe("https://TenantA.abp.io"); |
|||
(await _multiTenantUrlProvider.GetUrlAsync(tenantIdHolderUrl)).ShouldBe("https://"+_tenantAId+".abp.io"); |
|||
(await _multiTenantUrlProvider.GetUrlAsync(tenantHolderUrl)).ShouldBe("https://TenantA.abp.io"); |
|||
(await _multiTenantUrlProvider.GetUrlAsync(hostUrl)).ShouldBe(hostUrl); |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\common.test.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net8.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\src\Volo.Abp.RemoteServices\Volo.Abp.RemoteServices.csproj" /> |
|||
<ProjectReference Include="..\..\src\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj" /> |
|||
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" /> |
|||
<PackageReference Include="Microsoft.NET.Test.Sdk" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue