From 66ec1cacd869fcabf22d823aa15d254c62650c16 Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 12 Jul 2021 09:14:32 +0800 Subject: [PATCH 01/15] Switch to the given language if sent in the querystring. Resolve #9384 --- .../AbpRequestLocalizationMiddleware.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs index 06f3922b22..276fb6cb6c 100644 --- a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs @@ -29,6 +29,15 @@ namespace Microsoft.AspNetCore.RequestLocalization _loggerFactory ); + var requestCultureFeature = context.Features.Get(); + if (requestCultureFeature?.Provider is QueryStringRequestCultureProvider) + { + AbpRequestCultureCookieHelper.SetCultureCookie( + context, + requestCultureFeature.RequestCulture + ); + } + await middleware.Invoke(context); } } From c87a34b6f9bb9b3182fc4dfb113100089061fa03 Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 12 Jul 2021 11:10:11 +0800 Subject: [PATCH 02/15] Avoid setting cookies multiple times. --- .../MultiTenancy/MultiTenancyMiddleware.cs | 1 + .../Localization/AbpLanguagesController.cs | 2 ++ .../AbpRequestLocalizationMiddleware.cs | 24 +++++++++++++------ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs index f5541e3b40..f3d21a804b 100644 --- a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs @@ -64,6 +64,7 @@ namespace Volo.Abp.AspNetCore.MultiTenancy context, requestCulture ); + context.Items[AbpRequestLocalizationMiddleware.HttpContextItemName] = true; } await next(context); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpLanguagesController.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpLanguagesController.cs index b0fa63e4f5..f5324656b9 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpLanguagesController.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpLanguagesController.cs @@ -33,6 +33,8 @@ namespace Volo.Abp.AspNetCore.Mvc.Localization new RequestCulture(culture, uiCulture) ); + HttpContext.Items[AbpRequestLocalizationMiddleware.HttpContextItemName] = true; + var context = new QueryStringCultureReplacementContext(HttpContext, new RequestCulture(culture, uiCulture), returnUrl); await QueryStringCultureReplacement.ReplaceAsync(context); diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs index 276fb6cb6c..dad2b240d8 100644 --- a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs @@ -10,6 +10,8 @@ namespace Microsoft.AspNetCore.RequestLocalization { public class AbpRequestLocalizationMiddleware : IMiddleware, ITransientDependency { + public const string HttpContextItemName = "__AbpSetCultureCookie"; + private readonly IAbpRequestLocalizationOptionsProvider _requestLocalizationOptionsProvider; private readonly ILoggerFactory _loggerFactory; @@ -29,14 +31,22 @@ namespace Microsoft.AspNetCore.RequestLocalization _loggerFactory ); - var requestCultureFeature = context.Features.Get(); - if (requestCultureFeature?.Provider is QueryStringRequestCultureProvider) + context.Response.OnStarting(() => { - AbpRequestCultureCookieHelper.SetCultureCookie( - context, - requestCultureFeature.RequestCulture - ); - } + if (context.Items[HttpContextItemName] == null) + { + var requestCultureFeature = context.Features.Get(); + if (requestCultureFeature?.Provider is QueryStringRequestCultureProvider) + { + AbpRequestCultureCookieHelper.SetCultureCookie( + context, + requestCultureFeature.RequestCulture + ); + } + } + + return Task.CompletedTask; + }); await middleware.Invoke(context); } From 271bdd61c0d52310e53d582b9eea3206f9fee91b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ahmet=20=C3=87otur?= Date: Wed, 28 Jul 2021 06:12:23 +0300 Subject: [PATCH 03/15] Update Blazorise packages --- .../src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj b/framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj index f8c8658e5f..dcfe16cce3 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj +++ b/framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj @@ -14,10 +14,10 @@ - - - - + + + + From 318eea9e1473516b49ebb7ffd9f1558b979ccdfb Mon Sep 17 00:00:00 2001 From: enisn Date: Wed, 28 Jul 2021 09:56:26 +0300 Subject: [PATCH 04/15] Add CmsKit Menus documentation --- docs/en/Modules/Cms-Kit/Index.md | 1 + docs/en/Modules/Cms-Kit/Menus.md | 88 ++++++++++++++++++ docs/en/images/cmskit-module-menus-page.png | Bin 0 -> 18205 bytes docs/en/images/cmskit-module-menus-public.png | Bin 0 -> 12540 bytes 4 files changed, 89 insertions(+) create mode 100644 docs/en/Modules/Cms-Kit/Menus.md create mode 100644 docs/en/images/cmskit-module-menus-page.png create mode 100644 docs/en/images/cmskit-module-menus-public.png diff --git a/docs/en/Modules/Cms-Kit/Index.md b/docs/en/Modules/Cms-Kit/Index.md index fbdc37ec18..eb08a0c53c 100644 --- a/docs/en/Modules/Cms-Kit/Index.md +++ b/docs/en/Modules/Cms-Kit/Index.md @@ -12,6 +12,7 @@ The following features are currently available: * Provides a [**comment**](Comments.md) system to add comments feature to any kind of resource, like blog post or a product review page. * Provides a [**reaction**](Reactions.md) system to add reactions (smileys) feature to any kind of resource, like a blog post or a comment. * Provides a [**rating**](Ratings.md) system to add rating feature to any kind of resource. +* Provides a [**menu**](Menus.md) system to manage public menus dynamically. Click to a feature to understand and learn how to use it. diff --git a/docs/en/Modules/Cms-Kit/Menus.md b/docs/en/Modules/Cms-Kit/Menus.md new file mode 100644 index 0000000000..87486326da --- /dev/null +++ b/docs/en/Modules/Cms-Kit/Menus.md @@ -0,0 +1,88 @@ +# CMS Kit: Pages + +CMS Kit Menu system allows to manage public menus dynamically. + +## The User Interface + +### Menu items + +CMS Kit module admin side adds the following items to the main menu, under the *CMS* menu item: + +* **Menus**: Menu management page. + +`CmsKitAdminMenus` class has the constants for the menu item names. + +### Menus + +#### Menu Management + +Menus page is used to manage dynamic public menus in the system. + +![cms-kit-menus-page](../../images/cmskit-module-menus-page.png) + + + +Created menus will be visible on public site. + +![cms-kit-public-menus](../../images//cmskit-module-menus-public.png) + +# Internals + +## Domain Layer + +#### Aggregates + +This module follows the [Entity Best Practices & Conventions](https://docs.abp.io/en/abp/latest/Best-Practices/Entities) guide. + +##### Menus + +- `MenuItem` (aggregate root): A Menu Item presents a single node at menu tree. + +#### Repositories + +This module follows the [Repository Best Practices & Conventions](https://docs.abp.io/en/abp/latest/Best-Practices/Repositories) guide. + +Following custom repositories are defined for this feature: + +- `IMenuItemRepository` + +#### Domain services + +This module follows the [Domain Services Best Practices & Conventions](https://docs.abp.io/en/abp/latest/Best-Practices/Domain-Services) guide. + +##### Menu Item Manager + +`MenuItemManager` is used to perform some operations for the `MenuItemManager` aggregate root. + +### Application layer + +#### Application services + +- `MenuItemAdminAppService` (implements `IMenuItemAdminAppService`): Implements the management operations of menu system. +- `MenuItemPublicAppService` (implements `IMenuItemPublicAppService`): Implements the public use cases of menu system. + +### Database providers + +#### Common + +##### Table / collection prefix & schema + +All tables/collections use the `Cms` prefix by default. Set static properties on the `CmsKitDbProperties` class if you need to change the table prefix or set a schema name (if supported by your database provider). + +##### Connection string + +This module uses `CmsKit` for the connection string name. If you don't define a connection string with this name, it fallbacks to the `Default` connection string. + +See the [connection strings](https://docs.abp.io/en/abp/latest/Connection-Strings) documentation for details. + +#### Entity Framework Core + +##### Tables + +- CmsMenuItems + +#### MongoDB + +##### Collections + +- CmsMenuItems \ No newline at end of file diff --git a/docs/en/images/cmskit-module-menus-page.png b/docs/en/images/cmskit-module-menus-page.png new file mode 100644 index 0000000000000000000000000000000000000000..c2657637880230eb512a62d2657b6ce7f2ad7f90 GIT binary patch literal 18205 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

