diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json index 5ebdf0b2eb..cb79af1665 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json @@ -81,6 +81,7 @@ "LastSeenDate": "Last seen date", "{0}Computer{1}WillBeRemovedFromRecords": "Computer of {0} ({1}) will be removed from records", "OrganizationDeletionWarningMessage": "Organization will be deleted", + "DeletingLastOwnerWarningMessage": "An organization must have at least one owner! Therefore you cannot remove this owner", "This{0}AlreadyExistInThisOrganization": "This {0} already exist in this organization", "AreYouSureYouWantToDeleteAllComputers": "Are you sure you want to delete all computers?", "DeleteAll": "Delete all", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index 3df70437b4..2a57c6b25d 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -29,7 +29,7 @@ "ApiKey": "API key", "UserNameNotFound": "There is no user with username {0}", "SuccessfullyAddedToNewsletter": "Thanks you for subscribing to our newsletter!", - "ManageProfile": "Manage your profile", + "MyProfile": "My profile", "EmailNotValid": "Please enter a valid email address." } } \ No newline at end of file diff --git a/docs/en/Blog-Posts/2020-03-19 v2_3_Release/Post.md b/docs/en/Blog-Posts/2020-03-19 v2_3_Release/Post.md new file mode 100644 index 0000000000..dd081f38e5 --- /dev/null +++ b/docs/en/Blog-Posts/2020-03-19 v2_3_Release/Post.md @@ -0,0 +1,142 @@ +# ABP Framework v2.3.0 Has Been Released! + +In the days of **coronavirus**, we have released **ABP Framework v2.3** and this post will explain **what's new** with this release and **what we've done** in the last two weeks. + +## About the Coronavirus & Our Team + +**We are very sad** about the coronavirus case. As [Volosoft](https://volosoft.com/) team, we have **remote workers** working in their home in different countries. Beginning from the last week, we've **completely started to work remotely** from home including our main office employees. + +We believe in and pray for that the humanity will overcome this issue in a short time. + +## About the Release Cycle + +Beginning from the ABP v2.1.0, we have started to release feature versions once **in two weeks**, on Thursdays. This is the 3rd release after that decision and we see that it works fine for now and improved our agility. + +We will continue to release **feature versions** (like v2.4, v2.5) in every two weeks. In addition, we may release **hotfix versions** (like v2.3.1, v2.3.2) whenever needed. + +## What's New in ABP Framework v2.3.0 + +We've completed & merged **[104](https://github.com/abpframework/abp/milestone/30?closed=1) issues and pull requests** with **393 commits** in this two weeks development period. + +I will introduce some new features and enhancements introduced with this release. + +### React Native Mobile Application + +We have finally completed the **react native mobile application**. It currently allows you to **login**, manage your **users** and **tenants**. It utilizes the same setting, authorization and localization systems of the ABP Framework. + +A few screenshots from the application: + +![mobile-ui](react-native-ui.png) + +It doesn't have much functionality but it is a **perfect starting point** for your own mobile application since it is completely integrated to the backend and supports multi-tenancy. + +### Angular TypeScript Proxy Generator + +It is common to call a REST endpoint in the server from our Angular applications. In this case, we generally create **services** (those have methods for each service method on he server side) and **model objects** (matches to [DTOs](https://docs.abp.io/en/abp/latest/Data-Transfer-Objects) in the server side). + +In addition to manually creating such server-interacting services, we could use tools like [NSWAG](https://github.com/RicoSuter/NSwag) to generate service proxies for us. But NSWAG has the following problems we've experienced: + +* It generates a **big, single** .ts file which has some problems; + * It get **too large** when your application grows. + * It doesn't fit into the **[modular](https://docs.abp.io/en/abp/latest/Module-Development-Basics) approach** of the ABP framework. +* It creates a bit **ugly code**. We want to have a clean code (just like if we write manually). +* It can not generate the same **method signature** declared in the server side (because swagger.json doesn't exactly reflect the method signature of the backend service). We've created an endpoint that exposes server side method contacts to allow clients generate a better aligned client proxies. + +So, we've decided to create an ABP CLI command to automatically generate the typescript client proxies ([#2222](https://github.com/abpframework/abp/issues/2222)) for your REST API developed with the ABP Framework. + +It is easy to use. Just run the following command in the **root folder** of the angular application: + +````bash +abp generate-proxy +```` + +It only creates proxies only for your own application's services. It doesn't create proxies for the services of the application modules you're using (by default). There are several options. See the [CLI documentation](https://docs.abp.io/en/abp/latest/CLI). + +### CRUD Application Services for Entities with Composite Keys + +` CrudAppService ` is a useful base class to create CRUD application services for your entities. But it doesn't support entities with **composite primary keys**. `AbstractKeyCrudAppService` is the new base class that is developed to support entities with composite primary keys. See [the documentation](https://docs.abp.io/en/abp/latest/Application-Services#abstractkeycrudappservice) for more. + +### Add Source Code of the Modules + +The application startup template comes with some [application modules](https://docs.abp.io/en/abp/latest/Modules/Index) **pre-installed** as **NuGet & NPM packages**. This have a few important advantages: + +* You can **easily [upgrade](https://docs.abp.io/en/abp/latest/CLI#update)** these modules when a new version is available. +* Your solution becomes **cleaner**, so you can focus on your own code. + +However, when you need to make **major customizations** for a depended module, it is not easy as its source code is in your applications. To solve this problem, we've introduces a new command to the [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) that **replaces** NuGet packages with their **source code** in your solution. The usage is simple: + +````bash +abp add-module --with-source-code +```` + +This command adds a module with source code or replaces with its source code if it is already added as package references. + +> It is suggested to **save your changes** to your source control system before using this command since it makes a lot of changes in your source code. + +In addition, we've documented how to customize depended modules without changing their source code (see the section below). It is suggested to use modules as packages to easily upgrade them in the future. + +> Source code of the free modules are licensed under **MIT**, so you can freely change them and add into your solution. + +### Switch to Preview + +ABP Framework is rapidly evolving and we are frequently releasing new versions. However, if you want to follow it closer, you can use the **daily preview packages**. + +We've created an ABP CLI command to easily **update to the latest preview packages** for your solution. Run the following command in the root folder of your solution: + +````bash +abp switch-to-preview +```` + +It will change the versions of all ABP related NuGet and NPM packages. You can **switch back to the latest stable** when you want: + +````bash +abp switch-to-stable +```` + +See the [ABP CLI document](https://docs.abp.io/en/abp/latest/CLI#switch-to-preview) fore more. + +### Documentation Improvements + +#### Extending/Customizing Depended Application Modules + +We've created a huge documentation that explains how to customize a depended module without changing its source code. See [the documentation](https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Guide). + +In addition to the documentation, we've revised all the modules ([#3166](https://github.com/abpframework/abp/issues/3166)) to make their services easily extensible & customizable. + +#### EF Core Migration Guide + +We've recently created a guide to explain the migration system that is used by the ABP startup templates. [This guide](https://docs.abp.io/en/abp/latest/Entity-Framework-Core-Migrations) also explains how to customize the migration structure, split your modules across multiple databases, reusing a module's table and son on. + +#### Migration from the ASP.NET Boilerplate + +If you have a solution built on the ASP.NET Boilerplate, we've [created a guide](https://docs.abp.io/en/abp/latest/AspNet-Boilerplate-Migration-Guide) that tries to help you if you want to migrate your solution to the new ABP Framework. + +### Some Other Features + +#### The Framework + +* Add `IRepository.GetAsync` and `IRepository.FindAsync` methods ([#3184](https://github.com/abpframework/abp/issues/3148)). + +#### Modules + +* Get password & email address of the admin while creating a new tenant, for the tenant management module ([#3088](https://github.com/abpframework/abp/issues/3088)). +* Elastic search integrated full text search for the docs module ([#2901](https://github.com/abpframework/abp/pull/2901)). +* New Quartz background worker module ([#2762](https://github.com/abpframework/abp/issues/2762)) + +#### Samples + +* Add multi-tenancy support to the microservice demo ([#3032](https://github.com/abpframework/abp/pull/3032)). + +See [the release notes](https://github.com/abpframework/abp/releases/tag/2.3.0) for all feature, enhancement and bugfixes. + +## What's Next? + +We have the following goals for the next few months: + +* Complete the **documentation and samples**, write more tutorials. +* Make the framework and existing modules more **customizable and extensible**. +* Integrate to **gRPC** & implement gRPC endpoint for pre-built modules ([#2882](https://github.com/abpframework/abp/issues/2882)). +* Create a **Blazor UI** for the ABP Framework & implement it for all the modules and startup templates ([#394](https://github.com/abpframework/abp/issues/394)). +* Add **new features** to pre-built modules and create new modules for the [ABP Commercial](https://commercial.abp.io/). + +See [the GitHub milestones](https://github.com/abpframework/abp/milestones) for details. \ No newline at end of file diff --git a/docs/en/Blog-Posts/2020-03-19 v2_3_Release/abp-io-release-2-3-0-blog.png b/docs/en/Blog-Posts/2020-03-19 v2_3_Release/abp-io-release-2-3-0-blog.png new file mode 100644 index 0000000000..8c0a2bf241 Binary files /dev/null and b/docs/en/Blog-Posts/2020-03-19 v2_3_Release/abp-io-release-2-3-0-blog.png differ diff --git a/docs/en/Blog-Posts/2020-03-19 v2_3_Release/react-native-ui.png b/docs/en/Blog-Posts/2020-03-19 v2_3_Release/react-native-ui.png new file mode 100644 index 0000000000..47d889413c Binary files /dev/null and b/docs/en/Blog-Posts/2020-03-19 v2_3_Release/react-native-ui.png differ diff --git a/docs/en/CLI.md b/docs/en/CLI.md index 837ba26a11..a347599135 100644 --- a/docs/en/CLI.md +++ b/docs/en/CLI.md @@ -22,7 +22,7 @@ dotnet tool update -g Volo.Abp.Cli Generates a new solution based on the ABP [startup templates](Startup-Templates/Index.md). -Basic usage: +Usage: ````bash abp new [options] @@ -94,7 +94,7 @@ Adds a [multi-package application module](Modules/Index) to a solution by findin > A business module generally consists of several packages (because of layering, different database provider options or other reasons). Using `add-module` command dramatically simplifies adding a module to a solution. However, each module may require some additional configurations which is generally indicated in the documentation of the related module. -Basic usage: +Usage ````bash abp add-module [options] @@ -180,26 +180,26 @@ abp logout ### generate-proxy -Generates typescript service proxies and DTOs +Generates client proxies for your HTTP APIs to make easy to consume your services from the client side. Before running `generate-proxy` command, your host must be up and running. -Basic usage: +Usage: ````bash abp generate-proxy [options] ```` -Example: +#### Options + +* `--apiUrl` or `-a`: Specifies the root URL of the HTTP API. The default value is being retrieved from the `environment.ts` file for the Angular application. Make sure your host is up and running before running `abp generate-proxy`. +* `--ui` or `-u`: Specifies the UI framework. Default value is `angular` and it is the only UI framework supported for now. Creates TypeScript code. +* `--module` or `-m`: Specifies the module name. Default module name is `app`, which indicates your own application (you typically want this since every module is responsible to maintain its own client proxies). Set `all` for to generate proxies for all the modules. + +Example usage with the options: ````bash abp generate-proxy --apiUrl https://localhost:44305 --ui angular --module all ```` -#### Options - -* `--apiUrl` or `-a`: If you don't give this option, the default api url in your environment.ts file is used, but you can always use a specific api source with this option. -* `--ui` or `-u`: Specifies the UI framework. Default framework is angular. Currently there is only angular option, but we will increase the options with our new cli updates. Stay tuned! -* `--module` or `-m`: Specifies the module name. Default module name is app. If you want to all modules. You can give `--module all` command. - ### help diff --git a/docs/en/UI/AspNetCore/Tag-Helpers/Alerts.md b/docs/en/UI/AspNetCore/Tag-Helpers/Alerts.md new file mode 100644 index 0000000000..cf19e31e29 --- /dev/null +++ b/docs/en/UI/AspNetCore/Tag-Helpers/Alerts.md @@ -0,0 +1,82 @@ +# Alerts + +## Introduction + +`abp-alert` is a main element to create an alert. + +Basic usage: + +````xml + + A simple primary alert—check it out! + +```` + + + +## Demo + +See the [alerts demo page](https://bootstrap-taghelpers.abp.io/Components/Alerts) to see it in action. + +## Attributes + +### alert-type + +A value indicates the type of the alert. Should be one of the following values: + +* `Default` (default value) +* `Primary` +* `Secondary` +* `Success` +* `Danger` +* `Warning` +* `Info` +* `Light` +* `Dark` + +Example: + +````xml + + A simple warning alert—check it out! + +```` + +### alert-link + +A value provides matching colored links within any alert. + +Example: + +````xml + + A simple danger alert with an example link. Give it a click if you like. + +```` + +### dismissible + +A value to make the alert dismissible. + +Example: + +````xml + + Holy guacamole! You should check in on some of those fields below. + +```` + +### Additional content + +`abp-alert` can also contain additional HTML elements like headings, paragraphs and dividers. + +Example: + +````xml + +

Well done!

+

Aww yeah, you successfully read this important alert message. This example text is going to run a bit longer so that you can see how spacing within an alert works with this kind of content.

+
+

Whenever you need to, be sure to use margin utilities to keep things nice and tidy.

