Browse Source

Merge branch 'abpframework:dev' into pass-option-to-servicebusadminclient

pull/11991/head
GerardoGrecoPorini 4 years ago
committed by GitHub
parent
commit
fcfcee7e1e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      README.md
  2. 12
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json
  3. 17
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json
  4. 2
      common.props
  5. 10
      docs/en/Background-Workers.md
  6. 2
      docs/en/Blog-Posts/2021-04-05 CmsKit/POST.md
  7. 11
      docs/en/Blog-Posts/2022-03-08 v5_2_Preview/POST.md
  8. 2
      docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/POST.md
  9. 2
      docs/en/Community-Articles/2022-02-06-How-to-Hide-ABP-Related-Endpoints-on-Swagger-UI/POST.md
  10. 104
      docs/en/Distributed-Locking.md
  11. 4
      docs/en/Features.md
  12. 51
      docs/en/Migration-Guides/Abp-5_2.md
  13. 1
      docs/en/Migration-Guides/Index.md
  14. 71
      docs/en/UI/AspNetCore/AutoComplete-Select.md
  15. 8
      docs/en/docs-nav.json
  16. BIN
      docs/en/images/abp-select2-multiple.png
  17. BIN
      docs/en/images/abp-select2-single.png
  18. 259
      docs/zh-Hans/Caching.md
  19. 8
      docs/zh-Hans/Distributed-Event-Bus-Kafka-Integration.md
  20. 8
      docs/zh-Hans/Distributed-Event-Bus-RabbitMQ-Integration.md
  21. 4
      docs/zh-Hans/Distributed-Event-Bus-Rebus-Integration.md
  22. 2
      docs/zh-Hans/Distributed-Event-Bus.md
  23. 56
      docs/zh-Hans/Modules/Background-Jobs.md
  24. 256
      docs/zh-Hans/Specifications.md
  25. 8
      framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj
  26. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ConnectionStringChangeStep.cs
  27. 2
      framework/src/Volo.Abp.EventBus.Azure/Volo/Abp/EventBus/Azure/AbpAzureEventBusOptions.cs
  28. 15
      framework/src/Volo.Abp.EventBus.Azure/Volo/Abp/EventBus/Azure/AbpEventBusAzureModule.cs
  29. 14
      framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingEncryptionService.cs
  30. 13
      modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs
  31. 1
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/abp.resourcemapping.js
  32. 8
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/GlobalResources/Index.cshtml
  33. 19
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/GlobalResources/index.js
  34. 9
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Create.cshtml
  35. 5
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Update.cshtml
  36. 22
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/create.js
  37. 18
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/update.js
  38. 3
      npm/packs/cms-kit.admin/package.json
  39. 5
      npm/packs/codemirror/abp.resourcemapping.js
  40. 3
      npm/packs/jquery-form/abp.resourcemapping.js
  41. 22
      npm/packs/jquery-form/src/jquery.form.min.js
  42. 4
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server.Mongo/MyCompanyName.MyProjectName.Blazor.Server.Mongo.csproj
  43. 4
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj
  44. 13
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/_Imports.razor
  45. 4
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyCompanyName.MyProjectName.Blazor.Server.Tiered.csproj
  46. 4
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj
  47. 4
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj
  48. 4
      templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj
  49. 4
      templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyCompanyName.MyProjectName.Blazor.Server.Host.csproj

4
README.md

@ -108,6 +108,10 @@ ABP is a community-driven open source project. See [the contribution guide](http
Love ABP Framework? **Please give a star** to this repository :star:
## Discord Channel
You can use this link to join the ABP Community Discord Server: https://discord.gg/uVGt6hyhcm
## ABP Commercial
See also [ABP Commercial](https://commercial.abp.io/) if you are looking for pre-built application modules, professional themes, code generation tooling and premium support for the ABP Framework.

12
abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json

@ -337,18 +337,6 @@
"Expired": "Expired",
"TrialLicenseDeletionWarningMessage": "Are you sure you want to delete the trial license? Trial license, organization, support accounts will be deleted!",
"LicenseCategoryFilter": "License category",
"Volo.AbpIo.Commercial:030000": "You already used your trial period.",
"Volo.AbpIo.Commercial:030001": "This organization name already exists.",
"Volo.AbpIo.Commercial:030002": "Once activated, trial license cannot be set to requested!",
"Volo.AbpIo.Commercial:030003": "There is no such status!",
"Volo.AbpIo.Commercial:030004": "Status could not be changed due to an unexpected error!",
"Volo.AbpIo.Commercial:030005": "Start and end date can be updated when the trial license is in the -activated- status!",
"Volo.AbpIo.Commercial:030006": "End date must always be greater than start date!",
"Volo.AbpIo.Commercial:030007": "This trial license has already been activated once!",
"Volo.AbpIo.Commercial:030008": "Purchase date can be set only when status is Purchased!",
"Volo.AbpIo.Commercial:030009": "User not found!",
"Volo.AbpIo.Commercial:030010": "To purchase the trial license, first you need to activate your trial license!",
"Volo.AbpIo.Commercial:030011": "You cannot delete a trial license when it is purchased!",
"Permission:SendWelcomeEmail": "Send Welcome Email",
"SendWelcomeEmail": "Send Welcome Email",
"SendWelcomeEmailWarningMessage": "Are you sure you want to send welcome email to the organization members?",

17
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json

@ -14,6 +14,18 @@
"Volo.AbpIo.Domain:020002": "Could not delete this NPM Package because \"{Modules}\" Modules are using this package.",
"Volo.AbpIo.Domain:020003": "Could not delete this NPM Package because \"{Modules}\" Modules are using this package and \"{NugetPackages}\" Nuget Packages are dependent to this package.",
"Volo.AbpIo.Domain:020004": "Could not delete this Nuget Package because \"{Modules}\" Modules are using this package.",
"Volo.AbpIo.Domain:030000": "You have already completed your trial period.",
"Volo.AbpIo.Domain:030001": "This organization name already exists.",
"Volo.AbpIo.Domain:030002": "Once activated, you cannot switch the trial license to -requested- status!",
"Volo.AbpIo.Domain:030003": "There is no such status!",
"Volo.AbpIo.Domain:030004": "Status could not be changed due to an unexpected error!",
"Volo.AbpIo.Domain:030005": "Start and end date can be updated when the trial license is in the -activated- status!",
"Volo.AbpIo.Domain:030006": "The end date must be greater than the start date!",
"Volo.AbpIo.Domain:030007": "This trial license has already been activated!",
"Volo.AbpIo.Domain:030008": "The purchase date can be set only when the status is -purchased-!",
"Volo.AbpIo.Domain:030009": "User not found!",
"Volo.AbpIo.Domain:030010": "To purchase the trial license, you first need to activate your trial license!",
"Volo.AbpIo.Domain:030011": "You cannot delete a trial license when it is purchased!",
"WantToLearn?": "Want to learn?",
"ReadyToGetStarted?": "Ready to get started?",
"JoinOurCommunity": "Join our community",
@ -72,7 +84,7 @@
"WouldLikeToReceiveMarketingMaterials": "I would like to receive marketing materials like product deals & special offers.",
"JoinOurMarketingNewsletter": "Join our marketing newsletter",
"CommunityPrivacyPolicyConfirmation": "I agree to the Terms & Conditions and <a class=\"text-white fw-6 text-decoration-underline opacity-50\" href=\"https://commercial.abp.io/Privacy\">Privacy Policy</a>.",
"ABPIO-Common": "ABPIO-Common",
"WouldLikeToReceiveNotification": "I would like to receive the latest news from abp.io websites.",
"CommercialNewsletterConfirmationMessage": "I agree to the <a class=\"text-white fw-6 text-decoration-underline opacity-50\" href=\"https://commercial.abp.io/TermsConditions\">Terms & Conditions</a> and <a class=\"text-white fw-6 text-decoration-underline opacity-50\" href=\"https://commercial.abp.io/Privacy\">Privacy Policy</a>.",
"FreeDDDEBook": "Free DDD E-Book",
"AdditionalServices": "Additional Services",
@ -106,6 +118,7 @@
"ThereIsNoEvent": "There is no event.",
"Events": "Events",
"Volo.AbpIo.Domain:080000": "There is already a purchase item named \"{Name}\"",
"MasteringAbpFrameworkBook": "Book: Mastering ABP Framework"
"MasteringAbpFrameworkBook": "Book: Mastering ABP Framework",
"ABPIO-CommonPreferenceDefinition": "Get latest news about ABP Platform like new posts, events and more."
}
}

2
common.props

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

10
docs/en/Background-Workers.md

@ -86,20 +86,20 @@ After creating a background worker class, you should add it to the `IBackgroundW
[DependsOn(typeof(AbpBackgroundWorkersModule))]
public class MyModule : AbpModule
{
public override void OnApplicationInitialization(
public override Task OnApplicationInitializationAsync(
ApplicationInitializationContext context)
{
context.AddBackgroundWorker<PassiveUserCheckerWorker>();
context.AddBackgroundWorkerAsync<PassiveUserCheckerWorker>();
}
}
````
`context.AddBackgroundWorker(...)` is a shortcut extension method for the expression below:
`context.AddBackgroundWorkerAsync(...)` is a shortcut extension method for the expression below:
````csharp
context.ServiceProvider
await context.ServiceProvider
.GetRequiredService<IBackgroundWorkerManager>()
.Add(
.AddAsync(
context
.ServiceProvider
.GetRequiredService<PassiveUserCheckerWorker>()

2
docs/en/Blog-Posts/2021-04-05 CmsKit/POST.md

@ -79,7 +79,7 @@ For example,
We've covered the initial features, installation and configuration steps in this post. You can read the [open-source](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit) and [commercial](https://docs.abp.io/en/commercial/latest/modules/CMS-Kit) documentation to get further information about features and the CMS Kit module. CMS Kit's initial version contains lots of features that you can easily integrate and use in your applications. We're planning to improve the existing features, fixing bugs and adding new features in upcoming releases. If you want to give some feedback or have a feature request, please reach out to us from [GitHub](https://github.com/abpframework/abp) or [support.abp.io](https://support.abp.io). We will be happy to plan the CMS Kit module's future together.
We've covered the initial features, installation and configuration steps in this post. You can read the [open-source](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Index) and [commercial](https://docs.abp.io/en/commercial/latest/modules/CMS-Kit) documentation to get further information about features and the CMS Kit module. CMS Kit's initial version contains lots of features that you can easily integrate and use in your applications. We're planning to improve the existing features, fixing bugs and adding new features in upcoming releases. If you want to give some feedback or have a feature request, please reach out to us from [GitHub](https://github.com/abpframework/abp) or [support.abp.io](https://support.abp.io). We will be happy to plan the CMS Kit module's future together.
Thank you!

11
docs/en/Blog-Posts/2022-03-08 v5_2_Preview/POST.md

@ -34,6 +34,13 @@ See the [ABP CLI documentation](https://docs.abp.io/en/abp/latest/CLI) for all t
You can use any IDE that supports .NET 6.x, like **[Visual Studio 2022](https://visualstudio.microsoft.com/downloads/)**.
## Migration Guides
Please see the migration guides if you are upgrading from 5.x versions:
* [ABP Framework 5.x to 5.2 migration guide](https://docs.abp.io/en/abp/5.2/Migration-Guides/Abp-5_2)
* [ABP Commercial 5.x to 5.2 migration guide](https://docs.abp.io/en/commercial/5.2/migration-guides/index)
## What's New with ABP Framework 5.2?
In this section, I will introduce some major features released with this version. Here, a brief list of titles explained in the next sections:
@ -45,7 +52,7 @@ In this section, I will introduce some major features released with this version
* Custom Global CSS and JavaScript for the CMS Kit module
* Other news
Let's begin with the first section:
Let's begin with the first section.
### Single-layer Solution Template
@ -171,7 +178,7 @@ With this new feature, you can automatically generate advanced user interfaces w
## Community News
We organized the 3rd live [ABP Community Talks](https://community.abp.io/talks) event on February 23rd. ABP community has a good interest in these events and we will continue to organize such a live event in every month. March's event will be announced in a few days. [Follow us on twitter](https://twitter.com/abpframework).
We organized the 3rd live [ABP Community Talks](https://community.abp.io/events) event on February 23rd. ABP community has a good interest in these events and we will continue to organize such a live event in every month. March's event will be announced in a few days. [Follow us on twitter](https://twitter.com/abpframework).
[ABP Community](https://community.abp.io/) website is being a huge resource of articles and video tutorials on the ABP Framework and .NET. There have been 93 articles/tutorials submitted so far. Here's a list of a few contents posted in the last weeks:

2
docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/POST.md

@ -178,7 +178,7 @@ module.exports = {
};
```
> ABP copies related packages from **node_modules** folder to the **libs** folder by examining this file. You can read this [document](docs.abp.io/en/abp/latest/UI/AspNetCore/Client-Side-Package-Management#mapping-the-library-resources) for more info.
> ABP copies related packages from **node_modules** folder to the **libs** folder by examining this file. You can read this [document](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Client-Side-Package-Management#mapping-the-library-resources) for more info.
* Then run the `abp install-libs` to install the dependencies and copy them into the libs folder by your mappings configuration. After running this command, in your **libs** folder it should be a folder named **syncfusion** folder.

2
docs/en/Community-Articles/2022-02-06-How-to-Hide-ABP-Related-Endpoints-on-Swagger-UI/POST.md

@ -108,7 +108,7 @@ public class SwaggerSettingConsts
We've created a class with a constant variable to avoid using the magic strings. This variable will be our setting name.
ABP provides us a [Settings System](https://docs.abp.io/en/abp/latest/Setting) to easily define settings for our applications. We only need to create a class that derives from the `SettingDefinitionProvider` class, but we don't even need to do this because the ABP startup templates come with a pre-defined setting provider class.
ABP provides us a [Settings System](https://docs.abp.io/en/abp/latest/Settings) to easily define settings for our applications. We only need to create a class that derives from the `SettingDefinitionProvider` class, but we don't even need to do this because the ABP startup templates come with a pre-defined setting provider class.
* So open the setting definition provider class (`SwaggerSettingsDemoSettingDefinitionProvider` in our case, it's under the /Settings folder of your domain layer) and update the class:

104
docs/en/Distributed-Locking.md

@ -0,0 +1,104 @@
# Distributed Locking
Distributed locking is a technique to manage many applications that try to access the same resource.
The main purpose is to allow only one of many applications to access the same resource at the same time.
Otherwise, accessing the same object from various applications may corrupt the value of resources.
> ABP's current distributed locking implementation is based on the [DistributedLock](https://github.com/madelson/DistributedLock) library.
## Installation
You can open a command-line terminal and type the following command to install the [Volo.Abp.DistributedLocking](https://www.nuget.org/packages/Volo.Abp.DistributedLocking) package into your project:
````bash
abp add-package Volo.Abp.DistributedLocking
````
This package provides the necessary API to use the distributed locking system, however, you should configure a provider before using it.
### Configuring a provider
The [DistributedLock](https://github.com/madelson/DistributedLock) library provides [various of implementations](https://github.com/madelson/DistributedLock#implementations) for the locking, like [Redis](https://github.com/madelson/DistributedLock/blob/master/docs/DistributedLock.Redis.md) and [ZooKeeper](https://github.com/madelson/DistributedLock/blob/master/docs/DistributedLock.ZooKeeper.md).
For example, if you want to use the [Redis provider](https://github.com/madelson/DistributedLock/blob/master/docs/DistributedLock.Redis.md), you should add [DistributedLock.Redis](https://www.nuget.org/packages/DistributedLock.Redis) NuGet package to your project, then add the following code into the `ConfigureServices` method of your ABP [module](Module-Development-Basics.md) class:
````csharp
using Medallion.Threading;
using Medallion.Threading.Redis;
namespace AbpDemo
{
public class MyModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
context.Services.AddSingleton<IDistributedLockProvider>(sp =>
{
var connection = ConnectionMultiplexer
.Connect(configuration["Redis:Configuration"]);
return new
RedisDistributedSynchronizationProvider(connection.GetDatabase());
});
}
}
}
````
This code gets the Redis connection string from the [configuration](Configuration.md), so you can add the following lines to your `appsettings.json` file:
````json
"Redis": {
"Configuration": "127.0.0.1"
}
````
## Usage
There are two ways to use the distributed locking API: ABP's `IAbpDistributedLock` abstraction and [DistributedLock](https://github.com/madelson/DistributedLock) library's API.
### Using the IAbpDistributedLock service
`IAbpDistributedLock` is a simple service provided by the ABP framework for simple usage of distributed locking.
**Example: Using the `IAbpDistributedLock.TryAcquireAsync` method**
````csharp
using Volo.Abp.DistributedLocking;
namespace AbpDemo
{
public class MyService : ITransientDependency
{
private readonly IAbpDistributedLock _distributedLock;
public MyService(IAbpDistributedLock distributedLock)
{
_distributedLock = distributedLock;
}
public async Task MyMethodAsync()
{
await using (var handle =
await _distributedLock.TryAcquireAsync("MyLockName"))
{
if (handle != null)
{
// your code that access the shared resource
}
}
}
}
}
````
`TryAcquireAsync` may not acquire the lock. It returns `null` if the lock could not be acquired. In this case, you shouldn't access the resource. If the handle is not `null`, it means that you've obtained the lock and can safely access the resource.
`TryAcquireAsync` method gets the following parameters:
* `name` (`string`, required): Unique name of your lock. Different named locks are used to access different resources.
* `timeout` (`TimeSpan`): A timeout value to wait to obtain the lock. Default value is `TimeSpan.Zero`, which means it doesn't wait if the lock is already owned by another application.
* `cancellationToken`: A cancellation token that can be triggered later to cancel the operation.
### Using DistributedLock library's API
ABP's `IAbpDistributedLock` service is very limited and mainly designed to be internally used by the ABP Framework. For your own applications, you can use the DistributedLock library's own API. See its [own documentation](https://github.com/madelson/DistributedLock) for details.

4
docs/en/Features.md

@ -308,7 +308,7 @@ The example above defines a *Reporting* feature with two children: *PDF Reportin
### Changing Features Definitions of a Depended Module
A class deriving from the `FeatureDefinitionProvider` (just like the example above) can also get the existing permission definitions (defined by the depended [modules](Module-Development-Basics.md)) and change their definitions.
A class deriving from the `FeatureDefinitionProvider` (just like the example above) can also get the existing feature definitions (defined by the depended [modules](Module-Development-Basics.md)) and change their definitions.
**Example: Manipulate an existing feature definition**
@ -437,4 +437,4 @@ Use this code inside the `ConfigureServices` of your [module](Module-Development
### Feature Store
`IFeatureStore` is the only interface that needs to be implemented to read the value of features from a persistence source, generally a database system. The Feature Management module implements it and pre-installed in the application startup template. See the [feature management module documentation](https://docs.abp.io/en/abp/latest/Modules/Feature-Management) for more information
`IFeatureStore` is the only interface that needs to be implemented to read the value of features from a persistence source, generally a database system. The Feature Management module implements it and pre-installed in the application startup template. See the [feature management module documentation](https://docs.abp.io/en/abp/latest/Modules/Feature-Management) for more information

51
docs/en/Migration-Guides/Abp-5_2.md

@ -1,3 +1,52 @@
# ABP Version 5.2 Migration Guide
TODO
This document is a guide for upgrading ABP v5.x solutions to ABP v5.2. Please read them all since v5.2 has some changes you should take care.
## MongoDB
- `IMongoDbRepositoryFilterer.AddGlobalFilters()` method is replaced with async one `IMongoDbRepositoryFilterer.AddGlobalFiltersAsync()`
## Blazor UI
If you use Blazor WASM or Blazor Server UI, you should follow this section.
### Blazorise 1.0
We've upgraded to Blazorise 1.0 stable version. So there is some breaking changes that you have to apply in your project.
Also You can review that pull request [#11649 - Blazorise 1.0 Migration](https://github.com/abpframework/abp/pull/11649)
- `NumericEdit` is now made around the native `input type="number"` so a lot of its formating features are moved to the new `NumericPicker` component. Replace NumericEdit with NumericPicker.
- Rename `DecimalsSeparator` to `DecimalSeparator` on the `DataGridColumn` and `NumericPicker`.
- Rename `MaxMessageSize` to `MaxChunkSize`.
- Remove `Fullscreen` parameter on `<ModalContent>` and replace it with `Size="ModalSize.Fullscreen"` parameter.
- Remove `NotificationType`, `Message`, and `Title` parameter from `<NotificationAlert>` component.
- Move `RightAligned` parameter from `<BarDropdownMenu>` to `<BarDropdown>` component.
- Rename any usage of the `ChangeTextOnKeyPress` parameter into `Immediate`.
- Rename any usage of `DelayTextOnKeyPress` parameter into `Debounce` and `DelayTextOnKeyPressInterval` into DebounceInterval.
- Replace all `Left` and `Right` enums with `Start` and `End` for the following enum types: `Direction`, `Float`, `Placement`, `NotificationLocation`, `Side`, `SnackbarLocation`, `SnackbarStackLocation`, `TabPosition`, and `TextAlignment`.
- Replace all `FromLeft`, `FromRight`, `RoundedLeft`, and `RoundedRight` enums with `FromStart`, `FromEnd`, `RoundedStart`, and `RoundedEnd` for the `Border` utilities.
- Replace all `FromLeft` and `FromRight` with `FromStart`, `FromEnd` for the Margin and `Padding` utilities.
- Replace all `AddLabel` with `AddLabels` method on chart instance.
- Change enum value from `None` to `Default` for the following enum types: `Color`, `Background`, `TextColor`, `Alignment`, `BorderRadius`, `BorderSize`, `Direction`, `DisplayDirection`, `FigureSize`, `IconSize`, `JustifyContent`, `OverflowType`, `SnackbarColor`, `Target`, `TextAlignment`, `TextOverflow`, `TextTransform`, `TextWeight`, `VerticalAlignment`, `Visibility`, `Size`, and `SnackbarLocation`.
- Obsolete typography parameters `Alignment`, `Color`, `Transform`, and `Weight` are removed in favor of `TextAlignment`, `TextColor`, `TextTransform`, and `TextWeight`.
- Remove any use of an obsolete component `<InlineField>`.
- The Datagrid's obsolete `Direction` parameter has now been removed. Instead, please use the `SortDirection` parameter if you weren't already..
- Rename `<Tabs>` `Mode` parameter into `RenderMode`.
> _Check out [Blazorise Release Notes](https://preview.blazorise.com/news/release-notes/100) for more information._
## MVC - Razor Pages UI
If you use MVC Razor Pages UI, you should follow this section.
### Client libraries
The `libs` folder no longer exists in templates after v5.2. That change greatly reduced the size of templates and brought some other advantages.
You can use `abp install-libs` command for installing or updating client libraries. You should run this command after updating v5.2.
> If you're creating a new project, you don't have to be concerned about it, ABP CLI installs client libraries after automatically.
## See Also
* [Official blog post for the 5.2 release](https://blog.abp.io/abp/ABP.IO-Platform-5-2-RC-Has-Been-Published)

1
docs/en/Migration-Guides/Index.md

@ -1,5 +1,6 @@
# ABP Framework Migration Guides
- [5.1 to 5.2](Abp-5_2.md)
- [4.x to 5.0](Abp-5_0.md)
- [4.2 to 4.3](Abp-4_3.md)
- [4.x to 4.2](Abp-4_2.md)

71
docs/en/UI/AspNetCore/AutoComplete-Select.md

@ -0,0 +1,71 @@
# ASP.NET Core MVC / Razor Pages: Auto-Complete Select
A simple select component sometimes isn't useful with a huge amount of data. ABP Provides a select implementation that works with pagination and server-side search via using [Select2](https://select2.org/). It works with single or multiple choices well.
A screenshot can be shown below.
| Single | Multiple |
| --- | --- |
| ![autocomplete-select-example](../../images/abp-select2-single.png) |![autocomplete-select-example](../../images/abp-select2-multiple.png) |
## Getting Started
This is a core feature and it's used by the ABP Framework. There is no custom installation or additional packages required.
## Usage
A simple usage is presented below.
```html
<select asp-for="Book.AuthorId"
class="auto-complete-select"
data-autocomplete-api-url="/api/app/author"
data-autocomplete-display-property="name"
data-autocomplete-value-property="id"
data-autocomplete-items-property="items"
data-autocomplete-filter-param-name="filter">
<!-- You can define selected option(s) here -->
<option selected value="@SelectedAuthor.Id">@SelectedAuthor.Name</option>
</select>
```
The select must have the `auto-complete-select` class and the following attributes:
- `data-autocomplete-api-url`: * API Endpoint url to get select items. **GET** request will be sent to this url.
- `data-autocomplete-display-property`: * Property name to display. _(For example: `name` or `title`. Property name of entity/dto.)_.
- `data-autocomplete-value-property`: * Identifier property name. _(For example: `id`)_.
- `data-autocomplete-items-property`: * Property name of collection in response object. _(For example: `items`)_
- `data-autocomplete-filter-param-name`: * Filter text property name. _(For example: `filter`)_.
- `data-autocomplete-selected-item-name`: Text to display as selected item.
- `data-autocomplete-parent-selector`: jQuery selector expression for parent DOM. _(If it's in a modal, it's suggested to send the modal selector as this parameter)_.
Also, selected value(s) should be defined with the `<option>` tags inside select, since pagination is applied and the selected options might haven't loaded yet.
### Multiple Choices
AutoComplete Select supports multiple choices. If the select tag has a `multiple` attribute, it'll allow to choose multiple options.
```html
<select asp-for="Book.TagIds"
class="auto-complete-select"
multiple="multiple"
data-autocomplete-api-url="/api/app/tags"
data-autocomplete-display-property="name"
data-autocomplete-value-property="id"
data-autocomplete-items-property="items"
data-autocomplete-filter-param-name="filter">
@foreach(var tag in SelectedTags)
{
<option selected value="@tag.Id">@tag.Name</option>
}
</select>
```
It'll be automatically bound to a collection of defined value type.
```csharp
public List<Guid> TagIds { get; set; }
```
## Notices
If the authenticated user doesn't have permission on the given URL, the user will get an authorization error. Be careful while designing this kind of UIs.
You can create a specific, [unauthorized](../../Authorization.md) endpoint/method to get the list of items, so the page can retrieve lookup data of dependent entity without giving the entire read permission to users.

8
docs/en/docs-nav.json

@ -300,6 +300,10 @@
"text": "Data Seeding",
"path": "Data-Seeding.md"
},
{
"text": "Distributed Locking",
"path": "Distributed-Locking.md"
},
{
"text": "Email Sending",
"items": [
@ -623,6 +627,10 @@
"text": "Data Tables",
"path": "UI/AspNetCore/Data-Tables.md"
},
{
"text": "Auto-Complete Select",
"path": "UI/AspNetCore/AutoComplete-Select.md"
},
{
"text": "Page Alerts",
"path": "UI/AspNetCore/Page-Alerts.md"

BIN
docs/en/images/abp-select2-multiple.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

BIN
docs/en/images/abp-select2-single.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

259
docs/zh-Hans/Caching.md

@ -1,164 +1,180 @@
# 缓存
ABP框架扩展了ASP.NET Core的分布式缓存系统.
ABP框架扩展了 [ASP.NET Core的分布式缓存系统](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed).
## Volo.Abp.Caching Package
## 安装
> 默认情况下启动模板已经安装了这个包,所以大部分情况下你不需要手动安装.
> 默认情况下 [启动模板](Startup-Templates/Application.md) 已经安装了这个包. 所以大部分情况下你不需要手动安装.
Volo.Abp.Caching是缓存系统的核心包.使用包管理控制台(PMC)安装到项目:
[Volo.Abp.Caching](https://www.nuget.org/packages/Volo.Abp.Caching)是缓存系统的核心包. 可以使用 [ABP CLI](CLI.md) 的add-package命令将其安装到项目中:
```
Install-Package Volo.Abp.Caching
abp add-package Volo.Abp.Caching
```
你需要在包含 `csproj` 文件的文件夹中的命令行终端上运行此命令(请参阅 [其他选项](https://abp.io/package-detail/Volo.Abp.Caching) 安装).
然后将 **AbpCachingModule** 依赖添加到你的模块:
## 使用方式
```c#
using Volo.Abp.Modularity;
using Volo.Abp.Caching;
namespace MyCompany.MyProject
{
[DependsOn(typeof(AbpCachingModule))]
public class MyModule : AbpModule
{
//...
}
}
```
## `IDistributedCache` 接口
### `IDistributedCache` 接口
ASP.NET Core 定义了 `IDistributedCache` 接口用于 get/set 缓存值 . 但是会有以下问题:
ASP.NET Core 定义了 `IDistributedCache` 接口用于 get/set 缓存值. 但是会有以下问题:
* 它适用于 **byte 数组** 而不是 .NET 对象. 因此你需要对缓存的对象进行**序列化/反序列化**.
* 它为所有的缓存项提供了 **单个 key 池** , 因此 ;
* 它为所有的缓存项提供了 **单个 key 池** , 因此;
* 你需要注意键区分 **不同类型的对象**.
* 你需要注意**不同租户**(参见[多租户](Multi-Tenancy.md))的缓存项.
> `IDistributedCache` 定义在 `Microsoft.Extensions.Caching.Abstractions` 包中. 这使它不仅适用于ASP.NET Core应用程序, 也可用于**任何类型的程序**.
> `IDistributedCache` 接口的默认实现是 `MemoryDistributedCache` 它使用**内存**工作. 参见 [ASP.NET Core文档](https://docs.microsoft.com/zh-cn/aspnet/core/performance/caching/distributed) 了解如何切换到 **Redis** 或其他缓存提供程序.
> `IDistributedCache` 接口的默认实现是 `MemoryDistributedCache` 它使用**内存**工作. 参见 [ASP.NET Core文档](https://docs.microsoft.com/zh-cn/aspnet/core/performance/caching/distributed) 了解如何切换到 **Redis** 或其他缓存提供程序. 此外, 如果要将Redis用作分布式缓存服务器, [Redis缓存](Redis-Cache.md) 文档.
有关更多信息, 参见 [ASP.NET Core 分布式缓存文档](https://docs.microsoft.com/zh-cn/aspnet/core/performance/caching/distributed).
## `IDistributedCache<TCacheItem>` 接口
### `IDistributedCache<TCacheItem>` 接口
ABP框架在[Volo.Abp.Caching](https://www.nuget.org/packages/Volo.Abp.Caching/)包定义了通用的泛型 `IDistributedCache<TCacheItem>` 接口. `TCacheItem` 是存储在缓存中的对象类型.
`IDistributedCache<TCacheItem>` 接口了上述中的问题;
`IDistributedCache<TCacheItem>` 接口解决了上述中的问题;
* 它在内部 **序列化/反序列化** 缓存对象. 默认使用 **JSON** 序列化, 但可以替换[依赖注入](Dependency-Injection.md)系统中 `IDistributedCacheSerializer` 服务的实现来覆盖默认的处理.
* 它根据缓存中对象类型自动向缓存key添加 **缓存名称** 前缀. 默认缓存名是缓存对象类的全名(如果你的类名以`CacheItem` 结尾, 那么`CacheItem` 会被忽略,不应用到缓存名称上). 你也可以在缓存类上使用 `CacheName` 设置换缓存的名称.
* 它自动将当前的**租户id**添加到缓存键中, 以区分不同租户的缓存项 (只有在你的应用程序是[多租户](Multi-Tenancy.md)的情况下生效). 在缓存类上应用 `IgnoreMultiTenancy` attribute, 可以在所有的租户间共享缓存.
* 允许为每个应用程序定义 **全局缓存键前缀** ,不同的应用程序可以在共享的分布式缓存中拥有自己的隔离池.
* 它根据缓存中对象类型自动向缓存key添加 **缓存名称** 前缀. 默认缓存名是缓存对象类的全名(如果你的类名以`CacheItem` 结尾, 那么`CacheItem` 会被忽略,不应用到缓存名称上). 你也可以在缓存类上使用 **`CacheName` 特性** 设置缓存的名称.
* 它自动将**当前的租户id**添加到缓存键中, 以区分不同租户的缓存项 (只有在你的应用程序是[多租户](Multi-Tenancy.md)的情况下生效). 如果要在多租户应用程序中的所有租户之间共享缓存对象, 请在缓存项类上定义`IgnoreMultiTenancy`特性以禁用此选项.
* 允许为每个应用程序定义 **全局缓存键前缀** , 不同的应用程序可以在共享的分布式缓存中拥有自己的隔离池.
* 它可以在任何可能绕过缓存的情况下 **容忍错误** 的发生. 这在缓存服务器出现临时问题时非常有用.
* 它有 `GetManyAsync``SetManyAsync` 等方法, 可以显著提高**批处理**的性能.
### 使用方式
缓存中存储项的示例类:
**示例: 在缓存中存储图书名称和价格**
````csharp
public class BookCacheItem
namespace MyProject
{
public string Name { get; set; }
public class BookCacheItem
{
public string Name { get; set; }
public float Price { get; set; }
public float Price { get; set; }
}
}
````
你可以注入 `IDistributedCache<BookCacheItem>` 服务用于 get/set `BookCacheItem` 对象.
使用示例:
````csharp
public class BookService : ITransientDependency
{
private readonly IDistributedCache<BookCacheItem> _cache;
public BookService(IDistributedCache<BookCacheItem> cache)
{
_cache = cache;
}
public async Task<BookCacheItem> GetAsync(Guid bookId)
{
return await _cache.GetOrAddAsync(
bookId.ToString(), //Cache key
async () => await GetBookFromDatabaseAsync(bookId),
() => new DistributedCacheEntryOptions
{
AbsoluteExpiration = DateTimeOffset.Now.AddHours(1)
}
);
}
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Distributed;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
private Task<BookCacheItem> GetBookFromDatabaseAsync(Guid bookId)
namespace MyProject
{
public class BookService : ITransientDependency
{
//TODO: get from database
private readonly IDistributedCache<BookCacheItem> _cache;
public BookService(IDistributedCache<BookCacheItem> cache)
{
_cache = cache;
}
public async Task<BookCacheItem> GetAsync(Guid bookId)
{
return await _cache.GetOrAddAsync(
bookId.ToString(), //缓存键
async () => await GetBookFromDatabaseAsync(bookId),
() => new DistributedCacheEntryOptions
{
AbsoluteExpiration = DateTimeOffset.Now.AddHours(1)
}
);
}
private Task<BookCacheItem> GetBookFromDatabaseAsync(Guid bookId)
{
//TODO: 从数据库获取数据
}
}
}
````
* 示例服务代码中的 `GetOrAddAsync()` 方法从缓存中获取图书项.
* 示例服务代码中的 `GetOrAddAsync()` 方法从缓存中获取图书项. `GetOrAddAsync`是ABP框架在 ASP.NET Core 分布式缓存方法中添增的附加方法.
* 如果没有在缓存中找到图书,它会调用工厂方法 (本示例中是 `GetBookFromDatabaseAsync`)从原始数据源中获取图书项.
* `GetOrAddAsync` 有一个可选参数 `DistributedCacheEntryOptions` , 可用于设置缓存的生命周期.
`IDistributedCache<BookCacheItem>` 的其他方法与ASP.NET Core的`IDistributedCache` 接口相同, 你可以参考 [ASP.NET Core文档](https://docs.microsoft.com/zh-cn/aspnet/core/performance/caching/distributed).
`IDistributedCache<BookCacheItem>` 与ASP.NET Core的`IDistributedCache` 接口拥有相同的方法, 你可以参考 [ASP.NET Core文档](https://docs.microsoft.com/zh-cn/aspnet/core/performance/caching/distributed).
## `IDistributedCache<TCacheItem, TCacheKey>` 接口
### `IDistributedCache<TCacheItem, TCacheKey>` 接口
`IDistributedCache<TCacheItem>` 接口默认了键是 `string` 类型 (如果你的键不是string类型需要进行手动类型转换). `IDistributedCache<TCacheItem, TCacheKey>` 将键的类型泛型化试图简化手动转换的操作.
`IDistributedCache<TCacheItem>` 接口默认了**缓存**`string` 类型 (如果你的键不是string类型需要进行手动类型转换). 但当缓存键的类型不是`string`时, 可以使用`IDistributedCache<TCacheItem, TCacheKey>`.
### 使用示例
**示例: 在缓存中存储图书名称和价格**
示例缓存项
````csharp
public class BookCacheItem
using Volo.Abp.Caching;
namespace MyProject
{
public string Name { get; set; }
[CacheName("Books")]
public class BookCacheItem
{
public string Name { get; set; }
public float Price { get; set; }
public float Price { get; set; }
}
}
````
用法示例 (这里假设你的键类型是 `Guid`):
* 在本例中使用`CacheName`特性给`BookCacheItem`类设置缓存名称.
````csharp
public class BookService : ITransientDependency
{
private readonly IDistributedCache<BookCacheItem, Guid> _cache;
你可以注入 `IDistributedCache<BookCacheItem, Guid>` 服务用于 get/set `BookCacheItem` 对象.
public BookService(IDistributedCache<BookCacheItem, Guid> cache)
{
_cache = cache;
}
````csharp
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Distributed;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
public async Task<BookCacheItem> GetAsync(Guid bookId)
{
return await _cache.GetOrAddAsync(
bookId, //Guid type used as the cache key
async () => await GetBookFromDatabaseAsync(bookId),
() => new DistributedCacheEntryOptions
{
AbsoluteExpiration = DateTimeOffset.Now.AddHours(1)
}
);
}
private Task<BookCacheItem> GetBookFromDatabaseAsync(Guid bookId)
namespace MyProject
{
public class BookService : ITransientDependency
{
//TODO: get from database
private readonly IDistributedCache<BookCacheItem, Guid> _cache;
public BookService(IDistributedCache<BookCacheItem, Guid> cache)
{
_cache = cache;
}
public async Task<BookCacheItem> GetAsync(Guid bookId)
{
return await _cache.GetOrAddAsync(
bookId, //Guid类型作为缓存键
async () => await GetBookFromDatabaseAsync(bookId),
() => new DistributedCacheEntryOptions
{
AbsoluteExpiration = DateTimeOffset.Now.AddHours(1)
}
);
}
private Task<BookCacheItem> GetBookFromDatabaseAsync(Guid bookId)
{
//TODO: 从数据库获取数据
}
}
}
````
* 示例服务中 `GetOrAddAsync()` 方法获取缓存的图书项.
* 我们采用了 `Guid` 做为键,在 `_cache_GetOrAddAsync()` 方法中传入 `Guid` 类型的bookid.
* 我们采用了 `Guid` 做为键, 在 `_cache_GetOrAddAsync()` 方法中传入 `Guid` 类型的bookid.
#### 复杂类型的缓存键
`IDistributedCache<TCacheItem, TCacheKey>` 在内部使用键对象的 `ToString()` 方法转换类型为string. 如果你的将复杂对象做为键,那么需要重写类的 `ToString` 方法.
`IDistributedCache<TCacheItem, TCacheKey>` 在内部使用键对象的 `ToString()` 方法转换类型为string. 如果你的将复杂对象做为缓存键,那么需要重写类的 `ToString` 方法.
示例:
举例一个作为缓存键的类:
````csharp
public class UserInOrganizationCacheKey
@ -187,23 +203,72 @@ public class BookService : ITransientDependency
{
_cache = cache;
}
...
}
````
## 配置
### AbpDistributedCacheOptions
`AbpDistributedCacheOptions` 是配置缓存的主要[Option类](Options.md).
**示例:为应用程序设置缓存键前缀**
```csharp
Configure<AbpDistributedCacheOptions>(options =>
{
options.KeyPrefix = "MyApp1";
});
```
> 在[模块类](Module-Development-Basics.md)的`ConfigureServices`方法中添加代码.
#### 可用选项
* `HideErrors` (`bool`, 默认: `true`): 启用/禁用隐藏从缓存服务器写入/读取值时的错误.
* `KeyPrefix` (`string`, 默认: `null`): 如果你的缓存服务器由多个应用程序共同使用, 则可以为应用程序的缓存键设置一个前缀. 在这种情况下, 不同的应用程序不能覆盖彼此的缓存内容.
* `GlobalCacheEntryOptions` (`DistributedCacheEntryOptions`): 用于设置保存缓内容却没有指定选项时, 默认的分布式缓存选项 (例如 `AbsoluteExpiration``SlidingExpiration`). `SlidingExpiration`的默认值设置为20分钟.
## 错误处理
当为你的对象设计缓存时, 通常会首先尝试从缓存中获取值. 如果在缓存中找不到该值, 则从**来源**查询对象. 它可能在**数据库**中, 或者可能需要通过HTTP调用远程服务器.
在大多数情况下, 你希望**容忍缓存错误**; 如果缓存服务器出现错误, 也不希望取消该操作. 相反, 你可以默默地隐藏(并记录)错误并**从来源查询**. 这就是ABP框架默认的功能.
ABP的分布式缓存 [异常处理](Exception-Handling.md), 默认记录并隐藏错误. 有一个全局修改该功能的选项(参见下面的选项内容).
所有的`IDistributedCache<TCacheItem>` (和 `IDistributedCache<TCacheItem, TCacheKey>`)方法都有一个可选的参数`hideErrors`, 默认值为`null`. 如果此参数设置为`null`, 则全局生效, 否则你可以选择单个方法调用时隐藏或者抛出异常.
## 批量操作
ABP的分布式缓存接口定义了以下批量操作方法,当你需要在一个方法中调用多次缓存操作时,这些方法可以提高性能
* `SetManyAsync``SetMany` 方法可以用来设置多个值.
* `SetManyAsync``SetMany` 方法可以用来向缓存中设置多个值.
* `GetManyAsync``GetMany` 方法可以用来从缓存中获取多个值.
* `GetOrAddManyAsync``GetOrAddMany` 方法可以用来从缓存中获取并添加缺少的值.
* `RefreshManyAsync``RefreshMany` 方法可以来用重置多个值的滚动过期时间.
* `RemoveManyAsync``RemoveMany` 方法呆以用来删除多个值.
* `RemoveManyAsync``RemoveMany` 方法可以用来从缓存中删除多个值.
> 这些不是标准的ASP.NET Core缓存方法, 所以某些提供程序可能不支持. [ABP Redis集成包](Redis-Cache.md)实现了它们. 如果提供程序不支持,会回退到 `SetAsync``GetAsync` ... 方法(循环调用).
### DistributedCacheOptions
## 高级主题
### 工作单元级别的缓存
分布式缓存服务提供了一个有趣的功能. 假设你已经更新了数据库中某本书的价格, 然后将新价格设置到缓存中, 以便以后使用缓存的值. 如果设置缓存后出现异常, 并且更新图书价格的**事务被回滚了**, 该怎么办?在这种情况下, 缓存值是错误的.
`IDistributedCache<..>`方法提供一个可选参数, `considerOuw`, 默认为`false`. 如果将其设置为`true`, 则你对缓存所做的更改不会应用于真正的缓存存储, 而是与当前的[工作单元](Unit-Of-Work.md)关联. 你将获得在同一工作单元中设置的缓存值, 但**仅当前工作单元成功时**更改才会生效.
### IDistributedCacheSerializer
`IDistributedCacheSerializer`服务用于序列化和反序列化缓存内容. 默认实现是`Utf8JsonDistributedCacheSerializer`类, 它使用`IJsonSerializer`服务将对象转换为[JSON](Json-Serialization.md), 反之亦然. 然后, 它使用UTC8编码将JSON字符串转换为分布式缓存接受的字节数组.
如果你想实现自己的序列化逻辑, 可以自己实现并[替换](Dependency-Injection.md) 此服务.
### IDistributedCacheKeyNormalizer
默认情况下, `IDistributedCacheKeyNormalizer`是由`DistributedCacheKeyNormalizer`类实现的. 它将缓存名称、应用程序缓存前缀和当前租户id添加到缓存键中. 如果需要更高级的键规范化, 可以自己实现并[替换](Dependency-Injection.md)此服务.
## 另请参阅
TODO
* [Redis 缓存](Redis-Cache.md)

8
docs/zh-Hans/Distributed-Event-Bus-Kafka-Integration.md

@ -1,10 +1,10 @@
# 分布式事件总线Kafka集成
> 本文解释了**如何配置[Kafka](https://kafka.apache.org/)**做为分布式总线提供程序. 参阅[分布式事件总线文档](Distributed-Event-Bus.md)了解如何使用分布式事件总线系统.
> 本文解释了 **如何配置[Kafka](https://kafka.apache.org/)** 做为分布式总线提供程序. 参阅[分布式事件总线文档](Distributed-Event-Bus.md)了解如何使用分布式事件总线系统.
## 安装
使用ABP CLI添加[Volo.Abp.EventBus.Kafka[Volo.Abp.EventBus.Kafka](https://www.nuget.org/packages/Volo.Abp.EventBus.Kafka)NuGet包到你的项目:
使用ABP CLI添加[Volo.Abp.EventBus.Kafka](https://www.nuget.org/packages/Volo.Abp.EventBus.Kafka)NuGet包到你的项目:
* 安装[ABP CLI](https://docs.abp.io/en/abp/latest/CLI),如果你还没有安装.
* 在你想要安装 `Volo.Abp.EventBus.Kafka` 包的 `.csproj` 文件目录打开命令行(终端).
@ -18,7 +18,7 @@
### `appsettings.json` 文件配置
这是配置Kafka设置最简单的方法. 它也非常强大,因为你可以使用[由AspNet Core支持](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/)的任何其他配置源(如环境变量).
这是配置Kafka设置最简单的方法. 它也非常强大,因为你可以使用[由AspNet Core支持](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/)的任何其他配置源(如环境变量).
**示例:最小化配置与默认配置连接到本地的Kafka服务器**
@ -160,4 +160,4 @@ Configure<AbpKafkaOptions>(options =>
});
````
使用这些选项类可以与 `appsettings.json` 组合在一起. 在代码中配置选项属性会覆盖配置文件中的值.
使用这些选项类可以与 `appsettings.json` 组合在一起. 在代码中配置选项属性会覆盖配置文件中的值.

8
docs/zh-Hans/Distributed-Event-Bus-RabbitMQ-Integration.md

@ -1,10 +1,10 @@
# 分布式事件总线RabbitMQ集成
> 本文解释了**如何配置[RabbitMQ](https://www.rabbitmq.com/)**做为分布式总线提供程序. 参阅[分布式事件总线文档](Distributed-Event-Bus.md)了解如何使用分布式事件总线系统.
> 本文解释了 **如何配置[RabbitMQ](https://www.rabbitmq.com/)** 做为分布式总线提供程序. 参阅[分布式事件总线文档](Distributed-Event-Bus.md)了解如何使用分布式事件总线系统.
## 安装
使用ABP CLI添加[Volo.Abp.EventBus.RabbitMQ[Volo.Abp.EventBus.RabbitMQ](https://www.nuget.org/packages/Volo.Abp.EventBus.RabbitMQ)NuGet包到你的项目:
使用ABP CLI添加[Volo.Abp.EventBus.RabbitMQ](https://www.nuget.org/packages/Volo.Abp.EventBus.RabbitMQ)NuGet包到你的项目:
* 安装[ABP CLI](https://docs.abp.io/en/abp/latest/CLI),如果你还没有安装.
* 在你想要安装 `Volo.Abp.EventBus.RabbitMQ` 包的 `.csproj` 文件目录打开命令行(终端).
@ -18,7 +18,7 @@
### `appsettings.json` 文件配置
这是配置RabbitMQ设置最简单的方法. 它也非常强大,因为你可以使用[由AspNet Core支持](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/)的任何其他配置源(如环境变量).
这是配置RabbitMQ设置最简单的方法. 它也非常强大,因为你可以使用[由AspNet Core支持](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/)的任何其他配置源(如环境变量).
**示例:最小化配置与默认配置连接到本地的RabbitMQ服务器**
@ -151,4 +151,4 @@ Configure<AbpRabbitMqEventBusOptions>(options =>
});
````
使用这些选项类可以与 `appsettings.json` 组合在一起. 在代码中配置选项属性会覆盖配置文件中的值.
使用这些选项类可以与 `appsettings.json` 组合在一起. 在代码中配置选项属性会覆盖配置文件中的值.

4
docs/zh-Hans/Distributed-Event-Bus-Rebus-Integration.md

@ -1,10 +1,10 @@
# 分布式事件总线Rebus集成
> 本文解释了**如何配置[Rebus](http://mookid.dk/category/rebus/)**做为分布式总线提供程序. 参阅[分布式事件总线文档](Distributed-Event-Bus.md)了解如何使用分布式事件总线系统.
> 本文解释了 **如何配置[Rebus](http://mookid.dk/category/rebus/)** 做为分布式总线提供程序. 参阅[分布式事件总线文档](Distributed-Event-Bus.md)了解如何使用分布式事件总线系统.
## 安装
使用ABP CLI添加[Volo.Abp.EventBus.Rebus[Volo.Abp.EventBus.Rebus](https://www.nuget.org/packages/Volo.Abp.EventBus.Rebus)NuGet包到你的项目:
使用ABP CLI添加[Volo.Abp.EventBus.Rebus](https://www.nuget.org/packages/Volo.Abp.EventBus.Rebus)NuGet包到你的项目:
* 安装[ABP CLI](https://docs.abp.io/en/abp/latest/CLI),如果你还没有安装.
* 在你想要安装 `Volo.Abp.EventBus.Rebus` 包的 `.csproj` 文件目录打开命令行(终端).

2
docs/zh-Hans/Distributed-Event-Bus.md

@ -264,7 +264,7 @@ Configure<AbpDistributedEntityEventOptions>(options =>
因此可以实现 `IDistributedEventHandler<EntityUpdatedEto<EntityEto>>` 订阅事件. 但是订阅这样的通用事件不是一个好方法,你可以为实体类型定义对应的ETO.
**示例: 为 `Product` 声明使用 `ProductDto`**
**示例: 为 `Product` 声明使用 `ProductEto`**
````csharp
Configure<AbpDistributedEntityEventOptions>(options =>

56
docs/zh-Hans/Modules/Background-Jobs.md

@ -1,3 +1,55 @@
# Background Jobs Module
# 后台作业模块
待添加
后台作业模块实现了 `IBackgroundJobStore` 接口,并且可以使用ABP框架的默认后台作业管理.如果你不想使用这个模块,那么你需要自己实现 `IBackgroundJobStore` 接口.
> 本文档仅介绍后台作业模块,该模块将后台作业持久化到数据库.有关后台作业系统的更多信息,请参阅[后台作业](../Background-Jobs.md)文档.
## 如何使用
当你使用ABP框架[创建一个新的解决方案](https://abp.io/get-started)时,这个模块是(作为NuGet/NPM包)预先安装的.你可以继续将其作为软件包使用并轻松获取更新,也可以将其源代码包含到解决方案中(请参阅 `get-source` [CLI](../CLI.md)命令)以开发自定义模块.
### 源代码
此模块的源代码可在[此处](https://github.com/abpframework/abp/tree/dev/modules/background-jobs)访问.源代码是由[MIT](https://choosealicense.com/licenses/mit/)授权的,所以你可以自由使用和定制它.
## 内部结构
### 领域层
#### 聚合
- `BackgroundJobRecord` (聚合根): 表示后台工作记录.
#### 仓储
为该模块定义了以下自定义仓储:
- `IBackgroundJobRepository`
### 数据库提供程序
#### 通用
##### 表/集合的前缀与架构
默认情况下,所有表/集合都使用 `Abp` 前缀.如果需要更改表前缀或设置架构名称(如果数据库提供程序支持),请在 `BackgroundJobsDbProperties` 类上设置静态属性.
##### 连接字符串
此模块使用 `AbpBackgroundJobs` 作为连接字符串名称.如果不使用此名称定义连接字符串,它将返回 `Default` 连接字符串.有关详细信息,请参阅[连接字符串](https://docs.abp.io/en/abp/latest/Connection-Strings)文档.
#### Entity Framework Core
##### 表
- **AbpBackgroundJobs**
#### MongoDB
##### 集合
- **AbpBackgroundJobs**
## 另请参阅
* [后台作业系统](../Background-Jobs.md)

256
docs/zh-Hans/Specifications.md

@ -1,3 +1,257 @@
## 规约
TODO..
规约模式用于为实体和其他业务对象定义 **命名、可复用、可组合和可测试的过滤器** .
> 规约是领域层的一部分.
## 安装
> 这个包 **已经安装** 在启动模板中.所以,大多数时候你不需要手动去安装.
添加 [Volo.Abp.Specifications](https://abp.io/package-detail/Volo.Abp.Specifications) 包到你的项目. 如果当前文件夹是你的项目的根目录(`.csproj`)时,你可以在命令行终端中使用 [ABP CLI](CLI.md) *add package* 命令:
````bash
abp add-package Volo.Abp.Specifications
````
## 定义规约
假设你定义了如下的顾客实体:
````csharp
using System;
using Volo.Abp.Domain.Entities;
namespace MyProject
{
public class Customer : AggregateRoot<Guid>
{
public string Name { get; set; }
public byte Age { get; set; }
public long Balance { get; set; }
public string Location { get; set; }
}
}
````
你可以创建一个由 `Specification<Customer>` 派生的新规约类.
**例如:规定选择一个18岁以上的顾客**
````csharp
using System;
using System.Linq.Expressions;
using Volo.Abp.Specifications;
namespace MyProject
{
public class Age18PlusCustomerSpecification : Specification<Customer>
{
public override Expression<Func<Customer, bool>> ToExpression()
{
return c => c.Age >= 18;
}
}
}
````
你只需通过定义一个lambda[表达式](https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/operators/lambda-expressions)来定义规约.
> 你也可以直接实现`ISpecification<T>`接口,但是基类`Specification<T>`做了大量简化.
## 使用规约
这里有两种常见的规约用例.
### IsSatisfiedBy
`IsSatisfiedBy` 方法可以用于检查单个对象是否满足规约.
**例如:如果顾客不满足年龄规定,则抛出异常**
````csharp
using System;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace MyProject
{
public class CustomerService : ITransientDependency
{
public async Task BuyAlcohol(Customer customer)
{
if (!new Age18PlusCustomerSpecification().IsSatisfiedBy(customer))
{
throw new Exception(
"这位顾客不满足年龄规定!"
);
}
//TODO...
}
}
}
````
### ToExpression & Repositories
`ToExpression()` 方法可用于将规约转化为表达式.通过这种方式,你可以使用规约在**数据库查询时过滤实体**.
````csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Domain.Services;
namespace MyProject
{
public class CustomerManager : DomainService, ITransientDependency
{
private readonly IRepository<Customer, Guid> _customerRepository;
public CustomerManager(IRepository<Customer, Guid> customerRepository)
{
_customerRepository = customerRepository;
}
public async Task<List<Customer>> GetCustomersCanBuyAlcohol()
{
var queryable = await _customerRepository.GetQueryableAsync();
var query = queryable.Where(
new Age18PlusCustomerSpecification().ToExpression()
);
return await AsyncExecuter.ToListAsync(query);
}
}
}
````
> 规约被正确地转换为SQL/数据库查询语句,并且在DBMS端高效执行.虽然它与规约无关,但如果你想了解有关 `AsyncExecuter` 的更多信息,请参阅[仓储](Repositories.md)文档.
实际上,没有必要使用 `ToExpression()` 方法,因为规约会自动转换为表达式.这也会起作用:
````csharp
var queryable = await _customerRepository.GetQueryableAsync();
var query = queryable.Where(
new Age18PlusCustomerSpecification()
);
````
## 编写规约
规约有一个强大的功能是,它们可以与`And`、`Or`、`Not`以及`AndNot`扩展方法组合使用.
假设你有另一个规约,定义如下:
```csharp
using System;
using System.Linq.Expressions;
using Volo.Abp.Specifications;
namespace MyProject
{
public class PremiumCustomerSpecification : Specification<Customer>
{
public override Expression<Func<Customer, bool>> ToExpression()
{
return (customer) => (customer.Balance >= 100000);
}
}
}
```
你可以将 `PremiumCustomerSpecification``Age18PlusCustomerSpecification` 结合起来,查询优质成人顾客的数量,如下所示:
````csharp
using System;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Domain.Services;
using Volo.Abp.Specifications;
namespace MyProject
{
public class CustomerManager : DomainService, ITransientDependency
{
private readonly IRepository<Customer, Guid> _customerRepository;
public CustomerManager(IRepository<Customer, Guid> customerRepository)
{
_customerRepository = customerRepository;
}
public async Task<int> GetAdultPremiumCustomerCountAsync()
{
return await _customerRepository.CountAsync(
new Age18PlusCustomerSpecification()
.And(new PremiumCustomerSpecification()).ToExpression()
);
}
}
}
````
如果你想让这个组合成为一个可复用的规约,你可以创建这样一个组合的规约类,它派生自`AndSpecification`:
````csharp
using Volo.Abp.Specifications;
namespace MyProject
{
public class AdultPremiumCustomerSpecification : AndSpecification<Customer>
{
public AdultPremiumCustomerSpecification()
: base(new Age18PlusCustomerSpecification(),
new PremiumCustomerSpecification())
{
}
}
}
````
现在,你就可以向下面一样重新编写 `GetAdultPremiumCustomerCountAsync` 方法:
````csharp
public async Task<int> GetAdultPremiumCustomerCountAsync()
{
return await _customerRepository.CountAsync(
new AdultPremiumCustomerSpecification()
);
}
````
> 你可以从这些例子中看到规约的强大之处.如果你之后想要更改 `PremiumCustomerSpecification` ,比如将余额从 `100.000` 修改为 `200.000` ,所有查询语句和合并的规约都将受到本次更改的影响.这是减少代码重复的好方法!
## 讨论
虽然规约模式通常与C#的lambda表达式相比较,算是一种更老的方式.一些开发人员可能认为不再需要它,我们可以直接将表达式传入到仓储或领域服务中,如下所示:
````csharp
var count = await _customerRepository.CountAsync(c => c.Balance > 100000 && c.Age => 18);
````
自从ABP的[仓储](Repositories.md)支持表达式,这是一个完全有效的用法.你不必在应用程序中定义或使用任何规约,可以直接使用表达式.
所以,规约的意义是什么?为什么或者应该在什么时候考虑去使用它?
### 何时使用?
使用规约的一些好处:
- **可复用**:假设你在代码库的许多地方都需要用到优质顾客过滤器.如果使用表达式而不创建规约,那么如果以后更改“优质顾客”的定义会发生什么?假设你想将最低余额从100000美元更改为250000美元,并添加另一个条件,成为顾客超过3年.如果使用了规约,只需修改一个类.如果在任何其他地方重复(复制/粘贴)相同的表达式,则需要更改所有的表达式.
- **可组合**:可以组合多个规约来创建新规约.这是另一种可复用性.
- **命名**:`PremiumCustomerSpecification` 更好地解释了为什么使用规约,而不是复杂的表达式.因此,如果在你的业务中使用了一个有意义的表达式,请考虑使用规约.
- **可测试**:规约是一个单独(且易于)测试的对象.
### 什么时侯不要使用?
- **没有业务含义的表达式**:不要对与业务无关的表达式和操作使用规约.
- **报表**:如果只是创建报表,不要创建规约,而是直接使用 `IQueryable` 和LINQ表达式.你甚至可以使用普通SQL、视图或其他工具生成报表.DDD不关心报表,因此从性能角度来看,查询底层数据存储的方式可能很重要.

8
framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj

@ -14,10 +14,10 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Blazorise" Version="1.0.0" />
<PackageReference Include="Blazorise.DataGrid" Version="1.0.0" />
<PackageReference Include="Blazorise.Snackbar" Version="1.0.0" />
<PackageReference Include="Blazorise.Components" Version="1.0.0" />
<PackageReference Include="Blazorise" Version="1.0.1" />
<PackageReference Include="Blazorise.DataGrid" Version="1.0.1" />
<PackageReference Include="Blazorise.Snackbar" Version="1.0.1" />
<PackageReference Include="Blazorise.Components" Version="1.0.1" />
</ItemGroup>
</Project>

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ConnectionStringChangeStep.cs

@ -26,7 +26,7 @@ public class ConnectionStringChangeStep : ProjectBuildPipelineStep
return;
}
var newConnectionString = $"\"{DefaultConnectionStringKey}\": \"{context.BuildArgs.ConnectionString}\"";
var newConnectionString = $"\"{DefaultConnectionStringKey}\": \"{context.BuildArgs.ConnectionString.Replace(@"\\", @"\").Replace(@"\", @"\\")}\"";
foreach (var appSettingsJson in appSettingsJsonFiles)
{

2
framework/src/Volo.Abp.EventBus.Azure/Volo/Abp/EventBus/Azure/AbpAzureEventBusOptions.cs

@ -7,4 +7,6 @@ public class AbpAzureEventBusOptions
public string SubscriberName { get; set; }
public string TopicName { get; set; }
public bool IsServiceBusDisabled { get; set; }
}

15
framework/src/Volo.Abp.EventBus.Azure/Volo/Abp/EventBus/Azure/AbpEventBusAzureModule.cs

@ -1,4 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.AzureServiceBus;
using Volo.Abp.Modularity;
@ -19,9 +20,15 @@ public class AbpEventBusAzureModule : AbpModule
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
context
.ServiceProvider
.GetRequiredService<AzureDistributedEventBus>()
.Initialize();
var options = context.ServiceProvider.GetRequiredService<IOptions<AbpAzureEventBusOptions>>().Value;
if (!options.IsServiceBusDisabled)
{
context
.ServiceProvider
.GetRequiredService<AzureDistributedEventBus>()
.Initialize();
}
}
}

14
framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingEncryptionService.cs

@ -1,4 +1,6 @@
using System;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Security.Encryption;
@ -7,10 +9,12 @@ namespace Volo.Abp.Settings;
public class SettingEncryptionService : ISettingEncryptionService, ITransientDependency
{
protected IStringEncryptionService StringEncryptionService { get; }
public ILogger<SettingEncryptionService> Logger { get; set; }
public SettingEncryptionService(IStringEncryptionService stringEncryptionService)
{
StringEncryptionService = stringEncryptionService;
Logger = NullLogger<SettingEncryptionService>.Instance;
}
public virtual string Encrypt(SettingDefinition settingDefinition, string plainValue)
@ -30,6 +34,14 @@ public class SettingEncryptionService : ISettingEncryptionService, ITransientDep
return encryptedValue;
}
return StringEncryptionService.Decrypt(encryptedValue);
try
{
return StringEncryptionService.Decrypt(encryptedValue);
}
catch (Exception e)
{
Logger.LogException(e);
return string.Empty;
}
}
}

13
modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs

@ -231,11 +231,16 @@ namespace Volo.Blogging.Posts
return url;
}
private async Task SaveTags(ICollection<string> newTags, Post post)
private async Task SaveTags(ICollection<string> tags, Post post)
{
await RemoveOldTags(newTags, post);
await AddNewTags(newTags, post);
tags = tags
.Select(t => t.ToLowerInvariant())
.Distinct()
.ToList();
await RemoveOldTags(tags, post);
await AddNewTags(tags, post);
}
private async Task RemoveOldTags(ICollection<string> newTags, Post post)

1
modules/cms-kit/host/Volo.CmsKit.Web.Unified/abp.resourcemapping.js

@ -7,6 +7,5 @@ module.exports = {
"@libs"
],
mappings: {
}
}

8
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/GlobalResources/Index.cshtml

@ -2,6 +2,7 @@
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.AspNetCore.Mvc.UI.Layout
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.Codemirror
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.GlobalResources
@using Volo.CmsKit.Admin.Web.Menus
@using Volo.CmsKit.Localization
@ -17,8 +18,15 @@
PageLayout.Content.MenuItemName = CmsKitAdminMenus.GlobalResources.GlobalResourcesMenu;
}
@section styles{
<abp-style type="typeof(CodemirrorStyleContributor)" />
}
@section scripts {
<abp-script-bundle>
<abp-script type="typeof(CodemirrorScriptContributor )"/>
<abp-script src="/libs/codemirror/mode/css/css.js"/>
<abp-script src="/libs/codemirror/mode/javascript/javascript.js"/>
<abp-script src="/client-proxies/cms-kit-common-proxy.js"/>
<abp-script src="/client-proxies/cms-kit-admin-proxy.js"/>
<abp-script src="/Pages/CmsKit/GlobalResources/index.js"/>

19
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/GlobalResources/index.js

@ -3,11 +3,26 @@ $(function (){
var service = volo.cmsKit.admin.globalResources.globalResourceAdmin;
var scriptEditor = CodeMirror.fromTextArea(document.getElementById("ScriptContent"),{
mode:"javascript",
lineNumbers:true
});
var styleEditor = CodeMirror.fromTextArea(document.getElementById("StyleContent"),{
mode:"css",
lineNumbers:true
});
$('.nav-tabs a').on('shown.bs.tab', function() {
scriptEditor.refresh();
styleEditor.refresh();
});
$('#SaveResourcesButton').on('click','',function(){
service.setGlobalResources(
{
style: $('#StyleContent').val(),
script: $('#ScriptContent').val()
style: styleEditor.getValue(),
script: scriptEditor.getValue()
}
).then(function () {
abp.message.success(l("SavedSuccessfully"));

9
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Create.cshtml

@ -1,6 +1,7 @@
@page
@using System.Globalization
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.Codemirror
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.TuiEditor
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.Uppy
@using Volo.CmsKit.Admin.Web.Pages
@ -22,6 +23,9 @@
<abp-script type="typeof(TuiEditorScriptContributor)" />
<abp-script type="typeof(UppyScriptContributor)" />
<abp-script type="typeof(SlugifyScriptContributor)" />
<abp-script type="typeof(CodemirrorScriptContributor)"/>
<abp-script src="/libs/codemirror/mode/css/css.js"/>
<abp-script src="/libs/codemirror/mode/javascript/javascript.js"/>
<abp-script src="/client-proxies/cms-kit-common-proxy.js"/>
<abp-script src="/client-proxies/cms-kit-admin-proxy.js"/>
<abp-script src="/Pages/CmsKit/Pages/create.js" />
@ -31,6 +35,7 @@
@section styles {
<abp-style-bundle>
<abp-style type="typeof(TuiEditorStyleContributor)" />
<abp-style type="typeof(CodemirrorStyleContributor)" />
<abp-style src="/Pages/CmsKit/Pages/create.css"/>
</abp-style-bundle>
}
@ -56,11 +61,11 @@
</abp-tab>
<abp-tab title="@L["Script"]">
<abp-input asp-for="ViewModel.Script" suppress-label="true" class="cms-kit-editor" />
<abp-input asp-for="ViewModel.Script" suppress-label="true" />
</abp-tab>
<abp-tab title="@L["Style"]">
<abp-input asp-for="ViewModel.Style" suppress-label="true" class="cms-kit-editor"/>
<abp-input asp-for="ViewModel.Style" suppress-label="true"/>
</abp-tab>
</abp-tabs>

5
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Update.cshtml

@ -1,6 +1,7 @@
@page "{Id}"
@using System.Globalization
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.Codemirror
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.TuiEditor
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.Uppy
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.Slugify
@ -23,6 +24,9 @@
<abp-script type="typeof(TuiEditorScriptContributor)" />
<abp-script type="typeof(UppyScriptContributor)" />
<abp-script type="typeof(SlugifyScriptContributor)" />
<abp-script type="typeof(CodemirrorScriptContributor)"/>
<abp-script src="/libs/codemirror/mode/css/css.js"/>
<abp-script src="/libs/codemirror/mode/javascript/javascript.js"/>
<abp-script src="/client-proxies/cms-kit-common-proxy.js"/>
<abp-script src="/client-proxies/cms-kit-admin-proxy.js"/>
<abp-script src="/Pages/CmsKit/Pages/update.js" />
@ -32,6 +36,7 @@
@section styles {
<abp-style-bundle>
<abp-style type="typeof(TuiEditorStyleContributor)" />
<abp-style type="typeof(CodemirrorStyleContributor)" />
<abp-style src="/Pages/CmsKit/Pages/update.css" />
</abp-style-bundle>
}

22
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/create.js

@ -6,22 +6,40 @@ $(function () {
var $slug = $('#ViewModel_Slug');
var $buttonSubmit = $('#button-page-create');
var scriptEditor = CodeMirror.fromTextArea(document.getElementById("ViewModel_Script"), {
mode: "javascript",
lineNumbers: true
});
var styleEditor = CodeMirror.fromTextArea(document.getElementById("ViewModel_Style"), {
mode: "css",
lineNumbers: true
});
$('.nav-tabs a').on('shown.bs.tab', function () {
scriptEditor.refresh();
styleEditor.refresh();
});
$createForm.data('validator').settings.ignore = ":hidden, [contenteditable='true']:not([name]), .tui-popup-wrapper";
$createForm.on('submit', function (e) {
e.preventDefault();
if ($createForm.valid()) {
abp.ui.setBusy();
$("#ViewModel_Style").val(styleEditor.getValue());
$("#ViewModel_Script").val(scriptEditor.getValue());
$createForm.ajaxSubmit({
success: function (result) {
abp.notify.success(l('SuccessfullySaved'));
abp.ui.clearBusy();
location.href = "../Pages";
},
error: function(result){
error: function (result) {
abp.ui.clearBusy();
abp.notify.error(result.responseJSON.error.message);
}

18
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/update.js

@ -7,6 +7,21 @@ $(function () {
$formUpdate.data('validator').settings.ignore = ":hidden, [contenteditable='true']:not([name]), .tui-popup-wrapper";
var scriptEditor = CodeMirror.fromTextArea(document.getElementById("ViewModel_Script"), {
mode: "javascript",
lineNumbers: true
});
var styleEditor = CodeMirror.fromTextArea(document.getElementById("ViewModel_Style"), {
mode: "css",
lineNumbers: true
});
$('.nav-tabs a').on('shown.bs.tab', function () {
scriptEditor.refresh();
styleEditor.refresh();
});
$formUpdate.on('submit', function (e) {
e.preventDefault();
@ -14,6 +29,9 @@ $(function () {
abp.ui.setBusy();
$("#ViewModel_Style").val(styleEditor.getValue());
$("#ViewModel_Script").val(scriptEditor.getValue());
$formUpdate.ajaxSubmit({
success: function (result) {
abp.notify.success(l('SuccessfullySaved'));

3
npm/packs/cms-kit.admin/package.json

@ -8,7 +8,8 @@
"@abp/jstree": "~5.2.0-rc.1",
"@abp/slugify": "~5.2.0-rc.1",
"@abp/tui-editor": "~5.2.0-rc.1",
"@abp/uppy": "~5.2.0-rc.1"
"@abp/uppy": "~5.2.0-rc.1",
"@abp/codemirror": "~5.2.0-rc.1"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
}

5
npm/packs/codemirror/abp.resourcemapping.js

@ -1,5 +1,8 @@
module.exports = {
mappings: {
"@node_modules/codemirror/lib/*.*": "@libs/codemirror/"
"@node_modules/codemirror/lib/*.*": "@libs/codemirror/",
"@node_modules/codemirror/mode/**/*.*": "@libs/codemirror/mode/",
"@node_modules/codemirror/theme/**/*.*": "@libs/codemirror/theme/",
"@node_modules/codemirror/addon/**/*.*": "@libs/codemirror/addon/"
}
}

3
npm/packs/jquery-form/abp.resourcemapping.js

@ -1,6 +1,5 @@
module.exports = {
mappings: {
"@node_modules/jquery-form/dist/jquery.form.min.js": "@libs/jquery-form/",
"@node_modules/jquery-form/dist/jquery.form.min.js.map": "@libs/jquery-form/"
"@node_modules/@abp/jquery-form/src/jquery.form.min.js": "@libs/jquery-form/"
}
}

22
npm/packs/jquery-form/src/jquery.form.min.js

File diff suppressed because one or more lines are too long

4
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server.Mongo/MyCompanyName.MyProjectName.Blazor.Server.Mongo.csproj

@ -7,8 +7,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Blazorise.Bootstrap5" Version="1.0.0" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.0.0" />
<PackageReference Include="Blazorise.Bootstrap5" Version="1.0.1" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.0.1" />
<PackageReference Include="Serilog.AspNetCore" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
</ItemGroup>

4
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj

@ -7,8 +7,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Blazorise.Bootstrap5" Version="1.0.0" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.0.0" />
<PackageReference Include="Blazorise.Bootstrap5" Version="1.0.1" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.0.1" />
<PackageReference Include="Serilog.AspNetCore" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
</ItemGroup>

13
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/_Imports.razor

@ -0,0 +1,13 @@
@using System.Net.Http
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using MyCompanyName.MyProjectName.Blazor.Server
@using Blazorise
@using Blazorise.DataGrid
@using Volo.Abp.BlazoriseUI
@using Volo.Abp.BlazoriseUI.Components

4
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyCompanyName.MyProjectName.Blazor.Server.Tiered.csproj

@ -13,8 +13,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Blazorise.Bootstrap5" Version="1.0.0" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.0.0" />
<PackageReference Include="Blazorise.Bootstrap5" Version="1.0.1" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.0.1" />
<PackageReference Include="Serilog.AspNetCore" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="6.0.0" />

4
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj

@ -13,8 +13,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Blazorise.Bootstrap5" Version="1.0.0" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.0.0" />
<PackageReference Include="Blazorise.Bootstrap5" Version="1.0.1" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.0.1" />
<PackageReference Include="Serilog.AspNetCore" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
</ItemGroup>

4
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj

@ -8,8 +8,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Blazorise.Bootstrap5" Version="1.0.0" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.0.0" />
<PackageReference Include="Blazorise.Bootstrap5" Version="1.0.1" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="6.0.0" />
</ItemGroup>

4
templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj

@ -8,8 +8,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Blazorise.Bootstrap5" Version="1.0.0" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.0.0" />
<PackageReference Include="Blazorise.Bootstrap5" Version="1.0.1" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="6.0.0" />
</ItemGroup>

4
templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyCompanyName.MyProjectName.Blazor.Server.Host.csproj

@ -12,8 +12,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Blazorise.Bootstrap5" Version="1.0.0" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.0.0" />
<PackageReference Include="Blazorise.Bootstrap5" Version="1.0.1" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.0.1" />
<PackageReference Include="Serilog.AspNetCore" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.0" />

Loading…
Cancel
Save