mirror of https://github.com/abpframework/abp.git
253 changed files with 2200 additions and 28246 deletions
@ -0,0 +1,44 @@ |
|||||
|
## Streamline Localization in Your ABP Project |
||||
|
|
||||
|
Making localization changes to an ABP project can be a daunting task, especially if you're dealing with multiple languages and translations. During development, it's easy to overlook some changes and that leads to inconsistencies across different languages. Fortunately, I have developed a tool that can help streamline the localization process and ensure consistency across different languages. |
||||
|
|
||||
|
The tool is a console application that uses JSON files to manage localization keys and their translations. It addresses three common scenarios that can arise during localization: |
||||
|
|
||||
|
|
||||
|
1. When the argument count of a key changes, it can be difficult to update the translations for all languages. My tool solves this problem by scanning all JSON files in the project folder and identifying any keys that have mismatched argument counts. It then offers two options to the user: delete the mismatched translations or export them as a JSON file for manual editing. |
||||
|
|
||||
|
2. When a new key is added to the project, forgetting to add its translations to all the other languages is easy. My tool helps to avoid this issue by scanning the default language's JSON file and identifying any keys that don't have translations in other languages. It then exports these keys as a JSON file that can be used to add missing translations. |
||||
|
|
||||
|
3. When a key's name is changed, it's important to update its translations in all the other languages. My tool makes this task simple by scanning all the JSON files in the project folder and updating any translations of the old key name with the new one. |
||||
|
|
||||
|
The tool also includes an export feature that allows users to modify translations outside of the application and import them back into the JSON files. |
||||
|
|
||||
|
## How it Helps |
||||
|
|
||||
|
With my Localization Key Synchronizer tool, you can perform complex localization changes more quickly and easily than by manually sifting through files and making changes one-by-one. This can save you significant time and effort, especially if you're working with a large number of languages or translations. |
||||
|
|
||||
|
## How it Works |
||||
|
|
||||
|
When you run the Localization Key Synchronizer tool, it presents you with three options: |
||||
|
|
||||
|
1. Find Asynchronous Keys |
||||
|
2. Apply Changes in the Exported File |
||||
|
3. Replace Keys |
||||
|
|
||||
|
If you select "Find Asynchronous Keys," the tool prompts you to enter the default language path. Once you've entered the path, the tool displays all of the JSON files in the same folder as a multi-select list. After selecting one or more files, you are asked whether you want to find keys that do not match the number of arguments, missing keys, or both. If you select "Missing Keys," the tool prompts you to enter the absolute path to export the missing keys. After you've entered the path, the export process starts, and the tool closes. |
||||
|
|
||||
|
 |
||||
|
|
||||
|
If you select "Apply Changes in the Exported File" at the main menu, the tool prompts you to enter the path to the exported file. After you've entered the path, the import process starts, and the tool closes. |
||||
|
|
||||
|
 |
||||
|
|
||||
|
If you select "Replace Keys," the tool prompts you to enter the localization folder path, the old key, the new key, and the JSON files to apply the changes to. Once you've entered all the required information and made your selections, the tool performs the replacements and closes. |
||||
|
|
||||
|
 |