+
+```` diff --git a/docs/en/UI/AspNetCore/Tag-Helpers/Grids.md b/docs/en/UI/AspNetCore/Tag-Helpers/Grids.md new file mode 100644 index 0000000000..b33fa03c46 --- /dev/null +++ b/docs/en/UI/AspNetCore/Tag-Helpers/Grids.md @@ -0,0 +1,286 @@ +# Grids + +## Introduction + +Abp tag helpers for bootstrap based grid system. + + + +## Demo + +See the [grids demo page](https://bootstrap-taghelpers.abp.io/Components/Grids) to see it in action. + + + +### Sizing + +**Equal Width:** Creates columns with equal width. + +Sample: + +````xml + + + 1 of 2 + 2 of 2 + + + 1 of 3 + 2 of 3 + 3 of 3 + + +```` + +**Column Breaker:** `abp-column-breaker` is used for breaking the automatic width of placement of the current row and starting in a new row afterwards. + +Sample: + +````xml + + + column + column + + column + column + + +```` + +**Setting one column width:** size attribute is used for setting the width for a specific column. + +Sample: + +```xml + + + 1 of 3 + 2 of 3 (wider) + 3 of 3 + + + 1 of 3 + 2 of 3 (wider) + 3 of 3 + + +``` + +**Variable width content:** Auto resizing column based on content. + +```xml + + + 1 of 3 + Contrary to popular belief, Lorem Ipsum is not simply random text. + 3 of 3 + + + 1 of 3 + Variable width content + 3 of 3 + + +``` + + + +### Responsive Classes + +Responsive classes can be used strongly typed within abp tags. + +```xml + + col-sm-8 + col-sm-4 + + + col-sm + col-sm + col-sm + col-sm + + + + .col-12 .col-md-8 + .col-6 .col-md-4 + + + + + .col-6 .col-md-4 + .col-6 .col-md-4 + .col-6 .col-md-4 + + + + + .col-6 + .col-6 + +``` + + + +### Alignment + +Column alignments can be done strongly typed in abp tags with both vertically and horizontally. + +**Vertical-alignment**: `v-align` attribute value is used to align the columns vertically. + +Sample: + +```xml + + + column + column + column + + + column + column + column + + + column + column + column + + +``` + +**Horizontal-alignment**: `h-align` attribute value is used to align the columns horizontally. + +Sample: + +```xml + + + One of two columns + One of two columns + + + One of two columns + One of two columns + + + One of two columns + One of two columns + + + One of two columns + One of two columns + + + One of two columns + One of two columns + + +``` + +**No gutters**: The gutters between columns in predefined grid classes can be removed with `gutters="false"`. This removes the negative `margin`s from `abp-row` and the horizontal `padding` from all immediate children columns. + +Sample: + +```xml + + One of two columns + One of two columns + +``` + +**Column wrapping**: If more than 12 columns are placed within a single row, each group of extra columns will, as one unit, wrap onto a new line. + +Sample: + +```xml + + .col-9 + .col-4
Since 9 + 4 = 13 > 12, this 4-column-wide div gets wrapped onto a new line as one contiguous unit.
+ .col-6
Subsequent columns continue along the new line.s
+
+``` + + + +### Reordering + +**Order Classes**: `order` attribute is used for controlling the visual order of the content. + +Sample: + +```xml + + + First, but Last + Second, but unordered + Third, but Second + + +``` + +**Offsetting columns**: `offset` attribute is used for setting the offset of the grid columns. + +Sample: + +```xml + + + .col-md-4 + .col-md-4 .offset-md-4 + + + .col-md-3 .offset-md-3 + .col-md-3 .offset-md-3 + + + .col-md-6 .offset-md-3 + + + .col-sm-5 .col-md-6 + .col-sm-5 .offset-sm-2 .col-md-6 .offset-md-0 + + + col-sm-6 .col-md-5 .col-lg-6 + .col-sm-6 .col-md-5 .offset-md-2 .col-lg-6 .offset-lg-0 + + +``` + + + +## abp-row Attributes + +- **v-align:** A value indicates the vertical positioning of the containing columns. Should be one of the following values: + * `Default` (default value) + * `Start` + * `Center` + * `End` + +- **h-align**: A value indicates the horizontal positioning of the containing columns. Should be one of the following values: + * `Default` (default value) + * `Start` + * `Center` + * `Around` + * `Between` + * `End` +- **gutter**: A value indicates if the negative `margin` and horizontal `padding` will be removed from all children columns. Will act as `true` value if this attribute is not set. Should be one of the following values: + * `true` + * `false` + +## abp-column Attributes + +- **size:** A value indicates the width of the column from `_`, `Undefined`, `_1`..`_12`, `Auto`. Or can be used with predefined values like: + - `size-sm` + - `size-md` + - `size-lg` + - `size-xl` +- **order**: A value indicates the order of column from `Undefined`, `_1`..`_12`, `First` and `Last`. +- **offset:** A value indicates offset of the column from `_`, `Undefined`, `_1`..`_12`, `Auto`. Or can be used with predefined values like: + - `offset-sm` + - `offset-md` + - `offset-lg` + - `offset-xl` + diff --git a/docs/en/UI/AspNetCore/Tag-Helpers/Index.md b/docs/en/UI/AspNetCore/Tag-Helpers/Index.md index d7e393933e..5f36395c00 100644 --- a/docs/en/UI/AspNetCore/Tag-Helpers/Index.md +++ b/docs/en/UI/AspNetCore/Tag-Helpers/Index.md @@ -13,6 +13,8 @@ ABP Framework also adds some **useful features** to the standard bootstrap compo Here, the list of components those are wrapped by the ABP Framework: * [Buttons](Buttons.md) +* [Cards](Cards.md) +* [Alerts](Alerts.md) * ... > Until all the tag helpers are documented, you can visit https://bootstrap-taghelpers.abp.io/ to see them with live samples. diff --git a/docs/en/UI/AspNetCore/Tag-Helpers/Tabs.md b/docs/en/UI/AspNetCore/Tag-Helpers/Tabs.md new file mode 100644 index 0000000000..b6fc766753 --- /dev/null +++ b/docs/en/UI/AspNetCore/Tag-Helpers/Tabs.md @@ -0,0 +1,93 @@ +# Tabs + +## Introduction + +`abp-tab` is the basic tab navigation content container derived from bootstrap tab element. + +Basic usage: + +````xml + + + Content_Home + + + + Content_Profile + + + + Content_1_Content + + + Content_2_Content + + + +```` + + + +## Demo + +See the [cards demo page](https://bootstrap-taghelpers.abp.io/Components/Cards) to see it in action. + +## abp-tab Attributes + +- **title**: Sets the text of the tab menu. +- **name:** Sets "id" attribute of generated elements. Default value is a Guid. Not needed unless tabs are changed or modified with Jquery. +- **active**: Sets the active tab. + +Example: + +````xml + + + Content_Home + + + Content_Profile + + + Content_Contact + + +```` + +### Pills + +Example: + +````xml + + + Content_Home + + + Content_Profile + + + Content_Contact + + +```` + +### Vertical + +**vertical-header-size**: Sets the column width of tab headers. + +Example: + +````xml + + + Content_Home + + + Content_Profile + + + Content_Contact + + +```` diff --git a/docs/zh-Hans/Blog-Posts/2020-03-19 v2_3_Release/Post.md b/docs/zh-Hans/Blog-Posts/2020-03-19 v2_3_Release/Post.md new file mode 100644 index 0000000000..a17bef2e1b --- /dev/null +++ b/docs/zh-Hans/Blog-Posts/2020-03-19 v2_3_Release/Post.md @@ -0,0 +1,142 @@ +# ABP框架v2.3.0已经发布! + +在**新冠病毒**的日子里,我们发布了**ABP框架v2.3**, 这篇文章将说明本次发布**新增内容**和过去的两周**我们做了什么**. + +## 关于新冠病毒和我们的团队 + +关于冠状病毒的状况**我们很难过**.在[Volosoft](https://volosoft.com/)的团队,我们有不同国家的**远程工作者**在自己家里工作.从上周开始,我们已经**完全开始在家远程工作**,包括我们的主要办公室的员工. + +我们相信并祈祷人类会在很短的时间内克服这个问题. + +## 关于发布周期 + +从ABP v2.1.0开始,我们开始**每两周**的周四发布功能版本.本次是该决定后的第3次发布,我们看到这种方式目前运转良好,并提高了我们的灵活性. + +我们将继续每两周发布**功能版本**(如v2.4,v2.5).另外,如果需要我们会随时发布**热修复版本**(如v2.3.1,v2.3.2). + +## ABP框架v2.3.0新增内容 + +我们已在这两周的开发周期内通过**393次提交**完成和合并了 **[104](https://github.com/abpframework/abp/milestone/30?closed=1)个issue和pull request**. + +我将介绍这个版本加入的一些新功能和改善. + +### React Native移动应用程序 + +我们终于完成了**react native移动应用程序**.目前,它可以让你**登录**,管理**用户**和**租户**.它利用ABP框架相同的设置,授权和本地化系统. + +应用程序的一些截图: + +![mobile-ui](react-native-ui.png) + +它没有太多的功能,但它是你的移动应用程序一个**完美的起点**,因为它是完全集成到后端并支持多租户. + +### Angular TypeScript代理生成器 + +从我们的Angular应用程序中调用服务器中的REST端点是很常见的.这种情况下,我们一般创建**服务**(在服务器上包含各个服务的方法)和**模型对象**(对应服务器上的[DTO](https://docs.abp.io/en/abp/latest/Data-Transfer-Objects)). + +除了手动创建这样的与服务器交互的服务外,我们可以使用像[NSWAG](https://github.com/RicoSuter/NSwag)工具来为我们生成服务代理.但是NSWAG有以下几个我们遇到的问题: + +* 它产生一个**大,单一**的.ts文件; + * 当你的应用程序增长时,它变得**太大**了. + * 它不适合ABP框架的 **[模块化](https://docs.abp.io/en/abp/latest/Module-Development-Basics)方式**. +* 它创建了有点**丑陋的代码**.我们希望有一个干净的代码(就像我们手写的). +* 它不能生成服务器端声明的相同的**方法签名**(因为swagger.json不能准确地反映后端服务的方法签名).我们已创建了公开服务器端方法约定的端点,来允许客户端生成更好的客户端代理. + +因此,我们决定创建一个ABP CLI命令来自动生成typescript客户端代理([#2222](https://github.com/abpframework/abp/issues/2222)),用于在ABP框架中开发REST API. + +它用起来很简单.只需要在你Angular应用程序的**根文件夹**运行以下命令 + +````bash +abp generate-proxy +```` + +它只会为你自己的应用程序的服务创建代理.它(默认)不会为你使用的应用程序模块创建代理.有几个选项.参见[CLI文档](https://docs.abp.io/en/abp/latest/CLI). + +### 复合主键的CRUD应用服务 + +` CrudAppService `是一个很有用的基类,用来为你的实体创建CRUD应用服务.不过,它不支持**复合主键**的实体. `AbstractKeyCrudAppService`是新开发的基类以支持复合主键的实体.更多信息请浏览[文档](https://docs.abp.io/en/abp/latest/Application-Services#abstractkeycrudappservice). + +### 添加模块的源代码 + +应用程序启动模板带有一些[应用模块](https://docs.abp.io/en/abp/latest/Modules/Index), 以**Nuget和NPM包**的方式**预先安装了** .这样做有几个重要的优点: + +* 当新版本可用时, 你可以 **轻松地[升级](https://docs.abp.io/en/abp/latest/CLI#update)** 这些模块. +* 你的解决方案**更干净**,这样你就可以专注于自己的代码. + +但是,当你需要对一个依赖的模块**大量定制**时,就不如它的代码在你的应用程序中那么容易.为了解决这个问题,我们引入了一个[ABP CLI](https://docs.abp.io/en/abp/latest/CLI)的新命令, 在你的解决方案中用代码**替换**Nuget包.用法很简单: + +````bash +abp add-module --with-source-code +```` + +该命令以源代码方式添加模块, 或者如果模块已经以包引用方式添加了, 则替换为源代码,. + +> 建议在使用此命令前**保存你的更改**到源代码控制系统, 因为它会修改很多你的代码. + +此外,我们也创建了文档来说明如何定制依赖的模块而不改变它们的源代码(见下面的部分).仍然建议以包的方式使用模块,以便在以后可以轻松升级. + +> 免费模块的源代码是**MIT**许可,所以你可以自由更改它们并添加到您的解决方案中. + +### 切换到预览版 + +ABP框架正在迅速发展,我们经常发布新版本.不过,如果你想更紧密地追随它,你可以使用**每日预览包**. + +我们创建了一个ABP CLI命令来轻松地为你的解决方案**更新到最新的预览包**.在你的解决方案的根文件夹中运行以下命令: + +````bash +abp switch-to-preview +```` + +它会修改所有ABP相关的NuGet和NPM包的版本.当你需要时你也可以**切换回最新稳定版**: + +````bash +abp switch-to-stable +```` + +更多信息请浏览[ABP CLI文档](https://docs.abp.io/en/abp/latest/CLI#switch-to-preview). + +### 文档改进 + +#### 扩展/定制依赖应用模块 + +我们创建了一个巨大的文档来说明如何定制模块依赖而不改变其源代码.参见[文档](https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Guide). + +除了文档以外,我们已经修订了所有模块([#3166](https://github.com/abpframework/abp/issues/3166)),来使他们的服务更容易扩展和定制. + +#### EF Core迁移指南 + +最近,我们创建了一个指南,说明ABP启动模板所使用的迁移系统. [该指南](https://docs.abp.io/en/abp/latest/Entity-Framework-Core-Migrations)还介绍了如何定制迁移结构,拆分你的模块跨多个数据库,复用一个模块的表,等等. + +#### 从 ASP.NET Boilerplate迁移 + +如果你有建立在 ASP.NET Boilerplate的解决方案,我们[创建了一个指南](https://docs.abp.io/en/abp/latest/AspNet-Boilerplate-Migration-Guide),试着帮助迁移你的解决方案到新的ABP框架上. + +### 其他一些功能 + +#### 框架 + +* 添加`IRepository.GetAsync`和`IRepository.FindAsync`方法([#3184](https://github.com/abpframework/abp/issues/3148)). + +#### 模块 + +* 当创建新租户时获取管理员的密码和电子邮件地址,租户管理模块([#3088](https://github.com/abpframework/abp/issues/3088)). +* 集成Elastic全文检索, 文档模块([#2901](https://github.com/abpframework/abp/pull/2901)). +* 新的Quartz后台工作者模块([#2762](https://github.com/abpframework/abp/issues/2762)) + +#### 示例 + +* 微服务演示添加多租户支持([#3032](https://github.com/abpframework/abp/pull/3032)). + +所有的功能, 改善和BUG修复, 请浏览[发布说明](https://github.com/abpframework/abp/releases/tag/2.3.0). + +## 下一步? + +我们未来几个月的目标如下: + +* 完成**文档和示例**,写更多的教程. +* 使框架和现有模块的更加**可定制和可扩展**. +* 集成**gRPC**和为所有预置模块实现gRPC端点([#2882](https://github.com/abpframework/abp/issues/2882)). +* 为ABP框架创建**Blazor UI**, 并在所有模块和启动模板中实现它([#394](https://github.com/abpframework/abp/issues/394)). +* 为预置模块**添加新功能**,并为[ABP商业版](https://commercial.abp.io/)创建新模块. + +更多细节请浏览[GitHub里程碑](https://github.com/abpframework/abp/milestones). \ No newline at end of file diff --git a/docs/zh-Hans/Blog-Posts/2020-03-19 v2_3_Release/abp-io-release-2-3-0-blog.png b/docs/zh-Hans/Blog-Posts/2020-03-19 v2_3_Release/abp-io-release-2-3-0-blog.png new file mode 100644 index 0000000000..8c0a2bf241 Binary files /dev/null and b/docs/zh-Hans/Blog-Posts/2020-03-19 v2_3_Release/abp-io-release-2-3-0-blog.png differ diff --git a/docs/zh-Hans/Blog-Posts/2020-03-19 v2_3_Release/react-native-ui.png b/docs/zh-Hans/Blog-Posts/2020-03-19 v2_3_Release/react-native-ui.png new file mode 100644 index 0000000000..47d889413c Binary files /dev/null and b/docs/zh-Hans/Blog-Posts/2020-03-19 v2_3_Release/react-native-ui.png differ diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj b/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj index e2392c2b53..544099c653 100644 --- a/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj +++ b/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj @@ -19,7 +19,7 @@ - + diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalFooterTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalFooterTagHelper.cs index 2df1bf158a..30de6d25f5 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalFooterTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalFooterTagHelper.cs @@ -1,8 +1,12 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal +using Microsoft.AspNetCore.Razor.TagHelpers; + +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal { + [HtmlTargetElement("abp-modal-footer")] public class AbpModalFooterTagHelper : AbpTagHelper { public AbpModalButtons Buttons { get; set; } + public ButtonsAlign ButtonAlignment { get; set; } = ButtonsAlign.Default; public AbpModalFooterTagHelper(AbpModalFooterTagHelperService tagHelperService) : base(tagHelperService) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalFooterTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalFooterTagHelperService.cs index cff4646917..38cac85a6d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalFooterTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalFooterTagHelperService.cs @@ -24,6 +24,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal { output.PostContent.SetHtmlContent(CreateContent()); } + ProcessButtonsAlignment(output); } protected virtual string CreateContent() @@ -49,9 +50,18 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal sb.AppendLine(""); sb.AppendLine(""); break; - } - + } + return sb.ToString(); } + + protected virtual void ProcessButtonsAlignment(TagHelperOutput output) + { + if (TagHelper.ButtonAlignment == ButtonsAlign.Default) + { + return; + } + output.Attributes.AddClass("justify-content-" + TagHelper.ButtonAlignment.ToString().ToLowerInvariant()); + } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalTagHelper.cs index aa61832ab9..51688afceb 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalTagHelper.cs @@ -6,6 +6,8 @@ public bool? Centered { get; set; } = false; + public bool? Static { get; set; } = false; + public AbpModalTagHelper(AbpModalTagHelperService tagHelperService) : base(tagHelperService) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalTagHelperService.cs index 8106db4661..3524b27d35 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalTagHelperService.cs @@ -18,9 +18,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal var sb = new StringBuilder(); var attritubutes = output.Attributes.Select(a => " " + a.Name + "=\"" + a.Value + "\" ").ToList(); - var attritubutesAsJoin = string.Join(" ", attritubutes.ToArray()); - - sb.AppendLine("
"); + var attritubutesAsJoin = string.Join(" ", attritubutes.ToArray()); + + sb.AppendLine("
"); sb.AppendLine("
"); sb.AppendLine("
"); @@ -56,6 +56,15 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal return "modal-content"; } + protected virtual string GetDataAttributes() + { + if (TagHelper.Static == true) + { + return "data-backdrop=\"static\" "; + } + return string.Empty; + } + protected virtual string CreatePostContent() { var sb = new StringBuilder(); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/ButtonsAlign.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/ButtonsAlign.cs new file mode 100644 index 0000000000..7f6ba7b984 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/ButtonsAlign.cs @@ -0,0 +1,12 @@ +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal +{ + public enum ButtonsAlign + { + Default, + Start, + Center, + Around, + Between, + End + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Toolbar/LanguageSwitch/Default.cshtml b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Toolbar/LanguageSwitch/Default.cshtml index ae3255abbf..65ca8d940e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Toolbar/LanguageSwitch/Default.cshtml +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Toolbar/LanguageSwitch/Default.cshtml @@ -1,4 +1,5 @@ @using System.Linq +@using Microsoft.AspNetCore.Http.Extensions @using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Themes.Basic.Components.Toolbar.LanguageSwitch @model LanguageSwitchViewComponentModel @if (Model.OtherLanguages.Any()) @@ -11,7 +12,7 @@
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/FodyWeavers.xml b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/FodyWeavers.xml index 00e1d9a1c1..be0de3a908 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/FodyWeavers.xml +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/FodyWeavers.xml @@ -1,3 +1,3 @@  - + \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj index dabe2e30d4..90500a456b 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj @@ -26,9 +26,9 @@ - + - + diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProvider.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProvider.cs index aefad0f02e..f957fd894f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProvider.cs @@ -73,7 +73,7 @@ namespace Volo.Abp.AspNetCore.Mvc var controllerType = apiDescription.ActionDescriptor.AsControllerActionDescriptor().ControllerTypeInfo.AsType(); var setting = FindSetting(controllerType); - var moduleModel = applicationModel.GetOrAddModule(GetRootPath(controllerType, setting)); + var moduleModel = applicationModel.GetOrAddModule(GetRootPath(controllerType, setting), GetRemoteServiceName(controllerType, setting)); var controllerModel = moduleModel.GetOrAddController(controllerType.FullName, CalculateControllerName(controllerType, setting), controllerType, _modelOptions.IgnoredInterfaces); @@ -289,6 +289,22 @@ namespace Volo.Abp.AspNetCore.Mvc return ModuleApiDescriptionModel.DefaultRootPath; } + private string GetRemoteServiceName(Type controllerType, [CanBeNull] ConventionalControllerSetting setting) + { + if (setting != null) + { + return setting.RemoteServiceName; + } + + var remoteServiceAttr = controllerType.GetCustomAttributes().OfType().FirstOrDefault(); + if (remoteServiceAttr?.Name != null) + { + return remoteServiceAttr.Name; + } + + return ModuleApiDescriptionModel.DefaultRemoteServiceName; + } + [CanBeNull] private ConventionalControllerSetting FindSetting(Type controllerType) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpConventionalControllerOptions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpConventionalControllerOptions.cs index e28ff37717..e21e6ee939 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpConventionalControllerOptions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpConventionalControllerOptions.cs @@ -23,9 +23,16 @@ namespace Volo.Abp.AspNetCore.Mvc.Conventions }; } - public AbpConventionalControllerOptions Create(Assembly assembly, [CanBeNull] Action optionsAction = null) + public AbpConventionalControllerOptions Create( + Assembly assembly, + [CanBeNull] Action optionsAction = null) { - var setting = new ConventionalControllerSetting(assembly, ModuleApiDescriptionModel.DefaultRootPath); + var setting = new ConventionalControllerSetting( + assembly, + ModuleApiDescriptionModel.DefaultRootPath, + ModuleApiDescriptionModel.DefaultRemoteServiceName + ); + optionsAction?.Invoke(setting); setting.Initialize(); ConventionalControllerSettings.Add(setting); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalControllerSetting.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalControllerSetting.cs index fac627d182..bae2522d20 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalControllerSetting.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalControllerSetting.cs @@ -30,6 +30,18 @@ namespace Volo.Abp.AspNetCore.Mvc.Conventions } private string _rootPath; + [NotNull] + public string RemoteServiceName + { + get => _remoteServiceName; + set + { + Check.NotNull(value, nameof(value)); + _remoteServiceName = value; + } + } + private string _remoteServiceName; + [CanBeNull] public Func TypePredicate { get; set; } @@ -46,15 +58,16 @@ namespace Volo.Abp.AspNetCore.Mvc.Conventions public Action ApiVersionConfigurer { get; set; } - public ConventionalControllerSetting([NotNull] Assembly assembly, [NotNull] string rootPath) + public ConventionalControllerSetting( + [NotNull] Assembly assembly, + [NotNull] string rootPath, + [NotNull] string remoteServiceName) { - Check.NotNull(assembly, rootPath); - - Assembly = assembly; - RootPath = rootPath; + Assembly = Check.NotNull(assembly, nameof(assembly)); + RootPath = Check.NotNull(rootPath, nameof(rootPath)); + RemoteServiceName = Check.NotNull(remoteServiceName, nameof(remoteServiceName)); ControllerTypes = new HashSet(); - ApiVersions = new List(); } diff --git a/framework/src/Volo.Abp.AspNetCore.TestBase/Volo.Abp.AspNetCore.TestBase.csproj b/framework/src/Volo.Abp.AspNetCore.TestBase/Volo.Abp.AspNetCore.TestBase.csproj index 38d9a34867..2ff1d539a6 100644 --- a/framework/src/Volo.Abp.AspNetCore.TestBase/Volo.Abp.AspNetCore.TestBase.csproj +++ b/framework/src/Volo.Abp.AspNetCore.TestBase/Volo.Abp.AspNetCore.TestBase.csproj @@ -24,7 +24,7 @@ - + diff --git a/framework/src/Volo.Abp.Authorization/Volo.Abp.Authorization.csproj b/framework/src/Volo.Abp.Authorization/Volo.Abp.Authorization.csproj index 8c6482837f..e5183688df 100644 --- a/framework/src/Volo.Abp.Authorization/Volo.Abp.Authorization.csproj +++ b/framework/src/Volo.Abp.Authorization/Volo.Abp.Authorization.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj b/framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj index 868f7e6719..45cc6e2d94 100644 --- a/framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj +++ b/framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj @@ -17,7 +17,7 @@ - + diff --git a/framework/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj b/framework/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj index f59d9fe116..db744f410e 100644 --- a/framework/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj +++ b/framework/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GenerateProxyCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GenerateProxyCommand.cs index 17fe2d3781..12fc5af525 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GenerateProxyCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GenerateProxyCommand.cs @@ -67,7 +67,8 @@ namespace Volo.Abp.Cli.Commands var data = JObject.Parse(json); Logger.LogInformation("Modules are combining"); - var moduleList = GetCombinedModules(data, module); + var apiNameList = new Dictionary(); + var moduleList = GetCombinedModules(data, module, out apiNameList); if (moduleList.Count < 1) { @@ -85,6 +86,7 @@ namespace Volo.Abp.Cli.Commands var moduleValue = JObject.Parse(moduleItem.Value); var rootPath = moduleItem.Key; + var apiName = apiNameList.Where(p => p.Key == rootPath).Select(p => p.Value).FirstOrDefault(); Logger.LogInformation($"{rootPath} directory is creating"); @@ -105,6 +107,8 @@ namespace Volo.Abp.Cli.Commands serviceFileText.AppendLine(""); serviceFileText.AppendLine("@Injectable({providedIn: 'root'})"); serviceFileText.AppendLine("export class [controllerName]Service {"); + serviceFileText.AppendLine(" apiName = '"+ apiName + "';"); + serviceFileText.AppendLine(""); serviceFileText.AppendLine(" constructor(private restService: RestService) {}"); serviceFileText.AppendLine(""); @@ -309,8 +313,8 @@ namespace Volo.Abp.Cli.Commands serviceFileText.AppendLine( url.Contains("${") - ? $" return this.restService.request({{ url: `/{url}`, method: '{httpMethod}'{bodyExtra}{modelBindingExtra} }});" - : $" return this.restService.request({{ url: '/{url}', method: '{httpMethod}'{bodyExtra}{modelBindingExtra} }});"); + ? $" return this.restService.request({{ url: `/{url}`, method: '{httpMethod}'{bodyExtra}{modelBindingExtra} }},{{ apiName: this.apiName }});" + : $" return this.restService.request({{ url: '/{url}', method: '{httpMethod}'{bodyExtra}{modelBindingExtra} }},{{ apiName: this.apiName }});"); serviceFileText.AppendLine(" }"); @@ -369,13 +373,15 @@ namespace Volo.Abp.Cli.Commands Logger.LogInformation("Completed!"); } - private Dictionary GetCombinedModules(JToken data, string module) + private Dictionary GetCombinedModules(JToken data, string module, out Dictionary apiNameList) { var moduleList = new Dictionary(); + apiNameList = new Dictionary(); foreach (var moduleItem in data["modules"]) { var rootPath = ((string)moduleItem.First["rootPath"]).ToLower(); + var apiName = (string)moduleItem.First["remoteServiceName"]; if (moduleList.Any(p => p.Key == rootPath)) { @@ -385,6 +391,7 @@ namespace Volo.Abp.Cli.Commands } else { + apiNameList.Add(rootPath, apiName); moduleList.Add(rootPath, moduleItem.First["controllers"].ToString()); } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs index 28fcf4b3f6..3afc32ec4d 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs @@ -55,6 +55,12 @@ namespace Volo.Abp.Cli.Commands Logger.LogInformation("Version: " + version); } + var isTiered = commandLineArgs.Options.ContainsKey(Options.Tiered.Long); + if (isTiered) + { + Logger.LogInformation("Tiered: yes"); + } + var databaseProvider = GetDatabaseProvider(commandLineArgs); if (databaseProvider != DatabaseProvider.NotSpecified) { @@ -96,14 +102,9 @@ namespace Volo.Abp.Cli.Commands var outputFolderRoot = outputFolder != null ? Path.GetFullPath(outputFolder) : Directory.GetCurrentDirectory(); - if (createSolutionFolder) - { - outputFolder = Path.Combine(outputFolderRoot, SolutionName.Parse(projectName).FullName); - } - else - { - outputFolder = outputFolderRoot; - } + outputFolder = createSolutionFolder ? + Path.Combine(outputFolderRoot, SolutionName.Parse(projectName).FullName) : + outputFolderRoot; if (!Directory.Exists(outputFolder)) { @@ -232,7 +233,7 @@ namespace Volo.Abp.Cli.Commands } } - private UiFramework GetUiFramework(CommandLineArgs commandLineArgs) + protected virtual UiFramework GetUiFramework(CommandLineArgs commandLineArgs) { var optionValue = commandLineArgs.Options.GetOrNull(Options.UiFramework.Short, Options.UiFramework.Long); switch (optionValue) @@ -248,7 +249,7 @@ namespace Volo.Abp.Cli.Commands } } - private MobileApp GetMobilePreference(CommandLineArgs commandLineArgs) + protected virtual MobileApp GetMobilePreference(CommandLineArgs commandLineArgs) { var optionValue = commandLineArgs.Options.GetOrNull(Options.Mobile.Short, Options.Mobile.Long); switch (optionValue) @@ -316,6 +317,11 @@ namespace Volo.Abp.Cli.Commands public const string Short = "csf"; public const string Long = "create-solution-folder"; } + + public static class Tiered + { + public const string Long = "tiered"; + } } } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs index 263b675a2a..1ffdefbe61 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs @@ -94,36 +94,48 @@ namespace Volo.Abp.Cli.ProjectBuilding private async Task GetLatestSourceCodeVersionAsync(string name, string type) { - using (var client = new CliHttpClient()) + var url = $"{CliUrls.WwwAbpIo}api/download/{type}/get-version/"; + + try { - var response = await client.PostAsync( - $"{CliUrls.WwwAbpIo}api/download/{type}/get-version/", - new StringContent( - JsonSerializer.Serialize( - new GetLatestSourceCodeVersionDto { Name = name } + using (var client = new CliHttpClient(TimeSpan.FromMinutes(10))) + { + var response = await client.PostAsync( + url, + new StringContent( + JsonSerializer.Serialize( + new GetLatestSourceCodeVersionDto { Name = name } + ), + Encoding.UTF8, + MimeTypes.Application.Json ), - Encoding.UTF8, - MimeTypes.Application.Json - ), - CancellationTokenProvider.Token - ); + CancellationTokenProvider.Token + ); - await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response); + await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response); - var result = await response.Content.ReadAsStringAsync(); + var result = await response.Content.ReadAsStringAsync(); - return JsonSerializer.Deserialize(result).Version; + return JsonSerializer.Deserialize(result).Version; + } + } + catch (Exception ex) + { + Console.WriteLine("Error occured while getting the latest version from {0} : {1}", url, ex.Message); + throw; } } private async Task GetTemplateNugetVersionAsync(string name, string type, string version) { + var url = $"{CliUrls.WwwAbpIo}api/download/{type}/get-nuget-version/"; + try { using (var client = new CliHttpClient(TimeSpan.FromMinutes(10))) { var response = await client.PostAsync( - $"{CliUrls.WwwAbpIo}api/download/{type}/get-nuget-version/", + url, new StringContent( JsonSerializer.Serialize( new GetTemplateNugetVersionDto { Name = name, Version = version } @@ -141,40 +153,49 @@ namespace Volo.Abp.Cli.ProjectBuilding return JsonSerializer.Deserialize(result).Version; } } - catch (Exception) + catch (Exception ex) { + Console.WriteLine("Error occured while getting the NuGet version from {0} : {1}", url, ex.Message); return null; } } private async Task DownloadSourceCodeContentAsync(SourceCodeDownloadInputDto input) { - var postData = JsonSerializer.Serialize(input); + var url = $"{CliUrls.WwwAbpIo}api/download/{input.Type}/"; - using (var client = new CliHttpClient(TimeSpan.FromMinutes(10))) + try { - HttpResponseMessage responseMessage; - - if (input.TemplateSource.IsNullOrWhiteSpace()) - { - responseMessage = await client.PostAsync( - $"{CliUrls.WwwAbpIo}api/download/{input.Type}/", - new StringContent(postData, Encoding.UTF8, MimeTypes.Application.Json), - CancellationTokenProvider.Token - ); - } - else + using (var client = new CliHttpClient(TimeSpan.FromMinutes(10))) { - responseMessage = await client.GetAsync(input.TemplateSource, CancellationTokenProvider.Token); + HttpResponseMessage responseMessage; + + if (input.TemplateSource.IsNullOrWhiteSpace()) + { + responseMessage = await client.PostAsync( + url, + new StringContent(JsonSerializer.Serialize(input), Encoding.UTF8, MimeTypes.Application.Json), + CancellationTokenProvider.Token + ); + } + else + { + responseMessage = await client.GetAsync(input.TemplateSource, CancellationTokenProvider.Token); + } + + await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage); + + return await responseMessage.Content.ReadAsByteArrayAsync(); } - - await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage); - - return await responseMessage.Content.ReadAsByteArrayAsync(); + } + catch (Exception ex) + { + Console.WriteLine("Error occured while downloading source-code from {0} : {1}", url, ex.Message); + throw; } } - private bool IsNetworkSource(string source) + private static bool IsNetworkSource(string source) { return source.ToLower().StartsWith("http"); } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs index f7d9eaf3be..924fdaf2c9 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs @@ -8,6 +8,7 @@ using Volo.Abp.Cli.Commands; using Volo.Abp.Cli.Licensing; using Volo.Abp.Cli.ProjectBuilding.Analyticses; using Volo.Abp.Cli.ProjectBuilding.Building; +using Volo.Abp.Cli.ProjectBuilding.Templates.App; using Volo.Abp.DependencyInjection; using Volo.Abp.Json; @@ -55,9 +56,16 @@ namespace Volo.Abp.Cli.ProjectBuilding ); var apiKeyResult = await ApiKeyService.GetApiKeyOrNullAsync(); - if (apiKeyResult?.ApiKey != null) + if (apiKeyResult != null) { - args.ExtraProperties["api-key"] = apiKeyResult.ApiKey; + if (apiKeyResult.ApiKey != null) + { + args.ExtraProperties["api-key"] = apiKeyResult.ApiKey; + } + else if (templateInfo.Name == AppProTemplate.TemplateName) + { + throw new UserFriendlyException(apiKeyResult.ErrorMessage); + } } if (apiKeyResult?.LicenseCode != null) @@ -82,7 +90,7 @@ namespace Volo.Abp.Cli.ProjectBuilding // Exclude unwanted or known options. var options = args.ExtraProperties .Where(x => !x.Key.Equals(CliConsts.Command, StringComparison.InvariantCultureIgnoreCase)) - .Where(x => !x.Key.Equals("tiered", StringComparison.InvariantCultureIgnoreCase)) + .Where(x => !x.Key.Equals(NewCommand.Options.Tiered.Long, StringComparison.InvariantCultureIgnoreCase)) .Where(x => !x.Key.Equals(NewCommand.Options.DatabaseProvider.Long, StringComparison.InvariantCultureIgnoreCase) && !x.Key.Equals(NewCommand.Options.DatabaseProvider.Short, StringComparison.InvariantCultureIgnoreCase)) .Where(x => !x.Key.Equals(NewCommand.Options.OutputFolder.Long, StringComparison.InvariantCultureIgnoreCase) && @@ -102,7 +110,7 @@ namespace Volo.Abp.Cli.ProjectBuilding Tool = Options.ToolName, Command = args.ExtraProperties.ContainsKey(CliConsts.Command) ? args.ExtraProperties[CliConsts.Command] : "", DatabaseProvider = args.DatabaseProvider.ToProviderName(), - IsTiered = args.ExtraProperties.ContainsKey("tiered"), + IsTiered = args.ExtraProperties.ContainsKey(NewCommand.Options.Tiered.Long), UiFramework = args.UiFramework.ToFrameworkName(), Options = JsonSerializer.Serialize(options), ProjectName = args.SolutionName.FullName, diff --git a/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj b/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj index 0ccc8990d4..50fb328387 100644 --- a/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj +++ b/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj @@ -16,15 +16,15 @@ - - - - - - - - - + + + + + + + + + diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/RemoteServiceAttribute.cs b/framework/src/Volo.Abp.Core/Volo/Abp/RemoteServiceAttribute.cs index e866022437..84e46e2709 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/RemoteServiceAttribute.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/RemoteServiceAttribute.cs @@ -17,6 +17,13 @@ namespace Volo.Abp /// public bool IsMetadataEnabled { get; set; } + /// + /// Group name of the remote service. + /// Group names of all services of a module expected to be the same. + /// This name is also used to distinguish the service endpoint of this group. + /// + public string Name { get; set; } + public RemoteServiceAttribute(bool isEnabled = true) { IsEnabled = isEnabled; diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo.Abp.EntityFrameworkCore.SqlServer.csproj b/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo.Abp.EntityFrameworkCore.SqlServer.csproj index bc88ef83d1..74d9e15537 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo.Abp.EntityFrameworkCore.SqlServer.csproj +++ b/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo.Abp.EntityFrameworkCore.SqlServer.csproj @@ -19,7 +19,7 @@ - + diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo.Abp.EntityFrameworkCore.Sqlite.csproj b/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo.Abp.EntityFrameworkCore.Sqlite.csproj index 7747d7faf2..385ad9068a 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo.Abp.EntityFrameworkCore.Sqlite.csproj +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo.Abp.EntityFrameworkCore.Sqlite.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.csproj b/framework/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.csproj index d0d0c58601..a1418c84d3 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.csproj +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.csproj @@ -20,8 +20,8 @@ - - + + diff --git a/framework/src/Volo.Abp.Http.Client/Volo.Abp.Http.Client.csproj b/framework/src/Volo.Abp.Http.Client/Volo.Abp.Http.Client.csproj index 99f480ee63..8607f32a35 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo.Abp.Http.Client.csproj +++ b/framework/src/Volo.Abp.Http.Client/Volo.Abp.Http.Client.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ApplicationApiDescriptionModel.cs b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ApplicationApiDescriptionModel.cs index fad94b3745..cc09b7a153 100644 --- a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ApplicationApiDescriptionModel.cs +++ b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ApplicationApiDescriptionModel.cs @@ -36,9 +36,9 @@ namespace Volo.Abp.Http.Modeling return Modules[module.RootPath] = module; } - public ModuleApiDescriptionModel GetOrAddModule(string rootPath) + public ModuleApiDescriptionModel GetOrAddModule(string rootPath, string remoteServiceName) { - return Modules.GetOrAdd(rootPath, () => ModuleApiDescriptionModel.Create(rootPath)); + return Modules.GetOrAdd(rootPath, () => ModuleApiDescriptionModel.Create(rootPath, remoteServiceName)); } public ApplicationApiDescriptionModel CreateSubModel(string[] modules = null, string[] controllers = null, string[] actions = null) diff --git a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ModuleApiDescriptionModel.cs b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ModuleApiDescriptionModel.cs index 44967fa50c..b879b90135 100644 --- a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ModuleApiDescriptionModel.cs +++ b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ModuleApiDescriptionModel.cs @@ -11,10 +11,17 @@ namespace Volo.Abp.Http.Modeling /// /// "app". /// - public const string DefaultRootPath = "app"; + public const string DefaultRootPath = "app"; + /// + /// "Default". + /// + public const string DefaultRemoteServiceName = "Default"; + public string RootPath { get; set; } + public string RemoteServiceName { get; set; } + public IDictionary Controllers { get; set; } private ModuleApiDescriptionModel() @@ -22,11 +29,12 @@ namespace Volo.Abp.Http.Modeling } - public static ModuleApiDescriptionModel Create(string rootPath) + public static ModuleApiDescriptionModel Create(string rootPath, string remoteServiceName) { return new ModuleApiDescriptionModel { RootPath = rootPath, + RemoteServiceName = remoteServiceName, Controllers = new Dictionary() }; } @@ -48,7 +56,7 @@ namespace Volo.Abp.Http.Modeling public ModuleApiDescriptionModel CreateSubModel(string[] controllers, string[] actions) { - var subModel = Create(RootPath); + var subModel = Create(RootPath, RemoteServiceName); foreach (var controller in Controllers.Values) { diff --git a/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj b/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj index afda5e0002..ce26fe7bea 100644 --- a/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj +++ b/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj @@ -16,7 +16,7 @@ - + diff --git a/framework/src/Volo.Abp.VirtualFileSystem/Volo.Abp.VirtualFileSystem.csproj b/framework/src/Volo.Abp.VirtualFileSystem/Volo.Abp.VirtualFileSystem.csproj index 2ba15cae3d..46995e4eb4 100644 --- a/framework/src/Volo.Abp.VirtualFileSystem/Volo.Abp.VirtualFileSystem.csproj +++ b/framework/src/Volo.Abp.VirtualFileSystem/Volo.Abp.VirtualFileSystem.csproj @@ -15,8 +15,8 @@ - - + + diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Modals.cshtml b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Modals.cshtml index 74116488ad..ad2f4a602c 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Modals.cshtml +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Modals.cshtml @@ -45,16 +45,16 @@
-

-<abp-button button-type="Primary" data-toggle="modal" data-target="#myModal">Launch modal</abp-button>
-
-<abp-modal centered="true" size="Large" id="myModal">
-   <abp-modal-header title="Modal title"></abp-modal-header>
-   <abp-modal-body>
-       Woohoo, you're reading this text in a modal!
-   </abp-modal-body>
-   <abp-modal-footer buttons="(AbpModalButtons.Save|AbpModalButtons.Close)"></abp-modal-footer>
-</abp-modal>
+                

+    <abp-button button-type="Primary" data-toggle="modal" data-target="#myModal">Launch modal</abp-button>
+
+    <abp-modal centered="true" size="Large" id="myModal">
+    <abp-modal-header title="Modal title"></abp-modal-header>
+    <abp-modal-body>
+    Woohoo, you're reading this text in a modal!
+    </abp-modal-body>
+    <abp-modal-footer buttons="@(AbpModalButtons.Save|AbpModalButtons.Close)"></abp-modal-footer>
+    </abp-modal>
 
diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/AccountRemoteServiceConsts.cs b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/AccountRemoteServiceConsts.cs new file mode 100644 index 0000000000..43e5ca15fa --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/AccountRemoteServiceConsts.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.Account +{ + public static class AccountRemoteServiceConsts + { + public const string RemoteServiceName = "AbpAccount"; + } +} \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.HttpApi.Client/Volo/Abp/Account/AbpAccountHttpApiClientModule.cs b/modules/account/src/Volo.Abp.Account.HttpApi.Client/Volo/Abp/Account/AbpAccountHttpApiClientModule.cs index 2cfba522cb..a1eb2f9263 100644 --- a/modules/account/src/Volo.Abp.Account.HttpApi.Client/Volo/Abp/Account/AbpAccountHttpApiClientModule.cs +++ b/modules/account/src/Volo.Abp.Account.HttpApi.Client/Volo/Abp/Account/AbpAccountHttpApiClientModule.cs @@ -9,11 +9,10 @@ namespace Volo.Abp.Account typeof(AbpHttpClientModule))] public class AbpAccountHttpApiClientModule : AbpModule { - public const string RemoteServiceName = "Account"; - public override void ConfigureServices(ServiceConfigurationContext context) { - context.Services.AddHttpClientProxies(typeof(AbpAccountApplicationContractsModule).Assembly, RemoteServiceName); + context.Services.AddHttpClientProxies(typeof(AbpAccountApplicationContractsModule).Assembly, + AccountRemoteServiceConsts.RemoteServiceName); } } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.HttpApi/Volo/Abp/Account/AccountController.cs b/modules/account/src/Volo.Abp.Account.HttpApi/Volo/Abp/Account/AccountController.cs index e175607842..fa479568aa 100644 --- a/modules/account/src/Volo.Abp.Account.HttpApi/Volo/Abp/Account/AccountController.cs +++ b/modules/account/src/Volo.Abp.Account.HttpApi/Volo/Abp/Account/AccountController.cs @@ -5,7 +5,7 @@ using Volo.Abp.Identity; namespace Volo.Abp.Account { - [RemoteService] + [RemoteService(Name = AccountRemoteServiceConsts.RemoteServiceName)] [Area("account")] [Route("api/account")] public class AccountController : AbpController, IAccountAppService diff --git a/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs b/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs index 4a1689e8e9..1cfc96091a 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs @@ -15,7 +15,7 @@ using IdentityUser = Volo.Abp.Identity.IdentityUser; namespace Volo.Abp.Account.Web.Areas.Account.Controllers { - [RemoteService] + [RemoteService(Name = AccountRemoteServiceConsts.RemoteServiceName)] [Controller] [ControllerName("Login")] [Area("Account")] diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Shared/Volo.Abp.BackgroundJobs.DemoApp.Shared.csproj b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Shared/Volo.Abp.BackgroundJobs.DemoApp.Shared.csproj index 582cc3d634..3c942ccf89 100644 --- a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Shared/Volo.Abp.BackgroundJobs.DemoApp.Shared.csproj +++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Shared/Volo.Abp.BackgroundJobs.DemoApp.Shared.csproj @@ -7,7 +7,7 @@ - + diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Volo.Abp.BackgroundJobs.DemoApp.csproj b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Volo.Abp.BackgroundJobs.DemoApp.csproj index b3bc53a2ed..062db7437c 100644 --- a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Volo.Abp.BackgroundJobs.DemoApp.csproj +++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Volo.Abp.BackgroundJobs.DemoApp.csproj @@ -6,7 +6,7 @@ - + all runtime; build; native; contentfiles; analyzers diff --git a/modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.csproj b/modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.csproj index 918c42c1ad..16fc44f6e3 100644 --- a/modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.csproj +++ b/modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.csproj @@ -17,8 +17,8 @@ - - + + diff --git a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/BloggingRemoteServiceConsts.cs b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/BloggingRemoteServiceConsts.cs new file mode 100644 index 0000000000..e11f75adfb --- /dev/null +++ b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/BloggingRemoteServiceConsts.cs @@ -0,0 +1,7 @@ +namespace Volo.Blogging +{ + public static class BloggingRemoteServiceConsts + { + public const string RemoteServiceName = "Blogging"; + } +} diff --git a/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Blogs/BlogEto.cs b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Blogs/BlogEto.cs new file mode 100644 index 0000000000..ceb0b977cf --- /dev/null +++ b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Blogs/BlogEto.cs @@ -0,0 +1,20 @@ +using System; +using JetBrains.Annotations; + +namespace Volo.Blogging.Blogs +{ + [Serializable] + public class BlogEto + { + public Guid Id { get; set; } + + [NotNull] + public string Name { get; set; } + + [NotNull] + public string ShortName { get; set; } + + [CanBeNull] + public string Description { get; set; } + } +} \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Comments/CommentEto.cs b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Comments/CommentEto.cs new file mode 100644 index 0000000000..dd1b5ccb41 --- /dev/null +++ b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Comments/CommentEto.cs @@ -0,0 +1,16 @@ +using System; + +namespace Volo.Blogging.Comments +{ + [Serializable] + public class CommentEto + { + public Guid Id { get; set; } + + public Guid PostId { get; set; } + + public Guid? RepliedCommentId { get; set; } + + public string Text { get; set; } + } +} \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Posts/PostEto.cs b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Posts/PostEto.cs new file mode 100644 index 0000000000..90a88833c7 --- /dev/null +++ b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Posts/PostEto.cs @@ -0,0 +1,29 @@ +using JetBrains.Annotations; +using System; +using System.Collections.Generic; +using Volo.Blogging.Tagging; + +namespace Volo.Blogging.Posts +{ + [Serializable] + public class PostEto + { + public Guid Id { get; set; } + + public Guid BlogId { get; set; } + + [NotNull] + public string Url { get; set; } + + [NotNull] + public string CoverImage { get; set; } + + [NotNull] + public string Title { get; set; } + + [CanBeNull] + public string Content { get; set; } + + public int ReadCount { get; set; } + } +} \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Tagging/TagEto.cs b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Tagging/TagEto.cs new file mode 100644 index 0000000000..0f461a0281 --- /dev/null +++ b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Tagging/TagEto.cs @@ -0,0 +1,20 @@ +using System; +using JetBrains.Annotations; + +namespace Volo.Blogging.Tagging +{ + [Serializable] + public class TagEto + { + public Guid Id { get; set; } + + public Guid BlogId { get; set; } + + [NotNull] + public string Name { get; set; } + + public string Description { get; set; } + + public int UsageCount { get; set; } + } +} \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Domain/Volo.Blogging.Domain.csproj b/modules/blogging/src/Volo.Blogging.Domain/Volo.Blogging.Domain.csproj index a7cbc2c7c6..73cf0498c5 100644 --- a/modules/blogging/src/Volo.Blogging.Domain/Volo.Blogging.Domain.csproj +++ b/modules/blogging/src/Volo.Blogging.Domain/Volo.Blogging.Domain.csproj @@ -13,6 +13,7 @@ + diff --git a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/BloggingDomainMappingProfile.cs b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/BloggingDomainMappingProfile.cs new file mode 100644 index 0000000000..da36b39049 --- /dev/null +++ b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/BloggingDomainMappingProfile.cs @@ -0,0 +1,19 @@ +using AutoMapper; +using Volo.Blogging.Blogs; +using Volo.Blogging.Comments; +using Volo.Blogging.Posts; +using Volo.Blogging.Tagging; + +namespace Volo.Blogging +{ + public class BloggingDomainMappingProfile : Profile + { + public BloggingDomainMappingProfile() + { + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + } + } +} \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/BloggingDomainModule.cs b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/BloggingDomainModule.cs index 4690546a7e..f39c4c88fb 100644 --- a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/BloggingDomainModule.cs +++ b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/BloggingDomainModule.cs @@ -1,13 +1,37 @@ -using Volo.Abp.Domain; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.AutoMapper; +using Volo.Abp.Domain; +using Volo.Abp.EventBus.Distributed; using Volo.Abp.Modularity; +using Volo.Blogging.Blogs; +using Volo.Blogging.Comments; +using Volo.Blogging.Posts; +using Volo.Blogging.Tagging; namespace Volo.Blogging { [DependsOn( typeof(BloggingDomainSharedModule), - typeof(AbpDddDomainModule))] + typeof(AbpDddDomainModule), + typeof(AbpAutoMapperModule))] public class BloggingDomainModule : AbpModule { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAutoMapperObjectMapper(); + Configure(options => + { + options.AddProfile(validate: true); + }); + + Configure(options => + { + options.EtoMappings.Add(typeof(BloggingDomainModule)); + options.EtoMappings.Add(typeof(BloggingDomainModule)); + options.EtoMappings.Add(typeof(BloggingDomainModule)); + options.EtoMappings.Add(typeof(BloggingDomainModule)); + }); + } } } diff --git a/modules/blogging/src/Volo.Blogging.HttpApi.Client/Volo/Blogging/BloggingHttpApiClientModule.cs b/modules/blogging/src/Volo.Blogging.HttpApi.Client/Volo/Blogging/BloggingHttpApiClientModule.cs index 7e1418cbb0..0b33ff3367 100644 --- a/modules/blogging/src/Volo.Blogging.HttpApi.Client/Volo/Blogging/BloggingHttpApiClientModule.cs +++ b/modules/blogging/src/Volo.Blogging.HttpApi.Client/Volo/Blogging/BloggingHttpApiClientModule.cs @@ -9,11 +9,10 @@ namespace Volo.Blogging typeof(AbpHttpClientModule))] public class BloggingHttpApiClientModule : AbpModule { - public const string RemoteServiceName = "Blogging"; - public override void ConfigureServices(ServiceConfigurationContext context) { - context.Services.AddHttpClientProxies(typeof(BloggingApplicationContractsModule).Assembly, RemoteServiceName); + context.Services.AddHttpClientProxies(typeof(BloggingApplicationContractsModule).Assembly, + BloggingRemoteServiceConsts.RemoteServiceName); } } diff --git a/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/BlogFilesController.cs b/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/BlogFilesController.cs index 818435a78c..f71a0af6c2 100644 --- a/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/BlogFilesController.cs +++ b/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/BlogFilesController.cs @@ -10,7 +10,7 @@ using Volo.Blogging.Files; namespace Volo.Blogging { - [RemoteService] + [RemoteService(Name = BloggingRemoteServiceConsts.RemoteServiceName)] [Area("blogging")] [Route("api/blogging/files")] public class BlogFilesController : AbpController, IFileAppService diff --git a/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/BlogsController.cs b/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/BlogsController.cs index 084afb958a..cb67ac3fb7 100644 --- a/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/BlogsController.cs +++ b/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/BlogsController.cs @@ -9,7 +9,7 @@ using Volo.Blogging.Blogs.Dtos; namespace Volo.Blogging { - [RemoteService] + [RemoteService(Name = BloggingRemoteServiceConsts.RemoteServiceName)] [Area("blogging")] [Route("api/blogging/blogs")] public class BlogsController : AbpController, IBlogAppService diff --git a/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/CommentsController.cs b/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/CommentsController.cs index 270d8f1e13..caea1cfa2f 100644 --- a/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/CommentsController.cs +++ b/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/CommentsController.cs @@ -9,7 +9,7 @@ using Volo.Blogging.Comments.Dtos; namespace Volo.Blogging { - [RemoteService] + [RemoteService(Name = BloggingRemoteServiceConsts.RemoteServiceName)] [Area("blogging")] [Route("api/blogging/comments")] public class CommentsController : AbpController, ICommentAppService diff --git a/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/PostsController.cs b/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/PostsController.cs index 332f60c256..f7a1c01703 100644 --- a/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/PostsController.cs +++ b/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/PostsController.cs @@ -8,7 +8,7 @@ using Volo.Blogging.Posts; namespace Volo.Blogging { - [RemoteService] + [RemoteService(Name = BloggingRemoteServiceConsts.RemoteServiceName)] [Area("blogging")] [Route("api/blogging/posts")] public class PostsController : AbpController, IPostAppService diff --git a/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/TagsController.cs b/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/TagsController.cs index ede42dd264..6f17623a5e 100644 --- a/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/TagsController.cs +++ b/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/TagsController.cs @@ -9,7 +9,7 @@ using Volo.Blogging.Tagging.Dtos; namespace Volo.Blogging { - [RemoteService] + [RemoteService(Name = BloggingRemoteServiceConsts.RemoteServiceName)] [Area("blogging")] [Route("api/blogging/tags")] public class TagsController : AbpController, ITagAppService diff --git a/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs b/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs index 4bc793f799..57ade1bb4b 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs +++ b/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs @@ -23,8 +23,8 @@ namespace Volo.Docs.Admin.Documents public DocumentAdminAppService(IProjectRepository projectRepository, IDocumentRepository documentRepository, - IDocumentSourceFactory documentStoreFactory, - IDistributedCache documentUpdateCache, + IDocumentSourceFactory documentStoreFactory, + IDistributedCache documentUpdateCache, IDocumentFullSearch documentFullSearch) { _projectRepository = projectRepository; @@ -91,11 +91,21 @@ namespace Volo.Docs.Admin.Documents foreach (var doc in docs) { var project = projects.FirstOrDefault(x => x.Id == doc.ProjectId); - if (project != null && (doc.FileName == project.NavigationDocumentName || doc.FileName == project.ParametersDocumentName)) + if (project == null) { continue; } - + + if (doc.FileName == project.NavigationDocumentName) + { + continue; + } + + if (doc.FileName == project.ParametersDocumentName) + { + continue; + } + await _documentFullSearch.AddOrUpdateAsync(doc); } } diff --git a/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Documents/DocumentEto.cs b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Documents/DocumentEto.cs new file mode 100644 index 0000000000..12f62f8b6d --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Documents/DocumentEto.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; + +namespace Volo.Docs.Documents +{ + [Serializable] + public class DocumentEto + { + public Guid Id { get; set; } + + public Guid ProjectId { get; set; } + + public string Name { get; set; } + + public string Version { get; set; } + + public string LanguageCode { get; set; } + + public string FileName { get; set; } + + public string Content { get; set; } + + public string Format { get; set; } + + public string EditLink { get; set; } + + public string RootUrl { get; set; } + + public string RawRootUrl { get; set; } + + public string LocalDirectory { get; set; } + + public DateTime CreationTime { get; set; } + + public DateTime LastUpdatedTime { get; set; } + + public DateTime? LastSignificantUpdateTime { get; set; } + + public DateTime LastCachedTime { get; set; } + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Projects/ProjectEto.cs b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Projects/ProjectEto.cs new file mode 100644 index 0000000000..dae1affae4 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Projects/ProjectEto.cs @@ -0,0 +1,30 @@ +using System; + +namespace Volo.Docs.Projects +{ + [Serializable] + public class ProjectEto + { + public Guid Id { get; set; } + + public string Name { get; set; } + + public string ShortName { get; set; } + + public string Format { get; set; } + + public string DefaultDocumentName { get; set; } + + public string NavigationDocumentName { get; set; } + + public string ParametersDocumentName { get; set; } + + public string MinimumVersion { get; set; } + + public string DocumentStoreType { get; set; } + + public string MainWebsiteUrl { get; set; } + + public string LatestVersionBranchName { get; set; } + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo.Docs.Domain.csproj b/modules/docs/src/Volo.Docs.Domain/Volo.Docs.Domain.csproj index c2540754a3..5331433e24 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo.Docs.Domain.csproj +++ b/modules/docs/src/Volo.Docs.Domain/Volo.Docs.Domain.csproj @@ -16,7 +16,7 @@ - + @@ -25,6 +25,7 @@ + diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainMappingProfile.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainMappingProfile.cs new file mode 100644 index 0000000000..74f7224ea6 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainMappingProfile.cs @@ -0,0 +1,15 @@ +using AutoMapper; +using Volo.Docs.Documents; +using Volo.Docs.Projects; + +namespace Volo.Docs +{ + public class DocsDomainMappingProfile : Profile + { + public DocsDomainMappingProfile() + { + CreateMap(); + CreateMap(); + } + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainModule.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainModule.cs index ba2ee6018d..5e53b858ce 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainModule.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainModule.cs @@ -2,7 +2,9 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Volo.Abp; +using Volo.Abp.AutoMapper; using Volo.Abp.Domain; +using Volo.Abp.EventBus.Distributed; using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.Threading; @@ -12,17 +14,32 @@ using Volo.Docs.Documents.FullSearch.Elastic; using Volo.Docs.FileSystem.Documents; using Volo.Docs.GitHub.Documents; using Volo.Docs.Localization; +using Volo.Docs.Projects; namespace Volo.Docs { [DependsOn( typeof(DocsDomainSharedModule), - typeof(AbpDddDomainModule) + typeof(AbpDddDomainModule), + typeof(AbpAutoMapperModule) )] public class DocsDomainModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { + context.Services.AddAutoMapperObjectMapper(); + + Configure(options => + { + options.AddProfile(validate: true); + }); + + Configure(options => + { + options.EtoMappings.Add(typeof(DocsDomainModule)); + options.EtoMappings.Add(typeof(DocsDomainModule)); + }); + Configure(options => { options.FileSets diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/ElasticDocumentFullSearch.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/ElasticDocumentFullSearch.cs index 4574633318..51ecd817b5 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/ElasticDocumentFullSearch.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/ElasticDocumentFullSearch.cs @@ -23,7 +23,7 @@ namespace Volo.Docs.Documents.FullSearch.Elastic public async Task CreateIndexIfNeededAsync(CancellationToken cancellationToken = default) { - CheckEsEnabled(); + ValidateElasticSearchEnabled(); var client = _clientProvider.GetClient(); @@ -51,11 +51,11 @@ namespace Volo.Docs.Documents.FullSearch.Elastic public async Task AddOrUpdateAsync(Document document, CancellationToken cancellationToken = default) { - CheckEsEnabled(); + ValidateElasticSearchEnabled(); var client = _clientProvider.GetClient(); - var existsResponse = await client.DocumentExistsAsync(DocumentPath.Id(document.Id), + var existsResponse = await client.DocumentExistsAsync(DocumentPath.Id(document.Id), x => x.Index(_options.IndexName), cancellationToken); HandleError(existsResponse); @@ -73,12 +73,12 @@ namespace Volo.Docs.Documents.FullSearch.Elastic if (!existsResponse.Exists) { - HandleError(await client.IndexAsync(esDocument, + HandleError(await client.IndexAsync(esDocument, x => x.Id(document.Id).Index(_options.IndexName), cancellationToken)); } else { - HandleError(await client.UpdateAsync(DocumentPath.Id(document.Id), + HandleError(await client.UpdateAsync(DocumentPath.Id(document.Id), x => x.Doc(esDocument).Index(_options.IndexName), cancellationToken)); } @@ -86,7 +86,7 @@ namespace Volo.Docs.Documents.FullSearch.Elastic public async Task DeleteAsync(Guid id, CancellationToken cancellationToken = default) { - CheckEsEnabled(); + ValidateElasticSearchEnabled(); HandleError(await _clientProvider.GetClient() .DeleteAsync(DocumentPath.Id(id), x => x.Index(_options.IndexName), cancellationToken)); @@ -96,7 +96,7 @@ namespace Volo.Docs.Documents.FullSearch.Elastic string version, int? skipCount = null, int? maxResultCount = null, CancellationToken cancellationToken = default) { - CheckEsEnabled(); + ValidateElasticSearchEnabled(); var request = new SearchRequest { @@ -150,7 +150,6 @@ namespace Volo.Docs.Documents.FullSearch.Elastic } }; - //var json = _clientProvider.GetClient().RequestResponseSerializer.SerializeToString(request); var response = await _clientProvider.GetClient().SearchAsync(request, cancellationToken); HandleError(response); @@ -178,7 +177,7 @@ namespace Volo.Docs.Documents.FullSearch.Elastic } } - protected void CheckEsEnabled() + protected void ValidateElasticSearchEnabled() { if (!_options.Enable) { diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml index 68ba541938..67e5352e22 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml @@ -90,7 +90,10 @@
- +
@@ -109,7 +112,10 @@ - + @@ -127,7 +133,10 @@ - + @@ -142,7 +151,12 @@ - + @@ -156,7 +170,12 @@ - + @@ -204,7 +223,9 @@ @@ -216,7 +237,11 @@ { + class="rounded-circle" + alt="Avatar" + height="21" + width="21" + title="@contributor.Username" /> } } @@ -290,9 +315,7 @@
-
-
@L["InThisDocument"]
@@ -302,10 +325,8 @@ @L["GoToTop"]
- - } else { @@ -318,7 +339,6 @@ } - } diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/FeatureManagementRemoteServiceConsts.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/FeatureManagementRemoteServiceConsts.cs new file mode 100644 index 0000000000..749805da05 --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/FeatureManagementRemoteServiceConsts.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.FeatureManagement +{ + public class FeatureManagementRemoteServiceConsts + { + public const string RemoteServiceName = "FeatureManagement"; + } +} \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.HttpApi.Client/Volo/Abp/FeatureManagement/AbpFeatureManagementHttpApiClientModule.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.HttpApi.Client/Volo/Abp/FeatureManagement/AbpFeatureManagementHttpApiClientModule.cs index 002a7c3a9a..1bfd2a752c 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.HttpApi.Client/Volo/Abp/FeatureManagement/AbpFeatureManagementHttpApiClientModule.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.HttpApi.Client/Volo/Abp/FeatureManagement/AbpFeatureManagementHttpApiClientModule.cs @@ -9,13 +9,11 @@ namespace Volo.Abp.FeatureManagement typeof(AbpHttpClientModule))] public class AbpFeatureManagementHttpApiClientModule : AbpModule { - public const string RemoteServiceName = "AbpFeatureManagement"; - public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddHttpClientProxies( typeof(AbpFeatureManagementApplicationContractsModule).Assembly, - RemoteServiceName + FeatureManagementRemoteServiceConsts.RemoteServiceName ); } } diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.HttpApi/Volo/Abp/FeatureManagement/FeaturesController.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.HttpApi/Volo/Abp/FeatureManagement/FeaturesController.cs index a56ff24275..e3eda46033 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.HttpApi/Volo/Abp/FeatureManagement/FeaturesController.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.HttpApi/Volo/Abp/FeatureManagement/FeaturesController.cs @@ -4,7 +4,7 @@ using Volo.Abp.AspNetCore.Mvc; namespace Volo.Abp.FeatureManagement { - [RemoteService] + [RemoteService(Name = FeatureManagementRemoteServiceConsts.RemoteServiceName)] [Area("abp")] public class FeaturesController : AbpController, IFeatureAppService { diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityRemoteServiceConsts.cs b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityRemoteServiceConsts.cs new file mode 100644 index 0000000000..2e151f54b7 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityRemoteServiceConsts.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.Identity +{ + public static class IdentityRemoteServiceConsts + { + public const string RemoteServiceName = "AbpIdentity"; + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityClaimTypeEto.cs b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityClaimTypeEto.cs new file mode 100644 index 0000000000..2d0dd4ebfc --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityClaimTypeEto.cs @@ -0,0 +1,24 @@ +using System; + +namespace Volo.Abp.Identity +{ + [Serializable] + public class IdentityClaimTypeEto + { + public Guid Id { get; set; } + + public string Name { get; set; } + + public bool Required { get; set; } + + public bool IsStatic { get; set; } + + public string Regex { get; set; } + + public string RegexDescription { get; set; } + + public string Description { get; set; } + + public IdentityClaimValueType ValueType { get; set; } + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityRoleEto.cs b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityRoleEto.cs new file mode 100644 index 0000000000..8e91eadf72 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityRoleEto.cs @@ -0,0 +1,20 @@ +using System; + +namespace Volo.Abp.Identity +{ + [Serializable] + public class IdentityRoleEto + { + public Guid Id { get; set; } + + public Guid? TenantId { get; set; } + + public string Name { get; set; } + + public bool IsDefault { get; set; } + + public bool IsStatic { get; set; } + + public bool IsPublic { get; set; } + } +} \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.csproj b/modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.csproj index f6eb1df909..fa22210db0 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.csproj +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.csproj @@ -25,11 +25,12 @@ + - + diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityDomainModule.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityDomainModule.cs index 1bb065017e..12af875bab 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityDomainModule.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityDomainModule.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; +using Volo.Abp.AutoMapper; using Volo.Abp.Domain; using Volo.Abp.EventBus.Distributed; using Volo.Abp.Modularity; @@ -12,17 +13,27 @@ namespace Volo.Abp.Identity [DependsOn( typeof(AbpDddDomainModule), typeof(AbpIdentityDomainSharedModule), - typeof(AbpUsersDomainModule) + typeof(AbpUsersDomainModule), + typeof(AbpAutoMapperModule) )] public class AbpIdentityDomainModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { - Configure(options => + context.Services.AddAutoMapperObjectMapper(); + + Configure(options => { - options.EtoMappings.Add(); + options.AddProfile(validate: true); }); + Configure(options => + { + options.EtoMappings.Add(typeof(AbpIdentityDomainModule)); + options.EtoMappings.Add(typeof(AbpIdentityDomainModule)); + options.EtoMappings.Add(typeof(AbpIdentityDomainModule)); + }); + var identityBuilder = context.Services.AddAbpIdentity(options => { options.User.RequireUniqueEmail = true; diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDomainMappingProfile.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDomainMappingProfile.cs new file mode 100644 index 0000000000..547525b46e --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDomainMappingProfile.cs @@ -0,0 +1,15 @@ +using AutoMapper; +using Volo.Abp.Users; + +namespace Volo.Abp.Identity +{ + public class IdentityDomainMappingProfile : Profile + { + public IdentityDomainMappingProfile() + { + CreateMap(); + CreateMap(); + CreateMap(); + } + } +} \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs index c6ad077456..51e15339ee 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs @@ -8,12 +8,11 @@ using Microsoft.AspNetCore.Identity; using Volo.Abp.Auditing; using Volo.Abp.Domain.Entities.Auditing; using Volo.Abp.Guids; -using Volo.Abp.ObjectMapping; using Volo.Abp.Users; namespace Volo.Abp.Identity { - public class IdentityUser : FullAuditedAggregateRoot, IUser, IMapTo + public class IdentityUser : FullAuditedAggregateRoot, IUser { public virtual Guid? TenantId { get; protected set; } @@ -281,36 +280,5 @@ namespace Volo.Abp.Identity { return $"{base.ToString()}, UserName = {UserName}"; } - - UserEto IMapTo.MapTo() - { - //TODO: Instead, consider to use automapper (but it makes dependency just for a small code part)?? - - return new UserEto - { - Name = Name, - Email = Email, - EmailConfirmed = EmailConfirmed, - Id = Id, - PhoneNumber = PhoneNumber, - PhoneNumberConfirmed = PhoneNumberConfirmed, - Surname = Surname, - TenantId = TenantId, - UserName = UserName - }; - } - - void IMapTo.MapTo(UserEto destination) - { - destination.Name = Name; - destination.Email = Email; - destination.EmailConfirmed = EmailConfirmed; - destination.Id = Id; - destination.PhoneNumber = PhoneNumber; - destination.PhoneNumberConfirmed = PhoneNumberConfirmed; - destination.Surname = Surname; - destination.TenantId = TenantId; - destination.UserName = UserName; - } } } diff --git a/modules/identity/src/Volo.Abp.Identity.HttpApi.Client/Volo/Abp/Identity/AbpIdentityHttpApiClientModule.cs b/modules/identity/src/Volo.Abp.Identity.HttpApi.Client/Volo/Abp/Identity/AbpIdentityHttpApiClientModule.cs index ed830a1212..d4283e06f5 100644 --- a/modules/identity/src/Volo.Abp.Identity.HttpApi.Client/Volo/Abp/Identity/AbpIdentityHttpApiClientModule.cs +++ b/modules/identity/src/Volo.Abp.Identity.HttpApi.Client/Volo/Abp/Identity/AbpIdentityHttpApiClientModule.cs @@ -9,13 +9,11 @@ namespace Volo.Abp.Identity typeof(AbpHttpClientModule))] public class AbpIdentityHttpApiClientModule : AbpModule { - public const string RemoteServiceName = "AbpIdentity"; - public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddHttpClientProxies( typeof(AbpIdentityApplicationContractsModule).Assembly, - RemoteServiceName + IdentityRemoteServiceConsts.RemoteServiceName ); } } diff --git a/modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/IdentityRoleController.cs b/modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/IdentityRoleController.cs index 451e4d49f7..5d563b127e 100644 --- a/modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/IdentityRoleController.cs +++ b/modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/IdentityRoleController.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Volo.Abp.Application.Dtos; @@ -7,7 +6,7 @@ using Volo.Abp.AspNetCore.Mvc; namespace Volo.Abp.Identity { - [RemoteService] + [RemoteService(Name = IdentityRemoteServiceConsts.RemoteServiceName)] [Area("identity")] [ControllerName("Role")] [Route("api/identity/roles")] diff --git a/modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/IdentityUserController.cs b/modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/IdentityUserController.cs index 43bdf844d7..b9b02a7150 100644 --- a/modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/IdentityUserController.cs +++ b/modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/IdentityUserController.cs @@ -6,7 +6,7 @@ using Volo.Abp.AspNetCore.Mvc; namespace Volo.Abp.Identity { - [RemoteService] + [RemoteService(Name = IdentityRemoteServiceConsts.RemoteServiceName)] [Area("identity")] [ControllerName("User")] [Route("api/identity/users")] diff --git a/modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/IdentityUserLookupController.cs b/modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/IdentityUserLookupController.cs index 6bd3bec020..2f8011bf7f 100644 --- a/modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/IdentityUserLookupController.cs +++ b/modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/IdentityUserLookupController.cs @@ -6,7 +6,7 @@ using Volo.Abp.Users; namespace Volo.Abp.Identity { - [RemoteService] + [RemoteService(Name = IdentityRemoteServiceConsts.RemoteServiceName)] [Area("identity")] [ControllerName("UserLookup")] [Route("api/identity/users/lookup")] diff --git a/modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/ProfileController.cs b/modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/ProfileController.cs index d6ed67a7b8..91b1bc8325 100644 --- a/modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/ProfileController.cs +++ b/modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/ProfileController.cs @@ -4,7 +4,7 @@ using Volo.Abp.AspNetCore.Mvc; namespace Volo.Abp.Identity { - [RemoteService] + [RemoteService(Name = IdentityRemoteServiceConsts.RemoteServiceName)] [Area("identity")] [ControllerName("Profile")] [Route("/api/identity/my-profile")] diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/ApiResources/ApiResourceEto.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/ApiResources/ApiResourceEto.cs new file mode 100644 index 0000000000..1130b0bc92 --- /dev/null +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/ApiResources/ApiResourceEto.cs @@ -0,0 +1,20 @@ +using System; +using JetBrains.Annotations; + +namespace Volo.Abp.IdentityServer.ApiResources +{ + [Serializable] + public class ApiResourceEto + { + public Guid Id { get; set; } + + [NotNull] + public string Name { get; set; } + + public string DisplayName { get; set; } + + public string Description { get; set; } + + public bool Enabled { get; set; } + } +} \ No newline at end of file diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientEto.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientEto.cs new file mode 100644 index 0000000000..e5957eef5a --- /dev/null +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientEto.cs @@ -0,0 +1,84 @@ +using System; + +namespace Volo.Abp.IdentityServer.Clients +{ + [Serializable] + public class ClientEto + { + public Guid Id { get; set; } + + public string ClientId { get; set; } + + public string ClientName { get; set; } + + public string Description { get; set; } + + public string ClientUri { get; set; } + + public string LogoUri { get; set; } + + public bool Enabled { get; set; } = true; + + public string ProtocolType { get; set; } + + public bool RequireClientSecret { get; set; } + + public bool RequireConsent { get; set; } + + public bool AllowRememberConsent { get; set; } + + public bool AlwaysIncludeUserClaimsInIdToken { get; set; } + + public bool RequirePkce { get; set; } + + public bool AllowPlainTextPkce { get; set; } + + public bool AllowAccessTokensViaBrowser { get; set; } + + public string FrontChannelLogoutUri { get; set; } + + public bool FrontChannelLogoutSessionRequired { get; set; } + + public string BackChannelLogoutUri { get; set; } + + public bool BackChannelLogoutSessionRequired { get; set; } + + public bool AllowOfflineAccess { get; set; } + + public int IdentityTokenLifetime { get; set; } + + public int AccessTokenLifetime { get; set; } + + public int AuthorizationCodeLifetime { get; set; } + + public int? ConsentLifetime { get; set; } + + public int AbsoluteRefreshTokenLifetime { get; set; } + + public int SlidingRefreshTokenLifetime { get; set; } + + public int RefreshTokenUsage { get; set; } + + public bool UpdateAccessTokenClaimsOnRefresh { get; set; } + + public int RefreshTokenExpiration { get; set; } + + public int AccessTokenType { get; set; } + + public bool EnableLocalLogin { get; set; } + + public bool IncludeJwtId { get; set; } + + public bool AlwaysSendClientClaims { get; set; } + + public string ClientClaimsPrefix { get; set; } + + public string PairWiseSubjectSalt { get; set; } + + public int? UserSsoLifetime { get; set; } + + public string UserCodeType { get; set; } + + public int DeviceCodeLifetime { get; set; } + } +} \ No newline at end of file diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Devices/DeviceFlowCodesEto.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Devices/DeviceFlowCodesEto.cs new file mode 100644 index 0000000000..f82af68bbf --- /dev/null +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Devices/DeviceFlowCodesEto.cs @@ -0,0 +1,22 @@ +using System; + +namespace Volo.Abp.IdentityServer.Devices +{ + [Serializable] + public class DeviceFlowCodesEto + { + public Guid Id { get; set; } + + public string DeviceCode { get; set; } + + public string UserCode { get; set; } + + public string SubjectId { get; set; } + + public string ClientId { get; set; } + + public DateTime? Expiration { get; set; } + + public string Data { get; set; } + } +} \ No newline at end of file diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Grants/PersistedGrantEto.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Grants/PersistedGrantEto.cs new file mode 100644 index 0000000000..9d5db878f7 --- /dev/null +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Grants/PersistedGrantEto.cs @@ -0,0 +1,24 @@ +using System; + +namespace Volo.Abp.IdentityServer.Grants +{ + [Serializable] + public class PersistedGrantEto + { + public Guid Id { get; set; } + + public string Key { get; set; } + + public string Type { get; set; } + + public string SubjectId { get; set; } + + public string ClientId { get; set; } + + public DateTime CreationTime { get; set; } + + public DateTime? Expiration { get; set; } + + public string Data { get; set; } + } +} \ No newline at end of file diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/IdentityResources/IdentityResourceEto.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/IdentityResources/IdentityResourceEto.cs new file mode 100644 index 0000000000..c382642a9f --- /dev/null +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/IdentityResources/IdentityResourceEto.cs @@ -0,0 +1,24 @@ +using System; + +namespace Volo.Abp.IdentityServer.IdentityResources +{ + [Serializable] + public class IdentityResourceEto + { + public Guid Id { get; set; } + + public string Name { get; set; } + + public string DisplayName { get; set; } + + public string Description { get; set; } + + public bool Enabled { get; set; } + + public bool Required { get; set; } + + public bool Emphasize { get; set; } + + public bool ShowInDiscoveryDocument { get; set; } + } +} \ No newline at end of file diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs index 0ff798e7fd..ef1969fe24 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs @@ -6,7 +6,13 @@ using Microsoft.Extensions.Options; using Volo.Abp.AutoMapper; using Volo.Abp.BackgroundWorkers; using Volo.Abp.Caching; +using Volo.Abp.EventBus.Distributed; using Volo.Abp.Identity; +using Volo.Abp.IdentityServer.ApiResources; +using Volo.Abp.IdentityServer.Clients; +using Volo.Abp.IdentityServer.Devices; +using Volo.Abp.IdentityServer.Grants; +using Volo.Abp.IdentityServer.IdentityResources; using Volo.Abp.IdentityServer.Tokens; using Volo.Abp.Modularity; using Volo.Abp.Security; @@ -34,6 +40,14 @@ namespace Volo.Abp.IdentityServer options.AddProfile(validate: true); }); + Configure(options => + { + options.EtoMappings.Add(typeof(AbpIdentityServerDomainModule)); + options.EtoMappings.Add(typeof(AbpIdentityServerDomainModule)); + options.EtoMappings.Add(typeof(AbpIdentityServerDomainModule)); + options.EtoMappings.Add(typeof(AbpIdentityServerDomainModule)); + }); + AddIdentityServer(context.Services); } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityServerAutoMapperProfile.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityServerAutoMapperProfile.cs index ba1f44953c..e576d9413e 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityServerAutoMapperProfile.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityServerAutoMapperProfile.cs @@ -3,6 +3,7 @@ using System.Security.Claims; using AutoMapper; using Volo.Abp.IdentityServer.ApiResources; using Volo.Abp.IdentityServer.Clients; +using Volo.Abp.IdentityServer.Devices; using Volo.Abp.IdentityServer.Grants; using Volo.Abp.IdentityServer.IdentityResources; @@ -82,6 +83,12 @@ namespace Volo.Abp.IdentityServer CreateMap(MemberList.Destination) .ForMember(dest => dest.Type, opt => opt.Condition(srs => srs != null)) .ReverseMap(); + + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); } } } diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Application.Contracts/Volo/Abp/PermissionManagement/PermissionManagementRemoteServiceConsts.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.Application.Contracts/Volo/Abp/PermissionManagement/PermissionManagementRemoteServiceConsts.cs new file mode 100644 index 0000000000..4a9644b061 --- /dev/null +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Application.Contracts/Volo/Abp/PermissionManagement/PermissionManagementRemoteServiceConsts.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.PermissionManagement +{ + public class PermissionManagementRemoteServiceConsts + { + public const string RemoteServiceName = "AbpPermissionManagement"; + } +} \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.HttpApi.Client/Volo/Abp/PermissionManagement/AbpPermissionManagementHttpApiClientModule.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.HttpApi.Client/Volo/Abp/PermissionManagement/AbpPermissionManagementHttpApiClientModule.cs index 6bdc958780..35932bba56 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.HttpApi.Client/Volo/Abp/PermissionManagement/AbpPermissionManagementHttpApiClientModule.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.HttpApi.Client/Volo/Abp/PermissionManagement/AbpPermissionManagementHttpApiClientModule.cs @@ -9,13 +9,11 @@ namespace Volo.Abp.PermissionManagement typeof(AbpHttpClientModule))] public class AbpPermissionManagementHttpApiClientModule : AbpModule { - public const string RemoteServiceName = "AbpPermissionManagement"; - public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddHttpClientProxies( typeof(AbpPermissionManagementApplicationContractsModule).Assembly, - RemoteServiceName + PermissionManagementRemoteServiceConsts.RemoteServiceName ); } } diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.HttpApi/Volo/Abp/PermissionManagement/PermissionsController.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.HttpApi/Volo/Abp/PermissionManagement/PermissionsController.cs index 2dacd79d1f..2ed9a4d044 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.HttpApi/Volo/Abp/PermissionManagement/PermissionsController.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.HttpApi/Volo/Abp/PermissionManagement/PermissionsController.cs @@ -4,7 +4,7 @@ using Volo.Abp.AspNetCore.Mvc; namespace Volo.Abp.PermissionManagement { - [RemoteService] + [RemoteService(Name = PermissionManagementRemoteServiceConsts.RemoteServiceName)] [Area("abp")] public class PermissionsController : AbpController, IPermissionAppService { diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/TenantManagementRemoteServiceConsts.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/TenantManagementRemoteServiceConsts.cs new file mode 100644 index 0000000000..c820c1bd49 --- /dev/null +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/TenantManagementRemoteServiceConsts.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.TenantManagement +{ + public class TenantManagementRemoteServiceConsts + { + public const string RemoteServiceName = "AbpTenantManagement"; + } +} \ No newline at end of file diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.HttpApi.Client/Volo/Abp/TenantManagement/AbpTenantManagementHttpApiClientModule.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.HttpApi.Client/Volo/Abp/TenantManagement/AbpTenantManagementHttpApiClientModule.cs index 1cbdb36a10..7be0b53a72 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.HttpApi.Client/Volo/Abp/TenantManagement/AbpTenantManagementHttpApiClientModule.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.HttpApi.Client/Volo/Abp/TenantManagement/AbpTenantManagementHttpApiClientModule.cs @@ -9,13 +9,11 @@ namespace Volo.Abp.TenantManagement typeof(AbpHttpClientModule))] public class AbpTenantManagementHttpApiClientModule : AbpModule { - public const string RemoteServiceName = "AbpTenantManagement"; - public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddHttpClientProxies( typeof(AbpTenantManagementApplicationContractsModule).Assembly, - RemoteServiceName + TenantManagementRemoteServiceConsts.RemoteServiceName ); } } diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.HttpApi/Volo/Abp/TenantManagement/TenantController.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.HttpApi/Volo/Abp/TenantManagement/TenantController.cs index 5b821fbc71..317e7e62d0 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.HttpApi/Volo/Abp/TenantManagement/TenantController.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.HttpApi/Volo/Abp/TenantManagement/TenantController.cs @@ -7,7 +7,7 @@ using Volo.Abp.AspNetCore.Mvc; namespace Volo.Abp.TenantManagement { [Controller] - [RemoteService] + [RemoteService(Name = TenantManagementRemoteServiceConsts.RemoteServiceName)] [Area("multi-tenancy")] [Route("api/multi-tenancy/tenants")] public class TenantController : AbpController, ITenantAppService //TODO: Throws exception on validation if we inherit from Controller diff --git a/npm/ng-packs/packages/core/src/lib/models/config.ts b/npm/ng-packs/packages/core/src/lib/models/config.ts index 321a542097..0f7405380b 100644 --- a/npm/ng-packs/packages/core/src/lib/models/config.ts +++ b/npm/ng-packs/packages/core/src/lib/models/config.ts @@ -1,5 +1,5 @@ -import { AuthConfig } from 'angular-oauth2-oidc'; import { Type } from '@angular/core'; +import { AuthConfig } from 'angular-oauth2-oidc'; import { ApplicationConfiguration } from './application-configuration'; import { ABP } from './common'; @@ -13,6 +13,7 @@ export namespace Config { export interface Environment { application: Application; production: boolean; + hmr?: boolean; oAuthConfig: AuthConfig; apis: Apis; localization: { defaultResourceName: string }; @@ -23,8 +24,14 @@ export namespace Config { logoUrl?: string; } + export interface ApiConfig { + [key: string]: string; + url: string; + } + export interface Apis { - [key: string]: { [key: string]: string }; + [key: string]: ApiConfig; + default: ApiConfig; } export interface Requirements { diff --git a/npm/ng-packs/packages/core/src/lib/models/rest.ts b/npm/ng-packs/packages/core/src/lib/models/rest.ts index a494bbbc63..2f0e175002 100644 --- a/npm/ng-packs/packages/core/src/lib/models/rest.ts +++ b/npm/ng-packs/packages/core/src/lib/models/rest.ts @@ -1,10 +1,11 @@ import { HttpHeaders, HttpParams } from '@angular/common/http'; export namespace Rest { - export interface Config { - skipHandleError?: boolean; - observe?: Observe; - } + export type Config = Partial<{ + apiName: string; + skipHandleError: boolean; + observe: Observe; + }>; export const enum Observe { Body = 'body', diff --git a/npm/ng-packs/packages/core/src/lib/services/rest.service.ts b/npm/ng-packs/packages/core/src/lib/services/rest.service.ts index 0ad32ba010..936bc2a768 100644 --- a/npm/ng-packs/packages/core/src/lib/services/rest.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/rest.service.ts @@ -2,10 +2,11 @@ import { HttpClient, HttpRequest } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Store } from '@ngxs/store'; import { Observable, throwError } from 'rxjs'; -import { catchError, take, tap } from 'rxjs/operators'; +import { catchError } from 'rxjs/operators'; import { RestOccurError } from '../actions/rest.actions'; import { Rest } from '../models/rest'; import { ConfigState } from '../states/config.state'; +import { isUndefinedOrEmptyString } from '../utils/common-utils'; @Injectable({ providedIn: 'root', @@ -13,41 +14,40 @@ import { ConfigState } from '../states/config.state'; export class RestService { constructor(private http: HttpClient, private store: Store) {} + private getApiFromStore(apiName: string): string { + return this.store.selectSnapshot(ConfigState.getApiUrl(apiName)); + } + handleError(err: any): Observable { this.store.dispatch(new RestOccurError(err)); - console.error(err); return throwError(err); } - request(request: HttpRequest | Rest.Request, config?: Rest.Config, api?: string): Observable { + // TODO: Deprecate service or improve interface in v3.0 + request( + request: HttpRequest | Rest.Request, + config?: Rest.Config, + api?: string, + ): Observable { config = config || ({} as Rest.Config); - const { observe = Rest.Observe.Body, skipHandleError } = config; - const url = (api || this.store.selectSnapshot(ConfigState.getApiUrl())) + request.url; + api = api || this.getApiFromStore(config.apiName); const { method, params, ...options } = request; + const { observe = Rest.Observe.Body, skipHandleError } = config; return this.http - .request(method, url, { + .request(method, api + request.url, { observe, ...(params && { - params: Object.keys(params).reduce( - (acc, key) => ({ - ...acc, - ...(typeof params[key] !== 'undefined' && params[key] !== '' && { [key]: params[key] }), - }), - {}, - ), + params: Object.keys(params).reduce((acc, key) => { + const value = params[key]; + + if (!isUndefinedOrEmptyString(value)) acc[key] = value; + + return acc; + }, {}), }), ...options, } as any) - .pipe( - observe === Rest.Observe.Body ? take(1) : tap(), - catchError(err => { - if (skipHandleError) { - return throwError(err); - } - - return this.handleError(err); - }), - ); + .pipe(catchError(err => (skipHandleError ? throwError(err) : this.handleError(err)))); } } diff --git a/npm/ng-packs/packages/core/src/lib/services/track-by.service.ts b/npm/ng-packs/packages/core/src/lib/services/track-by.service.ts new file mode 100644 index 0000000000..ca2b92db5f --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/services/track-by.service.ts @@ -0,0 +1,18 @@ +import { Injectable, TrackByFunction } from '@angular/core'; + +@Injectable({ + providedIn: 'root', +}) +export class TrackByService { + by(key: keyof T): TrackByFunction { + return ({}, item) => item[key]; + } + + byDeep(...keys: (string | number)[]): TrackByFunction { + return ({}, item) => keys.reduce((acc, key) => acc[key], item); + } + + bySelf(): TrackByFunction { + return ({}, item) => item; + } +} diff --git a/npm/ng-packs/packages/core/src/lib/tests/common-utils.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/common-utils.spec.ts index 98c6614987..60280e396b 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/common-utils.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/common-utils.spec.ts @@ -1,4 +1,4 @@ -import { noop } from '../utils'; +import { isUndefinedOrEmptyString, noop } from '../utils'; describe('CommonUtils', () => { describe('#noop', () => { @@ -7,4 +7,20 @@ describe('CommonUtils', () => { expect(noop()()).toBeUndefined(); }); }); + + describe('#isUndefinedOrEmptyString', () => { + test.each` + value | expected + ${null} | ${false} + ${0} | ${false} + ${true} | ${false} + ${'x'} | ${false} + ${{}} | ${false} + ${[]} | ${false} + ${undefined} | ${true} + ${''} | ${true} + `('should return $expected when given parameter is $value', ({ value, expected }) => { + expect(isUndefinedOrEmptyString(value)).toBe(expected); + }); + }); }); diff --git a/npm/ng-packs/packages/core/src/lib/tests/rest.service.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/rest.service.spec.ts index 3d5cc11287..8251bcabb4 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/rest.service.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/rest.service.spec.ts @@ -1,68 +1,84 @@ +import { ConfigState } from '@abp/ng.core'; import { createHttpFactory, HttpMethod, SpectatorHttp, SpyObject } from '@ngneat/spectator/jest'; -import { Store } from '@ngxs/store'; -import { Subscription, timer, interval, throwError, of } from 'rxjs'; -import { mapTo, catchError } from 'rxjs/operators'; -import { RestService } from '../services/rest.service'; +import { NgxsModule, Store } from '@ngxs/store'; +import { of, throwError } from 'rxjs'; +import { catchError } from 'rxjs/operators'; import { Rest } from '../models'; -import { RestOccurError } from '../actions'; +import { RestService } from '../services/rest.service'; describe('HttpClient testing', () => { let spectator: SpectatorHttp; let store: SpyObject; const api = 'https://abp.io'; - const createHttp = createHttpFactory({ dataService: RestService, mocks: [Store] }); + const createHttp = createHttpFactory({ + dataService: RestService, + imports: [NgxsModule.forRoot([ConfigState])], + }); beforeEach(() => { spectator = createHttp(); store = spectator.get(Store); - store.selectSnapshot.andReturn(api); + store.reset({ + ConfigState: { + environment: { + apis: { + default: { + url: api, + }, + foo: { + url: 'bar', + }, + }, + }, + }, + }); + }); + + afterEach(() => { + spectator.controller.verify(); }); test('should send a GET request with params', () => { - spectator.service.request({ method: HttpMethod.GET, url: '/test', params: { id: 1 } }).subscribe(); + spectator.service + .request({ method: HttpMethod.GET, url: '/test', params: { id: 1 } }) + .subscribe(); spectator.expectOne(api + '/test?id=1', HttpMethod.GET); }); test('should send a POST request with body', () => { - spectator.service.request({ method: HttpMethod.POST, url: '/test', body: { id: 1 } }).subscribe(); + spectator.service + .request({ method: HttpMethod.POST, url: '/test', body: { id: 1 } }) + .subscribe(); const req = spectator.expectOne(api + '/test', HttpMethod.POST); expect(req.request.body['id']).toEqual(1); }); test('should use the specific api', () => { - spectator.service.request({ method: HttpMethod.GET, url: '/test' }, null, 'http://test.api').subscribe(); + spectator.service + .request({ method: HttpMethod.GET, url: '/test' }, null, 'http://test.api') + .subscribe(); spectator.expectOne('http://test.api' + '/test', HttpMethod.GET); }); - test('should close the subscriber when observe equal to body', done => { - jest.spyOn(spectator.httpClient, 'request').mockReturnValue(interval(50)); - - const subscriber: Subscription = spectator.service - .request({ method: HttpMethod.GET, url: '/test' }, { observe: Rest.Observe.Body }) + test('should use the url of a specific API when apiName is given', () => { + spectator.service + .request({ method: HttpMethod.GET, url: '/test' }, { apiName: 'foo' }) .subscribe(); - timer(51).subscribe(() => { - expect(subscriber.closed).toBe(true); - done(); - }); + spectator.expectOne('bar' + '/test', HttpMethod.GET); }); - test('should open the subscriber when observe not equal to body', done => { - jest.spyOn(spectator.httpClient, 'request').mockReturnValue(interval(50)); + test('should complete upon successful request', done => { + const complete = jest.fn(done); - const subscriber: Subscription = spectator.service - .request({ method: HttpMethod.GET, url: '/test' }, { observe: Rest.Observe.Events }) - .subscribe(); + spectator.service.request({ method: HttpMethod.GET, url: '/test' }).subscribe({ complete }); - timer(51).subscribe(() => { - expect(subscriber.closed).toBe(false); - done(); - }); + const req = spectator.expectOne(api + '/test', HttpMethod.GET); + spectator.flushAll([req], [{}]); }); test('should handle the error', () => { - jest.spyOn(spectator.httpClient, 'request').mockReturnValue(throwError('Testing error')); const spy = jest.spyOn(store, 'dispatch'); spectator.service @@ -70,26 +86,34 @@ describe('HttpClient testing', () => { .pipe( catchError(err => { expect(err).toBeTruthy(); - expect(spy.mock.calls[0][0] instanceof RestOccurError).toBe(true); + expect(spy).toHaveBeenCalled(); return of(null); }), ) .subscribe(); + + const req = spectator.expectOne(api + '/test', HttpMethod.GET); + spectator.flushAll([req], [throwError('Testing error')]); }); test('should not handle the error when skipHandleError is true', () => { - jest.spyOn(spectator.httpClient, 'request').mockReturnValue(throwError('Testing error')); const spy = jest.spyOn(store, 'dispatch'); spectator.service - .request({ method: HttpMethod.GET, url: '/test' }, { observe: Rest.Observe.Events, skipHandleError: true }) + .request( + { method: HttpMethod.GET, url: '/test' }, + { observe: Rest.Observe.Events, skipHandleError: true }, + ) .pipe( catchError(err => { expect(err).toBeTruthy(); - expect(spy.mock.calls).toHaveLength(0); + expect(spy).toHaveBeenCalledTimes(0); return of(null); }), ) .subscribe(); + + const req = spectator.expectOne(api + '/test', HttpMethod.GET); + spectator.flushAll([req], [throwError('Testing error')]); }); }); diff --git a/npm/ng-packs/packages/core/src/lib/tests/track-by.service.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/track-by.service.spec.ts new file mode 100644 index 0000000000..19868e8ad5 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/tests/track-by.service.spec.ts @@ -0,0 +1,33 @@ +import { TrackByService } from '../services/track-by.service'; + +describe('TrackByService', () => { + const service = new TrackByService(); + + describe('#by', () => { + it('should return a function which tracks a property', () => { + expect(service.by('x')(284, { x: 1036 })).toBe(1036); + }); + }); + + describe('#byDeep', () => { + it('should return a function which tracks a deeply-nested property', () => { + expect( + service.byDeep( + 'a', + 'b', + 'c', + 1, + 'x', + )(284, { + a: { b: { c: [{ x: 1035 }, { x: 1036 }, { x: 1037 }] } }, + }), + ).toBe(1036); + }); + }); + + describe('#bySelf', () => { + it('should return a function which tracks the item', () => { + expect(service.bySelf()(284, 'X')).toBe('X'); + }); + }); +}); diff --git a/npm/ng-packs/packages/core/src/lib/utils/common-utils.ts b/npm/ng-packs/packages/core/src/lib/utils/common-utils.ts index 756d3a34dd..b8609be130 100644 --- a/npm/ng-packs/packages/core/src/lib/utils/common-utils.ts +++ b/npm/ng-packs/packages/core/src/lib/utils/common-utils.ts @@ -3,3 +3,7 @@ export function noop() { const fn = function() {}; return fn; } + +export function isUndefinedOrEmptyString(value: unknown): boolean { + return value === undefined || value === ''; +} diff --git a/npm/preview-publish.ps1 b/npm/preview-publish.ps1 index 8f92022378..b1e5d8abe1 100644 --- a/npm/preview-publish.ps1 +++ b/npm/preview-publish.ps1 @@ -8,7 +8,7 @@ param( npm install -$NextVersion = $(node get-version.js) + '-preview' + (Get-Date).tostring("yyyyMMdd") +$NextVersion = $(node get-version.js) $rootFolder = (Get-Item -Path "./" -Verbose).FullName if(-Not $Version) { diff --git a/samples/BookStore-Angular-MongoDb/aspnet-core/src/Acme.BookStore.DbMigrator/Acme.BookStore.DbMigrator.csproj b/samples/BookStore-Angular-MongoDb/aspnet-core/src/Acme.BookStore.DbMigrator/Acme.BookStore.DbMigrator.csproj index e3f23bc85e..04e4195209 100644 --- a/samples/BookStore-Angular-MongoDb/aspnet-core/src/Acme.BookStore.DbMigrator/Acme.BookStore.DbMigrator.csproj +++ b/samples/BookStore-Angular-MongoDb/aspnet-core/src/Acme.BookStore.DbMigrator/Acme.BookStore.DbMigrator.csproj @@ -22,7 +22,7 @@ - + diff --git a/samples/BookStore-Angular-MongoDb/aspnet-core/src/Acme.BookStore.HttpApi.Host/Acme.BookStore.HttpApi.Host.csproj b/samples/BookStore-Angular-MongoDb/aspnet-core/src/Acme.BookStore.HttpApi.Host/Acme.BookStore.HttpApi.Host.csproj index 6119146712..31094a272a 100644 --- a/samples/BookStore-Angular-MongoDb/aspnet-core/src/Acme.BookStore.HttpApi.Host/Acme.BookStore.HttpApi.Host.csproj +++ b/samples/BookStore-Angular-MongoDb/aspnet-core/src/Acme.BookStore.HttpApi.Host/Acme.BookStore.HttpApi.Host.csproj @@ -15,7 +15,7 @@ - + diff --git a/samples/BookStore-Modular/application/src/Acme.BookStore.DbMigrator/Acme.BookStore.DbMigrator.csproj b/samples/BookStore-Modular/application/src/Acme.BookStore.DbMigrator/Acme.BookStore.DbMigrator.csproj index 7b08e55bda..548d856562 100644 --- a/samples/BookStore-Modular/application/src/Acme.BookStore.DbMigrator/Acme.BookStore.DbMigrator.csproj +++ b/samples/BookStore-Modular/application/src/Acme.BookStore.DbMigrator/Acme.BookStore.DbMigrator.csproj @@ -22,7 +22,7 @@ - + diff --git a/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Acme.BookStore.EntityFrameworkCore.DbMigrations.csproj b/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Acme.BookStore.EntityFrameworkCore.DbMigrations.csproj index b38c71d1d4..13a171d216 100644 --- a/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Acme.BookStore.EntityFrameworkCore.DbMigrations.csproj +++ b/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Acme.BookStore.EntityFrameworkCore.DbMigrations.csproj @@ -12,7 +12,7 @@ - + diff --git a/samples/BookStore-Modular/application/src/Acme.BookStore.Web/Acme.BookStore.Web.csproj b/samples/BookStore-Modular/application/src/Acme.BookStore.Web/Acme.BookStore.Web.csproj index d378f9ff00..25e40ef243 100644 --- a/samples/BookStore-Modular/application/src/Acme.BookStore.Web/Acme.BookStore.Web.csproj +++ b/samples/BookStore-Modular/application/src/Acme.BookStore.Web/Acme.BookStore.Web.csproj @@ -37,7 +37,7 @@ - + diff --git a/samples/BookStore-Modular/modules/book-management/host/Acme.BookStore.BookManagement.HttpApi.Host/Acme.BookStore.BookManagement.HttpApi.Host.csproj b/samples/BookStore-Modular/modules/book-management/host/Acme.BookStore.BookManagement.HttpApi.Host/Acme.BookStore.BookManagement.HttpApi.Host.csproj index 60c2276bb4..3e88d83236 100644 --- a/samples/BookStore-Modular/modules/book-management/host/Acme.BookStore.BookManagement.HttpApi.Host/Acme.BookStore.BookManagement.HttpApi.Host.csproj +++ b/samples/BookStore-Modular/modules/book-management/host/Acme.BookStore.BookManagement.HttpApi.Host/Acme.BookStore.BookManagement.HttpApi.Host.csproj @@ -14,8 +14,8 @@ - - + + diff --git a/samples/BookStore-Modular/modules/book-management/host/Acme.BookStore.BookManagement.IdentityServer/Acme.BookStore.BookManagement.IdentityServer.csproj b/samples/BookStore-Modular/modules/book-management/host/Acme.BookStore.BookManagement.IdentityServer/Acme.BookStore.BookManagement.IdentityServer.csproj index c0b6996719..5b6fd46c1e 100644 --- a/samples/BookStore-Modular/modules/book-management/host/Acme.BookStore.BookManagement.IdentityServer/Acme.BookStore.BookManagement.IdentityServer.csproj +++ b/samples/BookStore-Modular/modules/book-management/host/Acme.BookStore.BookManagement.IdentityServer/Acme.BookStore.BookManagement.IdentityServer.csproj @@ -12,9 +12,9 @@ - - - + + + diff --git a/samples/BookStore-Modular/modules/book-management/host/Acme.BookStore.BookManagement.Web.Host/Acme.BookStore.BookManagement.Web.Host.csproj b/samples/BookStore-Modular/modules/book-management/host/Acme.BookStore.BookManagement.Web.Host/Acme.BookStore.BookManagement.Web.Host.csproj index d2022bb48f..485cc3c1e9 100644 --- a/samples/BookStore-Modular/modules/book-management/host/Acme.BookStore.BookManagement.Web.Host/Acme.BookStore.BookManagement.Web.Host.csproj +++ b/samples/BookStore-Modular/modules/book-management/host/Acme.BookStore.BookManagement.Web.Host/Acme.BookStore.BookManagement.Web.Host.csproj @@ -13,9 +13,9 @@ - - - + + + diff --git a/samples/BookStore-Modular/modules/book-management/host/Acme.BookStore.BookManagement.Web.Unified/Acme.BookStore.BookManagement.Web.Unified.csproj b/samples/BookStore-Modular/modules/book-management/host/Acme.BookStore.BookManagement.Web.Unified/Acme.BookStore.BookManagement.Web.Unified.csproj index d54a64710b..3d47595d2d 100644 --- a/samples/BookStore-Modular/modules/book-management/host/Acme.BookStore.BookManagement.Web.Unified/Acme.BookStore.BookManagement.Web.Unified.csproj +++ b/samples/BookStore-Modular/modules/book-management/host/Acme.BookStore.BookManagement.Web.Unified/Acme.BookStore.BookManagement.Web.Unified.csproj @@ -13,7 +13,7 @@ - + diff --git a/samples/BookStore/src/Acme.BookStore.DbMigrator/Acme.BookStore.DbMigrator.csproj b/samples/BookStore/src/Acme.BookStore.DbMigrator/Acme.BookStore.DbMigrator.csproj index c77b3ae1eb..4c1a2612c8 100644 --- a/samples/BookStore/src/Acme.BookStore.DbMigrator/Acme.BookStore.DbMigrator.csproj +++ b/samples/BookStore/src/Acme.BookStore.DbMigrator/Acme.BookStore.DbMigrator.csproj @@ -19,7 +19,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Acme.BookStore.EntityFrameworkCore.DbMigrations.csproj b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Acme.BookStore.EntityFrameworkCore.DbMigrations.csproj index f8594c4ef9..6feb319c5e 100644 --- a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Acme.BookStore.EntityFrameworkCore.DbMigrations.csproj +++ b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Acme.BookStore.EntityFrameworkCore.DbMigrations.csproj @@ -8,7 +8,7 @@ - + diff --git a/samples/BookStore/src/Acme.BookStore.Web/Acme.BookStore.Web.csproj b/samples/BookStore/src/Acme.BookStore.Web/Acme.BookStore.Web.csproj index 61c73a3da8..984804f4be 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/Acme.BookStore.Web.csproj +++ b/samples/BookStore/src/Acme.BookStore.Web/Acme.BookStore.Web.csproj @@ -27,8 +27,8 @@ - - + + diff --git a/samples/DashboardDemo/src/DashboardDemo.DbMigrator/DashboardDemo.DbMigrator.csproj b/samples/DashboardDemo/src/DashboardDemo.DbMigrator/DashboardDemo.DbMigrator.csproj index 469d5a2773..cad80311b8 100644 --- a/samples/DashboardDemo/src/DashboardDemo.DbMigrator/DashboardDemo.DbMigrator.csproj +++ b/samples/DashboardDemo/src/DashboardDemo.DbMigrator/DashboardDemo.DbMigrator.csproj @@ -16,7 +16,7 @@ - + diff --git a/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore.DbMigrations/DashboardDemo.EntityFrameworkCore.DbMigrations.csproj b/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore.DbMigrations/DashboardDemo.EntityFrameworkCore.DbMigrations.csproj index c43e011cba..325fca41c4 100644 --- a/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore.DbMigrations/DashboardDemo.EntityFrameworkCore.DbMigrations.csproj +++ b/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore.DbMigrations/DashboardDemo.EntityFrameworkCore.DbMigrations.csproj @@ -12,7 +12,7 @@ - + diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.DbMigrator/Acme.BookStore.DbMigrator.csproj b/samples/EfCoreMigrationDemo/src/Acme.BookStore.DbMigrator/Acme.BookStore.DbMigrator.csproj index c2ed0c2edd..a1fb858a3e 100644 --- a/samples/EfCoreMigrationDemo/src/Acme.BookStore.DbMigrator/Acme.BookStore.DbMigrator.csproj +++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.DbMigrator/Acme.BookStore.DbMigrator.csproj @@ -22,7 +22,7 @@ - + diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Acme.BookStore.EntityFrameworkCore.DbMigrations.csproj b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Acme.BookStore.EntityFrameworkCore.DbMigrations.csproj index b38c71d1d4..13a171d216 100644 --- a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Acme.BookStore.EntityFrameworkCore.DbMigrations.csproj +++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Acme.BookStore.EntityFrameworkCore.DbMigrations.csproj @@ -12,7 +12,7 @@ - + diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrationsForSecondDb/Acme.BookStore.EntityFrameworkCore.DbMigrationsForSecondDb.csproj b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrationsForSecondDb/Acme.BookStore.EntityFrameworkCore.DbMigrationsForSecondDb.csproj index 820dc9e4d0..b1223793b2 100644 --- a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrationsForSecondDb/Acme.BookStore.EntityFrameworkCore.DbMigrationsForSecondDb.csproj +++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrationsForSecondDb/Acme.BookStore.EntityFrameworkCore.DbMigrationsForSecondDb.csproj @@ -12,7 +12,7 @@ - + \ No newline at end of file diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Web/Acme.BookStore.Web.csproj b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Web/Acme.BookStore.Web.csproj index 53faab21b7..04ba040321 100644 --- a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Web/Acme.BookStore.Web.csproj +++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Web/Acme.BookStore.Web.csproj @@ -37,7 +37,7 @@ - + diff --git a/samples/MicroserviceDemo/applications/AuthServer.Host/AuthServer.Host.csproj b/samples/MicroserviceDemo/applications/AuthServer.Host/AuthServer.Host.csproj index eaded7f020..7f5dad3178 100644 --- a/samples/MicroserviceDemo/applications/AuthServer.Host/AuthServer.Host.csproj +++ b/samples/MicroserviceDemo/applications/AuthServer.Host/AuthServer.Host.csproj @@ -15,9 +15,9 @@ - - - + + + diff --git a/samples/MicroserviceDemo/applications/BackendAdminApp.Host/BackendAdminApp.Host.csproj b/samples/MicroserviceDemo/applications/BackendAdminApp.Host/BackendAdminApp.Host.csproj index 4b24e5d584..ad98cbd55a 100644 --- a/samples/MicroserviceDemo/applications/BackendAdminApp.Host/BackendAdminApp.Host.csproj +++ b/samples/MicroserviceDemo/applications/BackendAdminApp.Host/BackendAdminApp.Host.csproj @@ -16,9 +16,9 @@ - - - + + + diff --git a/samples/MicroserviceDemo/applications/PublicWebSite.Host/PublicWebSite.Host.csproj b/samples/MicroserviceDemo/applications/PublicWebSite.Host/PublicWebSite.Host.csproj index 685038d9c8..8171af3273 100644 --- a/samples/MicroserviceDemo/applications/PublicWebSite.Host/PublicWebSite.Host.csproj +++ b/samples/MicroserviceDemo/applications/PublicWebSite.Host/PublicWebSite.Host.csproj @@ -15,9 +15,9 @@ - - - + + + diff --git a/samples/MicroserviceDemo/gateways/BackendAdminAppGateway.Host/BackendAdminAppGateway.Host.csproj b/samples/MicroserviceDemo/gateways/BackendAdminAppGateway.Host/BackendAdminAppGateway.Host.csproj index f0f2624e46..b8833d8984 100644 --- a/samples/MicroserviceDemo/gateways/BackendAdminAppGateway.Host/BackendAdminAppGateway.Host.csproj +++ b/samples/MicroserviceDemo/gateways/BackendAdminAppGateway.Host/BackendAdminAppGateway.Host.csproj @@ -18,8 +18,8 @@ - - + + diff --git a/samples/MicroserviceDemo/gateways/InternalGateway.Host/InternalGateway.Host.csproj b/samples/MicroserviceDemo/gateways/InternalGateway.Host/InternalGateway.Host.csproj index c393685128..581b56fb96 100644 --- a/samples/MicroserviceDemo/gateways/InternalGateway.Host/InternalGateway.Host.csproj +++ b/samples/MicroserviceDemo/gateways/InternalGateway.Host/InternalGateway.Host.csproj @@ -18,8 +18,8 @@ - - + + diff --git a/samples/MicroserviceDemo/gateways/PublicWebSiteGateway.Host/PublicWebSiteGateway.Host.csproj b/samples/MicroserviceDemo/gateways/PublicWebSiteGateway.Host/PublicWebSiteGateway.Host.csproj index fb06bcea05..99844c1619 100644 --- a/samples/MicroserviceDemo/gateways/PublicWebSiteGateway.Host/PublicWebSiteGateway.Host.csproj +++ b/samples/MicroserviceDemo/gateways/PublicWebSiteGateway.Host/PublicWebSiteGateway.Host.csproj @@ -18,8 +18,8 @@ - - + + diff --git a/samples/MicroserviceDemo/microservices/BloggingService.Host/BloggingService.Host.csproj b/samples/MicroserviceDemo/microservices/BloggingService.Host/BloggingService.Host.csproj index 1a107bcf40..ce45a91a66 100644 --- a/samples/MicroserviceDemo/microservices/BloggingService.Host/BloggingService.Host.csproj +++ b/samples/MicroserviceDemo/microservices/BloggingService.Host/BloggingService.Host.csproj @@ -17,8 +17,8 @@ - - + + diff --git a/samples/MicroserviceDemo/microservices/IdentityService.Host/IdentityService.Host.csproj b/samples/MicroserviceDemo/microservices/IdentityService.Host/IdentityService.Host.csproj index ec96f1ead6..5dd6961898 100644 --- a/samples/MicroserviceDemo/microservices/IdentityService.Host/IdentityService.Host.csproj +++ b/samples/MicroserviceDemo/microservices/IdentityService.Host/IdentityService.Host.csproj @@ -17,8 +17,8 @@ - - + + diff --git a/samples/MicroserviceDemo/microservices/ProductService.Host/ProductService.Host.csproj b/samples/MicroserviceDemo/microservices/ProductService.Host/ProductService.Host.csproj index 21750c55de..d07775748f 100644 --- a/samples/MicroserviceDemo/microservices/ProductService.Host/ProductService.Host.csproj +++ b/samples/MicroserviceDemo/microservices/ProductService.Host/ProductService.Host.csproj @@ -17,9 +17,9 @@ - - - + + + diff --git a/samples/MicroserviceDemo/microservices/TenantManagementService.Host/TenantManagementService.Host.csproj b/samples/MicroserviceDemo/microservices/TenantManagementService.Host/TenantManagementService.Host.csproj index 653eee189b..24d6fb8588 100644 --- a/samples/MicroserviceDemo/microservices/TenantManagementService.Host/TenantManagementService.Host.csproj +++ b/samples/MicroserviceDemo/microservices/TenantManagementService.Host/TenantManagementService.Host.csproj @@ -17,8 +17,8 @@ - - + + diff --git a/samples/MicroserviceDemo/modules/product/src/ProductManagement.EntityFrameworkCore/ProductManagement.EntityFrameworkCore.csproj b/samples/MicroserviceDemo/modules/product/src/ProductManagement.EntityFrameworkCore/ProductManagement.EntityFrameworkCore.csproj index 1e7d3e5cfe..d91a9c8358 100644 --- a/samples/MicroserviceDemo/modules/product/src/ProductManagement.EntityFrameworkCore/ProductManagement.EntityFrameworkCore.csproj +++ b/samples/MicroserviceDemo/modules/product/src/ProductManagement.EntityFrameworkCore/ProductManagement.EntityFrameworkCore.csproj @@ -6,7 +6,7 @@ - + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj index a4e6b5adb1..7c76be2c36 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj @@ -22,7 +22,7 @@ - + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations.csproj index cc8c7876ee..1bf1570157 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations.csproj @@ -12,7 +12,7 @@ - + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj index 20d35f5d01..21bd86eaca 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj @@ -15,9 +15,9 @@ - - - + + + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyCompanyName.MyProjectName.HttpApi.HostWithIds.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyCompanyName.MyProjectName.HttpApi.HostWithIds.csproj index 5b8db548fd..cbf882acc6 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyCompanyName.MyProjectName.HttpApi.HostWithIds.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyCompanyName.MyProjectName.HttpApi.HostWithIds.csproj @@ -15,7 +15,7 @@ - + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj index 160fcffc46..ec5209e8a0 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj @@ -35,9 +35,9 @@ - - - + + + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj index ae37bbd5a1..c0fa4cc23c 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj @@ -20,9 +20,9 @@ - - - + + + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj index ce1087911b..150ede13c7 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj @@ -37,7 +37,7 @@ - + diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj index c95c5a148f..71ac920b35 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj @@ -14,9 +14,9 @@ - - - + + + diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj index 946f3156f4..8bfc42e7d2 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj @@ -12,9 +12,9 @@ - - - + + + diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj index d3e5f19e78..25a0b25bc2 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj @@ -13,9 +13,9 @@ - - - + + + diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyCompanyName.MyProjectName.Web.Unified.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyCompanyName.MyProjectName.Web.Unified.csproj index 9277615d12..c531dc6474 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyCompanyName.MyProjectName.Web.Unified.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyCompanyName.MyProjectName.Web.Unified.csproj @@ -13,7 +13,7 @@ - +