-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 hmjN1F1ph|~F${A1f*`|&QSugBFznyp|J$ Date: Wed, 28 Jul 2021 10:41:55 +0300 Subject: [PATCH 05/15] docs: add basic theme document for Angular UI --- docs/en/UI/Angular/Basic-Theme.md | 107 ++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 docs/en/UI/Angular/Basic-Theme.md diff --git a/docs/en/UI/Angular/Basic-Theme.md b/docs/en/UI/Angular/Basic-Theme.md new file mode 100644 index 0000000000..7b6c98fdcc --- /dev/null +++ b/docs/en/UI/Angular/Basic-Theme.md @@ -0,0 +1,107 @@ +# Angular UI: Basic Theme + +The Basic Theme is a theme implementation for the Angular UI. It is a minimalist theme that doesn't add any styling on top of the plain [Bootstrap](https://getbootstrap.com/). You can take the Basic Theme as the **base theme** and build your own theme or styling on top of it. See the *Customization* section. + +> If you are looking for a professional, enterprise ready theme, you can check the [Lepton Theme](https://commercial.abp.io/themes), which is a part of the [ABP Commercial](https://commercial.abp.io/). + +> See the [Theming document](Theming.md) to learn about themes. + +## Installation + +**This theme is already installed** when you create a new solution using the [startup templates](../../Startup-Templates/Index.md). If you need to manually install it, follow the steps below: + +* Install the [@abp/ng.theme.basic](https://www.npmjs.com/package/@abp/ng.theme.basic) NPM package to your Angular project. +* Open the `src/app/app.module.ts` file, import `ThemeBasicModule` (it can be imported from `@abp/ng.theme.basic` package), and add `ThemeBasicModule.forRoot()` to the `imports` array. +* Open the `src/app/shared/shared.module` file, import `ThemeBasicModule` (it can be imported from `@abp/ng.theme.basic` package), and add `ThemeBasicModule` to the `imports` and `exports` array. + +The `ThemeBasicModule` is registered own layouts (`ApplicationLayoutComponent`, `AccountLayoutComponent`, `EmptyLayoutComponent`) to a service which is exposed by `@abp/ng.core` package on application initialization. + +## Application Layout + +![basic-theme-application-layout](../../images/basic-theme-application-layout.png) + +Application Layout implements the following parts, in addition to the common parts mentioned above; + +* Logo area +* Routes area +* Language selection & user menu +* [Page Alerts](Page-Alerts.md) + +See Application Layout components: + +![application layout components](./images/layout-components.png) + +### How to Use a Layout + +Routes should be added to the menu by calling `add` method `RoutesService`. A layout can be set in the object of your route. See the [modifying the menu](Modifying-the-Menu#how-to-add-a-navigation-element) for more information. + +## Customization + +You have two options two customize this theme: + +### Overriding Styles / Components + +In this approach, you continue to use the theme as an NPM package and customize the parts you need to. There are several ways to customize it; + +#### Override the Styles + +You can simply override the styles in the global styles (`src/styles.scss`) file of your application. + +#### Override the Components + +See the [Component Replacement](Component-Replacement.md) to learn how you can replace components, customize and extend the user interface. + +### Copy & Customize + +You can run the following [ABP CLI](../../CLI.md) command in **Angular** project directory to copy the source code to your solution: + +`abp add-package @abp/ng.theme.basic --with-source-code` + +---- + +Or, you can download the [source code](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/theme-basic) of the Basic Theme, manually copy the project content into your project (`projects/theme-basic` folder), open `angular.json` file and add configuration below to the `projects` object: + +```json +{ + "projects": { + ... + "theme-basic": { + "projectType": "library", + "root": "projects/theme-basic", + "sourceRoot": "projects/theme-basic/src", + "prefix": "abp", + "architect": { + "build": { + "builder": "@angular-devkit/build-ng-packagr:build", + "options": { + "tsConfig": "projects/theme-basic/tsconfig.lib.json", + "project": "projects/theme-basic/ng-package.json" + }, + "configurations": { + "production": { + "tsConfig": "projects/theme-basic/tsconfig.lib.prod.json" + } + } + } + } + } + } +} +``` + +Then, open the `tsconfig.json` file and add new paths as follows: + +```json +"paths": { + ... + "@abp/ng.theme.basic": ["projects/theme-basic/src/public-api.ts"], + "@abp/ng.theme.basic/testing": ["projects/theme-basic/testing/src/public-api.ts"] +} +``` + + +You can now freely customize the theme based on your application requirements. + +## See Also + +* [Theming](Theming.md) From 0ae7df7da275b854307907acefbbc6624320da09 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Wed, 28 Jul 2021 10:42:10 +0300 Subject: [PATCH 06/15] docs: add theming document for Angular UI --- docs/en/UI/Angular/Theming.md | 228 ++++++++++++++++++ .../basic-theme-application-layout-parts.png | Bin 0 -> 45699 bytes 2 files changed, 228 insertions(+) create mode 100644 docs/en/UI/Angular/Theming.md create mode 100644 docs/en/UI/Angular/images/basic-theme-application-layout-parts.png diff --git a/docs/en/UI/Angular/Theming.md b/docs/en/UI/Angular/Theming.md new file mode 100644 index 0000000000..21e28953f8 --- /dev/null +++ b/docs/en/UI/Angular/Theming.md @@ -0,0 +1,228 @@ +# Angular UI: Theming + +## Introduction + +ABP Framework provides a complete **UI Theming** system with the following goals: + +* Reusable [application modules](../../Modules/Index.md) are developed **theme-independent**, so they can work with any UI theme. +* UI theme is **decided by the final application**. +* The theme is distributed via an NPM package, so it is **easily upgradable**. +* The final application can **customize** the selected theme. + +In order to accomplish these goals, ABP Framework; + +* Determines a set of **base libraries** used and adapted by all the themes. So, module and application developers can depend on and use these libraries without depending on a particular theme. +* Provides a system that consists of layout parts (like navigation menus and toolbars) that is implemented by all the themes. So, the modules and the application contribute to the layout to compose a consistent application UI. + +### Current Themes + +Currently, two themes are **officially provided**: + +* The [Basic Theme](Basic-Theme.md) is the minimalist theme with the plain Bootstrap style. It is **open source and free**. +* The [Lepton Theme](https://commercial.abp.io/themes) is a **commercial** theme developed by the core ABP team and is a part of the [ABP Commercial](https://commercial.abp.io/) license. + +## Overall + +### The Base Libraries + +All the themes must depend on the [@abp/ng.theme.shared](https://www.npmjs.com/package/@abp/ng.theme.shared) NuGet package, so they are indirectly depending on the following libraries: + +* [Twitter Bootstrap](https://getbootstrap.com/) as the fundamental HTML/CSS framework. +* [FontAwesome](https://fontawesome.com/) as the fundamental CSS font library. +* [NG Bootstrap](https://ng-bootstrap.github.io/#/home) as a component library that supports the Bootstrap and adds extra components like modal and datepicker. +* [Ngx-Datatable](https://swimlane.gitbook.io/ngx-datatable/) as a datatable library. +* [ngx-validate](https://github.com/ng-turkey/ngx-validate) a dynamic validation of reactive forms library. +* [Chart.js](https://www.chartjs.org/) as a widget library. + +These libraries are selected as the base libraries and available to the applications and modules. + +> Bootstrap's JavaScript part is not used since the NG Bootstrap library already provides the necessary functionalities to the Bootstrap components in a native way. + +### The Layout + +All themes must define a layout for the application. The following image shows the user management page in the [Basic Theme](Basic-Theme.md) application layout: + +![basic-theme-application-layout](../../images/basic-theme-application-layout.png) + +And the same page is shown below with the [Lepton Theme](https://commercial.abp.io/themes) application layout: + +![lepton-theme-application-layout](../../images/lepton-theme-application-layout.png) + +As you can see, the page is the same, but the look is completely different in the themes above. + +The application layout typically includes the following parts; + +* Main menu +* Nav items area with the following components; + * User menu + * Language switch dropdown +* [Page alerts](Page-Alerts.md) +* The page content (aka ``) + +## Implementing a Theme + +A theme is simply an NPM package and comes with startup templates. + +### The Easy Way + +The easiest way to create a new theme is to add Basic Theme Source Code to your project via [ABP CLI](../../CLI.md) command and customize it. + +You can run the following command in **Angular** project directory to copy the source code to your solution: + +`abp add-package @abp/ng.theme.basic --with-source-code` + +### Global/Component Styles + +Angular can bundle global style files and component styles with components. +See the [component styles](https://angular.io/guide/component-styles) guide on Angular documentation for more information. + +### Layout Parts + +A typical layout consists of several parts. The theme should include the necessary parts in each layout. + +**Example: The Basic Theme has the following parts for the Application Layout** + +![basic-theme-application-layout-parts](images/basic-theme-application-layout-parts.png) + +The application code and the modules can only show contents in the Page Content part. If they need to change the other parts (to add a menu item, to add a nav item, to change the application name in the logo area...) they should use the ABP Framework APIs. + +The following sections explain the fundamental parts pre-defined by the ABP Framework and can be implemented by the themes. + +> It is a good practice to split the layout into components/partials, so the final application can override them partially for customization purpose. + +#### Logo + +The `application` object of an environment file should be configured to get the name and the logo URL of the application to render in the logo part. Additionally, `LogoComponent` can be replaced. See [Component Replacement](Component-Replacement.md) document for more. + +The [Application Startup Template](../../Startup-Templates/Application.md) has an implementation of this interface to set the values by the application developer. + +#### Main Menu / Routes + +`RoutesService` service is used to manage the main menu items and render them on the layout. + +**Example: Adding a route to the main menu** + +```ts +import { RoutesService, eLayoutType } from '@abp/ng.core'; +import { Component } from '@angular/core'; + +@Component(/* component metadata */) +export class AppComponent { + constructor(routes: RoutesService) { + routes.add([ + { + path: '/your-path', + name: 'Your navigation', + order: 101, + iconClass: 'fas fa-question-circle', + requiredPolicy: 'permission key here', + layout: eLayoutType.application, + }, + { + path: '/your-path/child', + name: 'Your child navigation', + parentName: 'Your navigation', + order: 1, + requiredPolicy: 'permission key here', + }, + ]); + } +} +``` + +See the [Modifying the Menu](Modifying-the-Menu.md) document to learn more about the navigation system. + +#### Toolbar / Nav Items + +`NavItemsService` service is used to get the menu's right part items and render on the layout. You can add an HTML content or Angular component as an element to render. + +**Example: Adding an element to right part of the menu** + +````ts +import { NavItemsService } from '@abp/ng.theme.shared'; +import { Component } from '@angular/core'; + +@Component({ + template: ` + + `, +}) +export class MySearchInputComponent {} + + +@Component(/* component metadata */) +export class AppComponent { + constructor(private navItems: NavItemsService) { + navItems.addItems([ + { + id: 'MySearchInput', + order: 1, + component: MySearchInputComponent, + }, + { + id: 'SignOutIcon', + html: '', + action: () => console.log('Clicked the sign out icon'), + order: 101, // puts as last element + }, + ]); + } +} +```` + +> See the [How to Add an Element to Right Part of the Menu](Modifying-the-Menu#how-to-add-an-element-to-right-part-of-the-menu) document to learn more on the nav items system. + +The theme has a responsibility to add two pre-defined items to the toolbar: Language Selection and User Menu. + +##### Language Selection + +Language Selection toolbar item is generally a dropdown that is used to switch between languages. `ConfigStateService` is used to get the list of available languages and `SessionStateService` is used to learn the current language. + +`SessionStateService` is used to get and set the current language. + +**Example: Get the currently selected language** + +````ts +import {SessionStateService} from '@abp/ng.core'; + +//... + +constructor(private sessionState: SessionStateService) { + const lang = this.sessionState.getLanguage() +} +```` + +**Example: Set the selected language** + +````ts +import {SessionStateService} from '@abp/ng.core'; + +//... + +constructor(private sessionState: SessionStateService) { + const lang = this.sessionState.setLanguage('en') +} +```` + +##### User Menu + +User menu is a component that can be replaceable. See an example to learn how can you replace it: + +````ts +import { eThemeBasicComponents } from '@abp/ng.theme.basic'; +import { NavItemsService } from '@abp/ng.theme.shared'; +import { Component } from '@angular/core'; + +@Component({/* component metadata */}) +export class AppComponent { + constructor(private navItems: NavItemsService) { + this.navItems.patchItem(eThemeBasicComponents.CurrentUser, { component: MyUserMenuComponent }); + } +} +```` + +[`ConfigStateService`](Config-State-Service.md) service can be used to obtain the `application-configuration` API response (e.g. getting current user or tenant). + +#### Page Alerts + +`PageAlertService` service is used to get the current page alerts to render on the layout. See the [Page Alerts](Page-Alerts.md) document to learn more. \ No newline at end of file diff --git a/docs/en/UI/Angular/images/basic-theme-application-layout-parts.png b/docs/en/UI/Angular/images/basic-theme-application-layout-parts.png new file mode 100644 index 0000000000000000000000000000000000000000..934b0e052833e0988801bbaa716c83898ec3816d GIT binary patch literal 45699 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 AssI20 literal 0 HcmV?d00001 From b00ccc80c15e34061c6cf6aaba22e7e75066121c Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Wed, 28 Jul 2021 10:43:16 +0300 Subject: [PATCH 07/15] docs: remove a word --- docs/en/UI/Blazor/Basic-Theme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/UI/Blazor/Basic-Theme.md b/docs/en/UI/Blazor/Basic-Theme.md index 6a71e50c84..2c034f258a 100644 --- a/docs/en/UI/Blazor/Basic-Theme.md +++ b/docs/en/UI/Blazor/Basic-Theme.md @@ -38,7 +38,7 @@ You have two options two customize this theme: ### Overriding Styles / Components -In this approach, you continue to use the the theme as NuGet and NPM packages and customize the parts you need to. There are several ways to customize it; +In this approach, you continue to use the theme as NuGet and NPM packages and customize the parts you need to. There are several ways to customize it; #### Override the Styles From 846d30ccf83179f2d6601176b94a0931f040e826 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Wed, 28 Jul 2021 15:52:14 +0800 Subject: [PATCH 08/15] Allowed to override CancellationToken for a specific call --- framework/Volo.Abp.sln | 7 +++ .../HttpContextCancellationTokenProvider.cs | 21 +++++-- .../Threading/CancellationTokenOverride.cs | 14 +++++ .../CancellationTokenProviderBase.cs | 26 ++++++++ .../Threading/ICancellationTokenProvider.cs | 4 +- .../NullCancellationTokenProvider.cs | 8 +-- .../Volo.Abp.Threading.Tests.csproj | 16 +++++ .../Abp/Threading/AbpThreadingTestModule.cs | 15 +++++ .../NullCancellationTokenProvider_Tests.cs | 60 +++++++++++++++++++ 9 files changed, 162 insertions(+), 9 deletions(-) create mode 100644 framework/src/Volo.Abp.Threading/Volo/Abp/Threading/CancellationTokenOverride.cs create mode 100644 framework/src/Volo.Abp.Threading/Volo/Abp/Threading/CancellationTokenProviderBase.cs create mode 100644 framework/test/Volo.Abp.Threading.Tests/Volo.Abp.Threading.Tests.csproj create mode 100644 framework/test/Volo.Abp.Threading.Tests/Volo/Abp/Threading/AbpThreadingTestModule.cs create mode 100644 framework/test/Volo.Abp.Threading.Tests/Volo/Abp/Threading/NullCancellationTokenProvider_Tests.cs diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index 0605f5c103..8d5432f4c6 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -383,6 +383,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.TextTemplating.Scr EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.MongoDB.Tests.SecondContext", "test\Volo.Abp.MongoDB.Tests.SecondContext\Volo.Abp.MongoDB.Tests.SecondContext.csproj", "{90B1866A-EF99-40B9-970E-B898E5AA523F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Threading.Tests", "test\Volo.Abp.Threading.Tests\Volo.Abp.Threading.Tests.csproj", "{7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1141,6 +1143,10 @@ Global {90B1866A-EF99-40B9-970E-B898E5AA523F}.Debug|Any CPU.Build.0 = Debug|Any CPU {90B1866A-EF99-40B9-970E-B898E5AA523F}.Release|Any CPU.ActiveCfg = Release|Any CPU {90B1866A-EF99-40B9-970E-B898E5AA523F}.Release|Any CPU.Build.0 = Release|Any CPU + {7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1334,6 +1340,7 @@ Global {C996F458-98FB-483D-9306-4701290E2FC1} = {447C8A77-E5F0-4538-8687-7383196D04EA} {75D8DADB-3FA9-4C1D-B23A-DBFD08133B7C} = {447C8A77-E5F0-4538-8687-7383196D04EA} {90B1866A-EF99-40B9-970E-B898E5AA523F} = {447C8A77-E5F0-4538-8687-7383196D04EA} + {7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B} = {447C8A77-E5F0-4538-8687-7383196D04EA} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Threading/HttpContextCancellationTokenProvider.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Threading/HttpContextCancellationTokenProvider.cs index c7c961176c..ce722b1176 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Threading/HttpContextCancellationTokenProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Threading/HttpContextCancellationTokenProvider.cs @@ -6,13 +6,26 @@ using Volo.Abp.Threading; namespace Volo.Abp.AspNetCore.Threading { [Dependency(ReplaceServices = true)] - public class HttpContextCancellationTokenProvider : ICancellationTokenProvider, ITransientDependency + public class HttpContextCancellationTokenProvider : CancellationTokenProviderBase, ITransientDependency { - public CancellationToken Token => _httpContextAccessor.HttpContext?.RequestAborted ?? CancellationToken.None; - private readonly IHttpContextAccessor _httpContextAccessor; - public HttpContextCancellationTokenProvider(IHttpContextAccessor httpContextAccessor) + public override CancellationToken Token + { + get + { + if (OverrideValue != null) + { + return OverrideValue.CancellationToken; + } + return _httpContextAccessor.HttpContext?.RequestAborted ?? CancellationToken.None; + } + } + + public HttpContextCancellationTokenProvider( + IAmbientScopeProvider cancellationTokenOverrideScopeProvider, + IHttpContextAccessor httpContextAccessor) + : base(cancellationTokenOverrideScopeProvider) { _httpContextAccessor = httpContextAccessor; } diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/CancellationTokenOverride.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/CancellationTokenOverride.cs new file mode 100644 index 0000000000..371e3d6652 --- /dev/null +++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/CancellationTokenOverride.cs @@ -0,0 +1,14 @@ +using System.Threading; + +namespace Volo.Abp.Threading +{ + public class CancellationTokenOverride + { + public CancellationToken CancellationToken { get; } + + public CancellationTokenOverride(CancellationToken cancellationToken) + { + CancellationToken = cancellationToken; + } + } +} diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/CancellationTokenProviderBase.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/CancellationTokenProviderBase.cs new file mode 100644 index 0000000000..20101a95da --- /dev/null +++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/CancellationTokenProviderBase.cs @@ -0,0 +1,26 @@ +using System; +using System.Threading; + +namespace Volo.Abp.Threading +{ + public abstract class CancellationTokenProviderBase : ICancellationTokenProvider + { + public const string CancellationTokenOverrideContextKey = "Volo.Abp.Threading.CancellationToken.Override"; + + public abstract CancellationToken Token { get; } + + protected IAmbientScopeProvider CancellationTokenOverrideScopeProvider { get; } + + protected CancellationTokenOverride OverrideValue => CancellationTokenOverrideScopeProvider.GetValue(CancellationTokenOverrideContextKey); + + protected CancellationTokenProviderBase(IAmbientScopeProvider cancellationTokenOverrideScopeProvider) + { + CancellationTokenOverrideScopeProvider = cancellationTokenOverrideScopeProvider; + } + + public IDisposable Use(CancellationToken cancellationToken) + { + return CancellationTokenOverrideScopeProvider.BeginScope(CancellationTokenOverrideContextKey, new CancellationTokenOverride(cancellationToken)); + } + } +} diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/ICancellationTokenProvider.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/ICancellationTokenProvider.cs index 24e303adde..c270eeddd2 100644 --- a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/ICancellationTokenProvider.cs +++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/ICancellationTokenProvider.cs @@ -1,9 +1,11 @@ -using System.Threading; +using System; +using System.Threading; namespace Volo.Abp.Threading { public interface ICancellationTokenProvider { CancellationToken Token { get; } + IDisposable Use(CancellationToken cancellationToken); } } diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/NullCancellationTokenProvider.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/NullCancellationTokenProvider.cs index ab6320546c..6c2b4d364c 100644 --- a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/NullCancellationTokenProvider.cs +++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/NullCancellationTokenProvider.cs @@ -2,15 +2,15 @@ namespace Volo.Abp.Threading { - public class NullCancellationTokenProvider : ICancellationTokenProvider + public class NullCancellationTokenProvider : CancellationTokenProviderBase { public static NullCancellationTokenProvider Instance { get; } = new NullCancellationTokenProvider(); - public CancellationToken Token { get; } = CancellationToken.None; + public override CancellationToken Token => OverrideValue?.CancellationToken ?? CancellationToken.None; private NullCancellationTokenProvider() + : base(new AmbientDataContextAmbientScopeProvider(new AsyncLocalAmbientDataContext())) { - } } -} \ No newline at end of file +} diff --git a/framework/test/Volo.Abp.Threading.Tests/Volo.Abp.Threading.Tests.csproj b/framework/test/Volo.Abp.Threading.Tests/Volo.Abp.Threading.Tests.csproj new file mode 100644 index 0000000000..cbca0b1329 --- /dev/null +++ b/framework/test/Volo.Abp.Threading.Tests/Volo.Abp.Threading.Tests.csproj @@ -0,0 +1,16 @@ + + + + + + net5.0 + + + + + + + + + + diff --git a/framework/test/Volo.Abp.Threading.Tests/Volo/Abp/Threading/AbpThreadingTestModule.cs b/framework/test/Volo.Abp.Threading.Tests/Volo/Abp/Threading/AbpThreadingTestModule.cs new file mode 100644 index 0000000000..de530512d3 --- /dev/null +++ b/framework/test/Volo.Abp.Threading.Tests/Volo/Abp/Threading/AbpThreadingTestModule.cs @@ -0,0 +1,15 @@ +using Volo.Abp.Modularity; + +namespace Volo.Abp.Threading +{ + [DependsOn( + typeof(AbpThreadingModule), + typeof(AbpTestBaseModule) + )] + public class AbpThreadingTestModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + } + } +} diff --git a/framework/test/Volo.Abp.Threading.Tests/Volo/Abp/Threading/NullCancellationTokenProvider_Tests.cs b/framework/test/Volo.Abp.Threading.Tests/Volo/Abp/Threading/NullCancellationTokenProvider_Tests.cs new file mode 100644 index 0000000000..24bc57dac7 --- /dev/null +++ b/framework/test/Volo.Abp.Threading.Tests/Volo/Abp/Threading/NullCancellationTokenProvider_Tests.cs @@ -0,0 +1,60 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Testing; +using Xunit; + +namespace Volo.Abp.Threading +{ + public class NullCancellationTokenProvider_Tests : AbpIntegratedTest + { + private readonly ICancellationTokenProvider _cancellationTokenProvider; + + public NullCancellationTokenProvider_Tests() + { + _cancellationTokenProvider = NullCancellationTokenProvider.Instance; + } + + [Fact] + public void Should_Return_None_Token() + { + _cancellationTokenProvider.Token.ShouldBe(CancellationToken.None); + } + + [Fact] + public void Should_Return_Specific_Token() + { + var cts = new CancellationTokenSource(); + + using (_cancellationTokenProvider.Use(cts.Token)) + { + _cancellationTokenProvider.Token.ShouldBe(cts.Token); + } + + _cancellationTokenProvider.Token.ShouldBe(CancellationToken.None); + } + + [Fact] + public void Should_Cancel_After_100_Milliseconds() + { + var cts = new CancellationTokenSource(); + cts.CancelAfter(TimeSpan.FromMilliseconds(100)); + + using (_cancellationTokenProvider.Use(cts.Token)) + { + Should.Throw(() => LongTask(1000, _cancellationTokenProvider.Token)); + } + } + + private void LongTask(int loopCounter, CancellationToken cancellationToken = default) + { + for (var i = 0; i < loopCounter; i++) + { + cancellationToken.ThrowIfCancellationRequested(); + + Thread.Sleep(10); + } + } + } +} From 34da6c2a45f2272ee3fef15242f3857d1e793247 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Wed, 28 Jul 2021 11:06:06 +0300 Subject: [PATCH 09/15] docs: add angular/theming to the menu --- docs/en/docs-nav.json | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index c946b8401c..5a2b18d365 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -365,8 +365,8 @@ "path": "Object-To-Object-Mapping.md" }, { - "text":"String Encryption", - "path":"String-Encryption.md" + "text": "String Encryption", + "path": "String-Encryption.md" }, { "text": "Text Templating", @@ -1025,6 +1025,19 @@ "text": "Customization Guide", "path": "UI/Angular/Customization-User-Interface.md" }, + { + "text": "Theming", + "items": [ + { + "text": "Overall", + "path": "UI/Angular/Theming.md" + }, + { + "text": "The Basic Theme", + "path": "UI/Angular/Basic-Theme.md" + } + ] + }, { "text": "Modifying the Menu", "path": "UI/Angular/Modifying-the-Menu.md" From 121280829d73705294ddceec28e024c73ad792f7 Mon Sep 17 00:00:00 2001 From: maliming Date: Wed, 28 Jul 2021 16:33:13 +0800 Subject: [PATCH 10/15] Update ICancellationTokenProvider.cs --- .../Volo/Abp/Threading/ICancellationTokenProvider.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/ICancellationTokenProvider.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/ICancellationTokenProvider.cs index c270eeddd2..06dc008d52 100644 --- a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/ICancellationTokenProvider.cs +++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/ICancellationTokenProvider.cs @@ -6,6 +6,7 @@ namespace Volo.Abp.Threading public interface ICancellationTokenProvider { CancellationToken Token { get; } + IDisposable Use(CancellationToken cancellationToken); } } From 76954740f5501b77e379d8370937eae2e17ff7d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 28 Jul 2021 13:55:33 +0300 Subject: [PATCH 12/15] Fix the language list. --- .../MyProjectNameIdentityServerModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs index 0829a70a7e..beab7c5132 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs @@ -119,7 +119,7 @@ namespace MyCompanyName.MyProjectName options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文")); options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch")); - options.Languages.Add(new LanguageInfo("es", "es", "Español"s)); + options.Languages.Add(new LanguageInfo("es", "es", "Español")); }); Configure(options => From 24e886badc5d1dee9890f81d31938c6ecff9dffa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ahmet=20=C3=87otur?= Date: Wed, 28 Jul 2021 14:06:30 +0300 Subject: [PATCH 13/15] update blazorize packages for app template --- .../MyCompanyName.MyProjectName.Blazor.Server.Tiered.csproj | 4 ++-- .../MyCompanyName.MyProjectName.Blazor.Server.csproj | 4 ++-- .../MyCompanyName.MyProjectName.Blazor.csproj | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyCompanyName.MyProjectName.Blazor.Server.Tiered.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyCompanyName.MyProjectName.Blazor.Server.Tiered.csproj index 1c88aabcd5..aa0170cca4 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyCompanyName.MyProjectName.Blazor.Server.Tiered.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyCompanyName.MyProjectName.Blazor.Server.Tiered.csproj @@ -14,8 +14,8 @@ - - + + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj index 362a1068f2..b83e86df6f 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj @@ -14,8 +14,8 @@ - - + + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj index 74e8f8ca07..0bde45f899 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj @@ -10,8 +10,8 @@ - - + + From a1f1fe98fe19d1d8784fc01eaa495f1493a26e23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ahmet=20=C3=87otur?= Date: Wed, 28 Jul 2021 14:29:20 +0300 Subject: [PATCH 14/15] update blazorise packages for module template --- .../MyCompanyName.MyProjectName.Blazor.Host.csproj | 4 ++-- .../MyCompanyName.MyProjectName.Blazor.Server.Host.csproj | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj index 9beaac9818..6adc30e7f6 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj @@ -8,8 +8,8 @@ - - + + diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyCompanyName.MyProjectName.Blazor.Server.Host.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyCompanyName.MyProjectName.Blazor.Server.Host.csproj index 923814f92b..098b542d4f 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyCompanyName.MyProjectName.Blazor.Server.Host.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyCompanyName.MyProjectName.Blazor.Server.Host.csproj @@ -13,8 +13,8 @@ - - + + From d9aab07b928b32381ce92f0ff167918b0f697d2c Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Wed, 28 Jul 2021 21:04:34 +0800 Subject: [PATCH 15/15] Update NullCancellationTokenProvider_Tests.cs --- .../Abp/Threading/NullCancellationTokenProvider_Tests.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/framework/test/Volo.Abp.Threading.Tests/Volo/Abp/Threading/NullCancellationTokenProvider_Tests.cs b/framework/test/Volo.Abp.Threading.Tests/Volo/Abp/Threading/NullCancellationTokenProvider_Tests.cs index 24bc57dac7..34c5988eb1 100644 --- a/framework/test/Volo.Abp.Threading.Tests/Volo/Abp/Threading/NullCancellationTokenProvider_Tests.cs +++ b/framework/test/Volo.Abp.Threading.Tests/Volo/Abp/Threading/NullCancellationTokenProvider_Tests.cs @@ -29,7 +29,9 @@ namespace Volo.Abp.Threading using (_cancellationTokenProvider.Use(cts.Token)) { - _cancellationTokenProvider.Token.ShouldBe(cts.Token); + var newCancellationTokenProvider = NullCancellationTokenProvider.Instance; + + newCancellationTokenProvider.Token.ShouldBe(cts.Token); } _cancellationTokenProvider.Token.ShouldBe(CancellationToken.None); @@ -43,7 +45,8 @@ namespace Volo.Abp.Threading using (_cancellationTokenProvider.Use(cts.Token)) { - Should.Throw(() => LongTask(1000, _cancellationTokenProvider.Token)); + var newCancellationTokenProvider = NullCancellationTokenProvider.Instance; + Should.Throw(() => LongTask(1000, newCancellationTokenProvider.Token)); } }