||||
|
|
||||
|
## Conclusion |
||||
|
|
||||
|
If you're struggling to manage localization changes in an ABP project, give my Localization Key Synchronizer tool a try. It can help streamline your workflow and make the process much more manageable. You can find the tool on [GitHub](https://github.com/abpframework/abp/tree/dev/tools/localization-key-synchronizer). |
||||
|
|
||||
|
To use the tool, simply run the console application and follow the prompts. It's a user-friendly solution that helps to ensure localization consistency in your ABP project. Give it a try and let me know what you think! |
||||
|
After Width: | Height: | Size: 3.1 MiB |
|
After Width: | Height: | Size: 3.0 MiB |
|
After Width: | Height: | Size: 2.7 MiB |
@ -0,0 +1,230 @@ |
|||||
|
# Migrating from OpenIddict to IdentityServer4 Step by Step Guide |
||||
|
|
||||
|
ABP startup templates use `OpenIddict` OpenID provider from v6.0.0 by default and `IdentityServer` projects are renamed to `AuthServer` in tiered/separated solutions. Since OpenIddict is the default OpenID provider library for ABP templates since v6.0, you may want to keep using [IdentityServer4](https://github.com/IdentityServer/IdentityServer4) library, even it is **archived and no longer maintained by the owners**. ABP doesn't provide support for newer versions of IdentityServer. This guide provides layer-by-layer guidance for migrating your existing [OpenIddict](https://github.com/openiddict/openiddict-core) application to IdentityServer4. |
||||
|
|
||||
|
## IdentityServer4 Migration Steps |
||||
|
|
||||
|
Use the `abp update` command to update your existing application. See [Upgrading docs](../Upgrading.md) for more info. Apply required migrations by following the [Migration Guides](Index.md) based on your application version. |
||||
|
|
||||
|
### Domain.Shared Layer |
||||
|
|
||||
|
- In **MyApplication.Domain.Shared.csproj** replace **project reference**: |
||||
|
|
||||
|
```csharp |
||||
|
<PackageReference Include="Volo.Abp.OpenIddict.Domain.Shared" Version="6.0.*" /> |
||||
|
``` |
||||
|
|
||||
|
with |
||||
|
|
||||
|
```csharp |
||||
|
<PackageReference Include="Volo.Abp.IdentityServer.Domain.Shared" Version="6.0.*" /> |
||||
|
``` |
||||
|
|
||||
|
- In **MyApplicationDomainSharedModule.cs** replace usings and **module dependencies:** |
||||
|
|
||||
|
```csharp |
||||
|
using Volo.Abp.OpenIddict; |
||||
|
... |
||||
|
typeof(AbpOpenIddictDomainSharedModule) |
||||
|
``` |
||||
|
|
||||
|
with |
||||
|
|
||||
|
```csharp |
||||
|
using Volo.Abp.IdentityServer; |
||||
|
... |
||||
|
typeof(AbpIdentityServerDomainSharedModule) |
||||
|
``` |
||||
|
|
||||
|
### Domain Layer |
||||
|
|
||||
|
- In **MyApplication.Domain.csproj** replace **project references**: |
||||
|
|
||||
|
```csharp |
||||
|
<PackageReference Include="Volo.Abp.OpenIddict.Domain" Version="6.0.*" /> |
||||
|
<PackageReference Include="Volo.Abp.PermissionManagement.Domain.OpenIddict" Version="6.0.*" /> |
||||
|
``` |
||||
|
|
||||
|
with |
||||
|
|
||||
|
```csharp |
||||
|
<PackageReference Include="Volo.Abp.IdentityServer.Domain" Version="6.0.*" /> |
||||
|
<PackageReference Include="Volo.Abp.PermissionManagement.Domain.IdentityServer" Version="6.0.*" /> |
||||
|
``` |
||||
|
|
||||
|
- In **MyApplicationDomainModule.cs** replace usings and **module dependencies**: |
||||
|
|
||||
|
```csharp |
||||
|
using Volo.Abp.OpenIddict; |
||||
|
using Volo.Abp.PermissionManagement.OpenIddict; |
||||
|
... |
||||
|
typeof(AbpOpenIddictDomainModule), |
||||
|
typeof(AbpPermissionManagementDomainOpenIddictModule), |
||||
|
``` |
||||
|
|
||||
|
with |
||||
|
|
||||
|
```csharp |
||||
|
using Volo.Abp.IdentityServer; |
||||
|
using Volo.Abp.PermissionManagement.IdentityServer; |
||||
|
... |
||||
|
typeof(AbpIdentityServerDomainModule), |
||||
|
typeof(AbpPermissionManagementDomainIdentityServerModule), |
||||
|
``` |
||||
|
|
||||
|
#### OpenIddictDataSeedContributor |
||||
|
|
||||
|
DataSeeder is the most important part for starting the application since it seeds the initial data for both OpenID providers. |
||||
|
|
||||
|
- Create a folder named *IdentityServer* under the Domain project and copy the [IdentityServerDataSeedContributor.cs](https://github.com/abpframework/abp-samples/blob/master/Ids2OpenId/src/Ids2OpenId.Domain/IdentityServer/IdentityServerDataSeedContributor.cs) under this folder. **Rename** all the `OpenId2Ids` with your project name. |
||||
|
- Delete *OpenIddict* folder that contains `OpenIddictDataSeedContributor.cs` which is no longer needed. |
||||
|
|
||||
|
### EntityFrameworkCore Layer |
||||
|
|
||||
|
If you are using MongoDB, skip this step and check the *MongoDB* layer section. |
||||
|
|
||||
|
- In **MyApplication.EntityFrameworkCore.csproj** replace **project reference**: |
||||
|
|
||||
|
```csharp |
||||
|
<PackageReference Include="Volo.Abp.OpenIddict.EntityFrameworkCore" Version="6.0.*" /> |
||||
|
``` |
||||
|
|
||||
|
with |
||||
|
|
||||
|
```csharp |
||||
|
<PackageReference Include="Volo.Abp.IdentityServer.EntityFrameworkCore" Version="6.0.*" /> |
||||
|
``` |
||||
|
|
||||
|
- In **MyApplicationEntityFrameworkCoreModule.cs** replace usings and **module dependencies**: |
||||
|
|
||||
|
```csharp |
||||
|
using Volo.Abp.OpenIddict.EntityFrameworkCore; |
||||
|
... |
||||
|
typeof(AbpOpenIddictEntityFrameworkCoreModule), |
||||
|
``` |
||||
|
|
||||
|
with |
||||
|
|
||||
|
```csharp |
||||
|
using Volo.Abp.IdentityServer.EntityFrameworkCore; |
||||
|
... |
||||
|
typeof(AbpIdentityServerEntityFrameworkCoreModule), |
||||
|
``` |
||||
|
|
||||
|
- In **MyApplicationDbContext.cs** replace usings and **fluent api configurations**: |
||||
|
|
||||
|
```csharp |
||||
|
using Volo.Abp.OpenIddict.EntityFrameworkCore; |
||||
|
... |
||||
|
protected override void OnModelCreating(ModelBuilder builder) |
||||
|
{ |
||||
|
base.OnModelCreating(builder); |
||||
|
|
||||
|
/* Include modules to your migration db context */ |
||||
|
|
||||
|
... |
||||
|
builder.ConfigureOpenIddict(); |
||||
|
``` |
||||
|
|
||||
|
with |
||||
|
|
||||
|
```csharp |
||||
|
using Volo.Abp.IdentityServer.EntityFrameworkCore; |
||||
|
... |
||||
|
using Volo.Abp.OpenIddict.EntityFrameworkCore; |
||||
|
... |
||||
|
protected override void OnModelCreating(ModelBuilder builder) |
||||
|
{ |
||||
|
base.OnModelCreating(builder); |
||||
|
|
||||
|
/* Include modules to your migration db context */ |
||||
|
|
||||
|
... |
||||
|
builder.ConfigureIdentityServer(); |
||||
|
``` |
||||
|
|
||||
|
> Not: You need to create new migration after updating the fluent api. Navigate to *EntityFrameworkCore* folder and add a new migration. Ex, `dotnet ef migrations add Updated_To_IdentityServer ` |
||||
|
|
||||
|
### MongoDB Layer |
||||
|
|
||||
|
If you are using EntityFrameworkCore, skip this step and check the *EntityFrameworkCore* layer section. |
||||
|
|
||||
|
- In **MyApplication.MongoDB.csproj** replace **project reference**: |
||||
|
|
||||
|
```csharp |
||||
|
<PackageReference Include="Volo.Abp.OpenIddict.MongoDB" Version="6.0.*" /> |
||||
|
``` |
||||
|
|
||||
|
with |
||||
|
|
||||
|
```csharp |
||||
|
<PackageReference Include="Volo.Abp.IdentityServer.MongoDB" Version="6.0.*" /> |
||||
|
``` |
||||
|
|
||||
|
- In **MyApplicationMongoDbModule.cs** replace usings and **module dependencies**: |
||||
|
|
||||
|
```csharp |
||||
|
using Volo.Abp.OpenIddict.MongoDB; |
||||
|
... |
||||
|
typeof(AbpOpenIddictMongoDbModule), |
||||
|
``` |
||||
|
|
||||
|
with |
||||
|
|
||||
|
```csharp |
||||
|
using Volo.Abp.IdentityServer.MongoDB; |
||||
|
... |
||||
|
typeof(AbpIdentityServerMongoDbModule), |
||||
|
``` |
||||
|
|
||||
|
### DbMigrator Project |
||||
|
|
||||
|
- In `appsettings.json` **replace OpenIddict section with IdentityServer** since IdentityServerDataSeeder will be using these information for initial data seeding: |
||||
|
|
||||
|
```json |
||||
|
"IdentityServer": { // Rename OpenIddict to IdentityServer |
||||
|
"Clients ": { // Rename Applications to Clients |
||||
|
... |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
|
||||
|
### Test Project |
||||
|
|
||||
|
- In **MyApplicationTestBaseModule.cs** **add** the IdentityServer related using and PreConfigurations: |
||||
|
|
||||
|
```csharp |
||||
|
using Volo.Abp.IdentityServer; |
||||
|
``` |
||||
|
|
||||
|
and |
||||
|
|
||||
|
```csharp |
||||
|
PreConfigure<AbpIdentityServerBuilderOptions>(options => |
||||
|
{ |
||||
|
options.AddDeveloperSigningCredential = false; |
||||
|
}); |
||||
|
|
||||
|
PreConfigure<IIdentityServerBuilder>(identityServerBuilder => |
||||
|
{ |
||||
|
identityServerBuilder.AddDeveloperSigningCredential(false, System.Guid.NewGuid().ToString()); |
||||
|
}); |
||||
|
``` |
||||
|
|
||||
|
to `PreConfigureServices` to run authentication related unit tests. |
||||
|
|
||||
|
### UI Layer |
||||
|
|
||||
|
You can follow the migrations guides from IdentityServer to OpenIddict in **reverse order** to update your UIs. You can also check the source-code for [Index.cshtml.cs](https://github.com/abpframework/abp-samples/blob/master/OpenId2Ids/src/OpenId2Ids.AuthServer/Pages/Index.cshtml) and [Index.cshtml](https://github.com/abpframework/abp-samples/blob/master/OpenId2Ids/src/OpenId2Ids.AuthServer/Pages/Index.cshtml.cs) files for **AuthServer** project. |
||||
|
|
||||
|
- [Angular UI Migration](OpenIddict-Angular.md) |
||||
|
- [MVC/Razor UI Migration](OpenIddict-Mvc.md) |
||||
|
- [Blazor-Server UI Migration](OpenIddict-Blazor-Server.md) |
||||
|
- [Blazor-Wasm UI Migration](OpenIddict-Blazor.md) |
||||
|
|
||||
|
## Source code of samples and module |
||||
|
|
||||
|
* [Open source tiered & separate auth server application migrate OpenIddict to Identity Server](https://github.com/abpframework/abp-samples/tree/master/OpenId2Ids) |
||||
|
* [IdentityServer module document](https://docs.abp.io/en/abp/6.0/Modules/IdentityServer) |
||||
|
* [IdentityServer module source code](https://github.com/abpframework/abp/tree/rel-6.0/modules/identityserver) |
||||
@ -0,0 +1,16 @@ |
|||||
|
using NuGet.Versioning; |
||||
|
|
||||
|
namespace Volo.Abp.Cli.Version; |
||||
|
|
||||
|
public class LatestVersionInfo |
||||
|
{ |
||||
|
public SemanticVersion Version { get; } |
||||
|
|
||||
|
public string Message { get; } |
||||
|
|
||||
|
public LatestVersionInfo(SemanticVersion version, string message = null) |
||||
|
{ |
||||
|
Version = version; |
||||
|
Message = message; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Volo.Abp.Http.Client.StaticProxying; |
||||
|
|
||||
|
public class AbpHttpClientStaticProxyingOptions |
||||
|
{ |
||||
|
public List<Type> BindingFromQueryTypes { get; } |
||||
|
|
||||
|
public AbpHttpClientStaticProxyingOptions() |
||||
|
{ |
||||
|
BindingFromQueryTypes = new List<Type>(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.Net; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Shouldly; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.MultiTenancy; |
||||
|
|
||||
|
public class AspNetCoreMultiTenancy_MultiTenancyMiddlewareErrorPageBuilder_Tests : AspNetCoreMultiTenancyTestBase |
||||
|
{ |
||||
|
private readonly AbpAspNetCoreMultiTenancyOptions _options; |
||||
|
|
||||
|
public AspNetCoreMultiTenancy_MultiTenancyMiddlewareErrorPageBuilder_Tests() |
||||
|
{ |
||||
|
_options = ServiceProvider.GetRequiredService<IOptions<AbpAspNetCoreMultiTenancyOptions>>().Value; |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task MultiTenancyMiddlewareErrorPageBuilder() |
||||
|
{ |
||||
|
var result = await GetResponseAsStringAsync($"http://abp.io?{_options.TenantKey}=<script>alert(hi)</script>", HttpStatusCode.NotFound); |
||||
|
result.ShouldNotContain("<script>alert(hi)</script>"); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
[ |
||||
|
{ |
||||
|
"version": "7.0.2", |
||||
|
"releaseDate": "", |
||||
|
"type": "stable", |
||||
|
"message": "" |
||||
|
} |
||||
|
] |
||||
@ -1,23 +1,40 @@ |
|||||
using System; |
using System; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Hangfire; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.BackgroundJobs.DemoApp.Shared.Jobs; |
||||
|
using Volo.Abp.Threading; |
||||
|
|
||||
namespace Volo.Abp.BackgroundJobs.DemoApp.HangFire; |
namespace Volo.Abp.BackgroundJobs.DemoApp.HangFire; |
||||
|
|
||||
class Program |
class Program |
||||
{ |
{ |
||||
static void Main(string[] args) |
async static Task Main(string[] args) |
||||
{ |
{ |
||||
using (var application = AbpApplicationFactory.Create<DemoAppHangfireModule>(options => |
using (var application = await AbpApplicationFactory.CreateAsync<DemoAppHangfireModule>(options => |
||||
|
{ |
||||
|
options.UseAutofac(); |
||||
|
})) |
||||
{ |
{ |
||||
options.UseAutofac(); |
await application.InitializeAsync(); |
||||
})) |
|
||||
{ |
await CancelableBackgroundJobAsync(application.ServiceProvider); |
||||
application.Initialize(); |
|
||||
|
|
||||
Console.WriteLine("Started: " + typeof(Program).Namespace); |
Console.WriteLine("Started: " + typeof(Program).Namespace); |
||||
Console.WriteLine("Press ENTER to stop the application..!"); |
Console.WriteLine("Press ENTER to stop the application..!"); |
||||
Console.ReadLine(); |
Console.ReadLine(); |
||||
|
|
||||
application.Shutdown(); |
await application.ShutdownAsync(); |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
|
private async static Task CancelableBackgroundJobAsync(IServiceProvider serviceProvider) |
||||
|
{ |
||||
|
var backgroundJobManager = serviceProvider.GetRequiredService<IBackgroundJobManager>(); |
||||
|
var jobId = await backgroundJobManager.EnqueueAsync(new LongRunningJobArgs { Value = "test-1" }); |
||||
|
await backgroundJobManager.EnqueueAsync(new LongRunningJobArgs { Value = "test-2" }); |
||||
|
Thread.Sleep(1000); |
||||
|
BackgroundJob.Delete(jobId); |
||||
|
} |
||||
} |
} |
||||
|
|||||
@ -1,23 +1,41 @@ |
|||||
using System; |
using System; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Quartz; |
||||
|
using Volo.Abp.BackgroundJobs.DemoApp.Shared.Jobs; |
||||
|
using Volo.Abp.Threading; |
||||
|
|
||||
namespace Volo.Abp.BackgroundJobs.DemoApp.Quartz; |
namespace Volo.Abp.BackgroundJobs.DemoApp.Quartz; |
||||
|
|
||||
class Program |
class Program |
||||
{ |
{ |
||||
static void Main(string[] args) |
async static Task Main(string[] args) |
||||
{ |
{ |
||||
using (var application = AbpApplicationFactory.Create<DemoAppQuartzModule>(options => |
using (var application = await AbpApplicationFactory.CreateAsync<DemoAppQuartzModule>(options => |
||||
{ |
{ |
||||
options.UseAutofac(); |
options.UseAutofac(); |
||||
})) |
})) |
||||
{ |
{ |
||||
application.Initialize(); |
await application.InitializeAsync(); |
||||
|
|
||||
|
await CancelableBackgroundJobAsync(application.ServiceProvider); |
||||
|
|
||||
Console.WriteLine("Started: " + typeof(Program).Namespace); |
Console.WriteLine("Started: " + typeof(Program).Namespace); |
||||
Console.WriteLine("Press ENTER to stop the application..!"); |
Console.WriteLine("Press ENTER to stop the application..!"); |
||||
Console.ReadLine(); |
Console.ReadLine(); |
||||
|
|
||||
application.Shutdown(); |
await application.ShutdownAsync(); |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
|
private async static Task CancelableBackgroundJobAsync(IServiceProvider serviceProvider) |
||||
|
{ |
||||
|
var backgroundJobManager = serviceProvider.GetRequiredService<IBackgroundJobManager>(); |
||||
|
var jobId = await backgroundJobManager.EnqueueAsync(new LongRunningJobArgs {Value = "test-1"}); |
||||
|
await backgroundJobManager.EnqueueAsync(new LongRunningJobArgs { Value = "test-2" }); |
||||
|
Thread.Sleep(1000); |
||||
|
var scheduler = serviceProvider.GetRequiredService<IScheduler>(); |
||||
|
await scheduler.Interrupt(new JobKey(jobId.Split('.')[1],jobId.Split('.')[0])); |
||||
|
} |
||||
} |
} |
||||
|
|||||
@ -1,23 +1,24 @@ |
|||||
using System; |
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
namespace Volo.Abp.BackgroundJobs.DemoApp.RabbitMq; |
namespace Volo.Abp.BackgroundJobs.DemoApp.RabbitMq; |
||||
|
|
||||
class Program |
class Program |
||||
{ |
{ |
||||
static void Main(string[] args) |
async static Task Main(string[] args) |
||||
{ |
{ |
||||
using (var application = AbpApplicationFactory.Create<DemoAppRabbitMqModule>(options => |
using (var application = await AbpApplicationFactory.CreateAsync<DemoAppRabbitMqModule>(options => |
||||
{ |
{ |
||||
options.UseAutofac(); |
options.UseAutofac(); |
||||
})) |
})) |
||||
{ |
{ |
||||
application.Initialize(); |
await application.InitializeAsync(); |
||||
|
|
||||
Console.WriteLine("Started: " + typeof(Program).Namespace); |
Console.WriteLine("Started: " + typeof(Program).Namespace); |
||||
Console.WriteLine("Press ENTER to stop the application..!"); |
Console.WriteLine("Press ENTER to stop the application..!"); |
||||
Console.ReadLine(); |
Console.ReadLine(); |
||||
|
|
||||
application.Shutdown(); |
await application.ShutdownAsync(); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,49 @@ |
|||||
|
using System; |
||||
|
using System.Threading; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Threading; |
||||
|
|
||||
|
namespace Volo.Abp.BackgroundJobs.DemoApp.Shared.Jobs |
||||
|
{ |
||||
|
public class LongRunningJob : BackgroundJob<LongRunningJobArgs>, ITransientDependency |
||||
|
{ |
||||
|
private readonly ICancellationTokenProvider _cancellationTokenProvider; |
||||
|
|
||||
|
public LongRunningJob(ICancellationTokenProvider cancellationTokenProvider) |
||||
|
{ |
||||
|
_cancellationTokenProvider = cancellationTokenProvider; |
||||
|
} |
||||
|
|
||||
|
public override void Execute(LongRunningJobArgs args) |
||||
|
{ |
||||
|
lock (Console.Out) |
||||
|
{ |
||||
|
var oldColor = Console.ForegroundColor; |
||||
|
try |
||||
|
{ |
||||
|
Console.WriteLine($"Long running {args.Value} start: {DateTime.Now}"); |
||||
|
|
||||
|
for (var i = 1; i <= 10; i++) |
||||
|
{ |
||||
|
_cancellationTokenProvider.Token.ThrowIfCancellationRequested(); |
||||
|
|
||||
|
Thread.Sleep(1000); |
||||
|
Console.WriteLine($"{args.Value} step-{i} done: {DateTime.Now}"); |
||||
|
} |
||||
|
|
||||
|
Console.ForegroundColor = ConsoleColor.Green; |
||||
|
Console.WriteLine($"Long running {args.Value} completed: {DateTime.Now}"); |
||||
|
} |
||||
|
catch (OperationCanceledException) |
||||
|
{ |
||||
|
Console.ForegroundColor = ConsoleColor.Red; |
||||
|
Console.WriteLine($"Long running {args.Value} cancelled!!!"); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
Console.ForegroundColor = oldColor; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
namespace Volo.Abp.BackgroundJobs.DemoApp.Shared.Jobs |
||||
|
{ |
||||
|
[BackgroundJobName("LongJob")] |
||||
|
public class LongRunningJobArgs |
||||
|
{ |
||||
|
public string Value { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -1,23 +1,23 @@ |
|||||
using System; |
using System; |
||||
|
using System.Threading.Tasks; |
||||
namespace Volo.Abp.BackgroundJobs.DemoApp; |
namespace Volo.Abp.BackgroundJobs.DemoApp; |
||||
|
|
||||
class Program |
class Program |
||||
{ |
{ |
||||
static void Main(string[] args) |
async static Task Main(string[] args) |
||||
{ |
{ |
||||
using (var application = AbpApplicationFactory.Create<DemoAppModule>(options => |
using (var application = await AbpApplicationFactory.CreateAsync<DemoAppModule>(options => |
||||
{ |
{ |
||||
options.UseAutofac(); |
options.UseAutofac(); |
||||
})) |
})) |
||||
{ |
{ |
||||
application.Initialize(); |
await application.InitializeAsync(); |
||||
|
|
||||
Console.WriteLine("Started: " + typeof(Program).Namespace); |
Console.WriteLine("Started: " + typeof(Program).Namespace); |
||||
Console.WriteLine("Press ENTER to stop the application..!"); |
Console.WriteLine("Press ENTER to stop the application..!"); |
||||
Console.ReadLine(); |
Console.ReadLine(); |
||||
|
|
||||
application.Shutdown(); |
await application.ShutdownAsync(); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
File diff suppressed because it is too large
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -0,0 +1,8 @@ |
|||||
|
namespace Volo.Blogging.Admin; |
||||
|
|
||||
|
public class BloggingAdminMenuNames |
||||
|
{ |
||||
|
public const string GroupName = "BlogManagement"; |
||||
|
|
||||
|
public const string Blogs = GroupName + ".Blogs"; |
||||
|
} |
||||
File diff suppressed because it is too large
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue