Browse Source

Merge branch 'abpframework:dev' into dev

pull/21450/head
Celal Ak 2 years ago
committed by GitHub
parent
commit
97dc015294
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      Directory.Packages.props
  2. 6
      docs/en/cli/index.md
  3. 3
      docs/en/framework/ui/maui/index.md
  4. 4
      docs/en/solution-templates/microservice/guides/add-new-microservice.md
  5. BIN
      docs/en/studio/images/solution-runner/cli-application-context-menu.png
  6. BIN
      docs/en/studio/images/solution-runner/csharp-application-context-menu-build.png
  7. BIN
      docs/en/studio/images/solution-runner/csharp-application-context-menu-monitor.png
  8. BIN
      docs/en/studio/images/solution-runner/csharp-application-context-menu.png
  9. BIN
      docs/en/studio/images/solution-runner/folder-context-menu-add.png
  10. BIN
      docs/en/studio/images/solution-runner/folder-context-menu-build.png
  11. BIN
      docs/en/studio/images/solution-runner/folder-context-menu.png
  12. BIN
      docs/en/studio/images/solution-runner/manage-start-actions.png
  13. BIN
      docs/en/studio/images/solution-runner/profile-root-context-menu-add.png
  14. BIN
      docs/en/studio/images/solution-runner/profile-root-context-menu-build.png
  15. BIN
      docs/en/studio/images/solution-runner/profile-root-context-menu.png
  16. BIN
      docs/en/studio/images/solution-runner/solutioın-runner-properties.png
  17. 7
      docs/en/studio/release-notes.md
  18. 67
      docs/en/studio/running-applications.md
  19. 1
      docs/en/studio/version-mapping.md
  20. 7
      docs/en/tutorials/book-store-with-abp-suite/part-01.md
  21. 62
      docs/en/tutorials/book-store-with-abp-suite/part-02.md
  22. 4
      docs/en/tutorials/book-store-with-abp-suite/part-03.md
  23. 2
      docs/en/tutorials/book-store-with-abp-suite/part-04.md
  24. 12
      docs/en/tutorials/book-store/part-02.md
  25. 11
      docs/en/tutorials/book-store/part-03.md
  26. 28
      docs/en/tutorials/book-store/part-05.md
  27. 2
      docs/en/tutorials/book-store/part-06.md
  28. 7
      docs/en/tutorials/book-store/part-09.md
  29. 2
      docs/en/tutorials/book-store/part-10.md
  30. 33
      framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs
  31. 42
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/StaticFiles/AbpStaticFileProvider.cs
  32. 6
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/AuthService.cs
  33. 53
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/VoloNugetPackagesVersionUpdater.cs
  34. 30
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Version/PackageVersionCheckerService.cs
  35. 1
      framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo.Abp.EntityFrameworkCore.Oracle.csproj
  36. 23
      latest-versions.json
  37. 2
      modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.cs

4
Directory.Packages.props

@ -114,7 +114,7 @@
<PackageVersion Include="NEST" Version="7.17.5" /> <PackageVersion Include="NEST" Version="7.17.5" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" /> <PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="Nito.AsyncEx.Context" Version="5.1.2" /> <PackageVersion Include="Nito.AsyncEx.Context" Version="5.1.2" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.0" /> <PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.2" />
<PackageVersion Include="NSubstitute" Version="5.1.0" /> <PackageVersion Include="NSubstitute" Version="5.1.0" />
<PackageVersion Include="NuGet.Versioning" Version="6.11.1" /> <PackageVersion Include="NuGet.Versioning" Version="6.11.1" />
<PackageVersion Include="NUglify" Version="1.21.9" /> <PackageVersion Include="NUglify" Version="1.21.9" />
@ -125,7 +125,7 @@
<PackageVersion Include="OpenIddict.Server.AspNetCore" Version="5.8.0" /> <PackageVersion Include="OpenIddict.Server.AspNetCore" Version="5.8.0" />
<PackageVersion Include="OpenIddict.Validation.AspNetCore" Version="5.8.0" /> <PackageVersion Include="OpenIddict.Validation.AspNetCore" Version="5.8.0" />
<PackageVersion Include="OpenIddict.Validation.ServerIntegration" Version="5.8.0" /> <PackageVersion Include="OpenIddict.Validation.ServerIntegration" Version="5.8.0" />
<PackageVersion Include="Oracle.EntityFrameworkCore" Version="8.23.60" /> <PackageVersion Include="Oracle.EntityFrameworkCore" Version="9.23.60" />
<PackageVersion Include="Polly" Version="8.4.2" /> <PackageVersion Include="Polly" Version="8.4.2" />
<PackageVersion Include="Polly.Extensions.Http" Version="3.0.0" /> <PackageVersion Include="Polly.Extensions.Http" Version="3.0.0" />
<PackageVersion Include="Pomelo.EntityFrameworkCore.MySql" Version="9.0.0-preview.1" /> <PackageVersion Include="Pomelo.EntityFrameworkCore.MySql" Version="9.0.0-preview.1" />

6
docs/en/cli/index.md

@ -227,15 +227,15 @@ For more samples, go to [ABP CLI Create Solution Samples](new-command-samples.md
* `--no-kubernetes-configuration` or `-nkc`: Skips the Kubernetes configuration files. * `--no-kubernetes-configuration` or `-nkc`: Skips the Kubernetes configuration files.
* `--no-social-logins` or `-nsl`: Skipts the social login configuration. * `--no-social-logins` or `-nsl`: Skipts the social login configuration.
* `--no-tests` or `-ntp`: Does not add test projects. * `--no-tests` or `-ntp`: Does not add test projects.
* *Module Options*: You can skip some modules if you don't want to add them to your solution (*Available for* ***Team*** *or higher licenses*). Available commands: * *Module Options*: You can skip some modules if you don't want to add them to your solution, or include if you want them (*Available for* ***Team*** *or higher licenses*). Available commands:
* `-no-saas`: Skips the Saas module. * `-no-saas`: Skips the Saas module.
* `-no-gdpr`: Skips the GDPR module. * `-no-gdpr`: Skips the GDPR module.
* `-no-openiddict-admin-ui`: Skips the OpenIddict Admin UI module. * `-no-openiddict-admin-ui`: Skips the OpenIddict Admin UI module.
* `-no-audit-logging`: Skips the Audit Logging module. * `-no-audit-logging`: Skips the Audit Logging module.
* `-no-file-management`: Skips the File Management module.
* `-no-language-management`: Skips the Language Management module. * `-no-language-management`: Skips the Language Management module.
* `-no-text-template-management`: Skips the Text Template Management module. * `-no-text-template-management`: Skips the Text Template Management module.
* `-no-chat`: Skips the Chat module. * `-file-management`: Includes the File Management module.
* `-chat`: Includes the Chat module.
* `--legacy`: Generates a legacy solution. * `--legacy`: Generates a legacy solution.
* `trust-version`: Trusts the user's version and does not check if the version exists or not. If the template with the given version is found in the cache, it will be used, otherwise throws an exception. * `trust-version`: Trusts the user's version and does not check if the version exists or not. If the template with the given version is found in the cache, it will be used, otherwise throws an exception.

3
docs/en/framework/ui/maui/index.md

@ -40,6 +40,9 @@ Open a command line terminal and run the `adb reverse` command to expose a port
> You should replace "44305" with the real port. > You should replace "44305" with the real port.
> You should run the command after starting the emulator. > You should run the command after starting the emulator.
> If you don't have a separate installation of Android Debug Bridge, you can open it from **Visual Studio** by following toolbar menu `Tools` > `Android` > `Android Adb Command Prompt`. Android emulator has to be running for this operation.
### iOS ### iOS
The iOS simulator uses the host machine network. Therefore, applications running in the simulator can connect to web services running on your local machine via the machines IP address or via the localhost hostname. For example, given a local secure web service that exposes a GET operation via the /api/todoitems/ relative URI, an application running on the iOS simulator can consume the operation by sending a GET request to https://localhost:<port>/api/todoitems/. The iOS simulator uses the host machine network. Therefore, applications running in the simulator can connect to web services running on your local machine via the machines IP address or via the localhost hostname. For example, given a local secure web service that exposes a GET operation via the /api/todoitems/ relative URI, an application running on the iOS simulator can consume the operation by sending a GET request to https://localhost:<port>/api/todoitems/.

4
docs/en/solution-templates/microservice/guides/add-new-microservice.md

@ -1,3 +1 @@
# ABP Studio Microservice Solution: Adding New Microservices > This document is [moved to here](../adding-new-microservices.md).
This document is planned to be written later.

BIN
docs/en/studio/images/solution-runner/cli-application-context-menu.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 13 KiB

BIN
docs/en/studio/images/solution-runner/csharp-application-context-menu-build.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 27 KiB

BIN
docs/en/studio/images/solution-runner/csharp-application-context-menu-monitor.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 20 KiB

BIN
docs/en/studio/images/solution-runner/csharp-application-context-menu.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 22 KiB

BIN
docs/en/studio/images/solution-runner/folder-context-menu-add.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 14 KiB

BIN
docs/en/studio/images/solution-runner/folder-context-menu-build.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 14 KiB

BIN
docs/en/studio/images/solution-runner/folder-context-menu.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 14 KiB

BIN
docs/en/studio/images/solution-runner/manage-start-actions.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
docs/en/studio/images/solution-runner/profile-root-context-menu-add.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 10 KiB

BIN
docs/en/studio/images/solution-runner/profile-root-context-menu-build.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
docs/en/studio/images/solution-runner/profile-root-context-menu.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

BIN
docs/en/studio/images/solution-runner/solutioın-runner-properties.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 16 KiB

7
docs/en/studio/release-notes.md

@ -2,6 +2,13 @@
This document contains **brief release notes** for each ABP Studio release. Release notes only include **major features** and **visible enhancements**. Therefore, they don't include all the development done in the related version. This document contains **brief release notes** for each ABP Studio release. Release notes only include **major features** and **visible enhancements**. Therefore, they don't include all the development done in the related version.
## 0.9.15 (2024-12-05)
* Upgraded templates to version `9.0.1`.
* Fixed problems in the microservice service_nolayers template.
* Fixed microservice angular template for wrong file-management module reference.
* Fixed added extra lines in the hosts.txt file.
## 0.9.14 (2024-12-03) ## 0.9.14 (2024-12-03)
* Refactored `dotnet watch` command in solution runner. * Refactored `dotnet watch` command in solution runner.

67
docs/en/studio/running-applications.md

@ -41,27 +41,22 @@ When you click *Add New Profile*, it opens the *Create New Profile* window. You
## Using the Profile ## Using the Profile
After selecting the current profile, which is the *Default* profile that comes pre-configured, we can utilize the tree items. This allows us to execute collective commands and create various tree structures based on our specific needs. You can navigate through the root of the tree and right-click to view the context menu, which includes 3 options: `Run`, `Build` and `Add`. After selecting the current profile, which is the *Default* profile that comes pre-configured, we can utilize the tree items. This allows us to execute collective commands and create various tree structures based on our specific needs. You can navigate through the root of the tree and right-click to view the context menu, which includes the following options: `Start All`, `Stop All`, `Build`, `Add`, and `Manage Start Actions`.
![profile-root-context-menu](images/solution-runner/profile-root-context-menu.png) ![profile-root-context-menu](images/solution-runner/profile-root-context-menu.png)
### Run ### Start/Stop All
We can start/stop the applications with this option. Go to root of the tree and right-click to view the context menu, in this example *Acme.Bookstore(Default)* -> *Run*. We can start/stop the applications with these options. Go to the root of the tree and right-click to view the context menu:
![profile-root-context-menu-run](images/solution-runner/profile-root-context-menu-run.png)
- `Start All`: Start all(CLI, C#) applications. - `Start All`: Start all(CLI, C#) applications.
- `Stop All`: Stop all(CLI, C#) applications. - `Stop All`: Stop all(CLI, C#) applications.
- `Build & Start All`: Builds each C# application in the [Background Tasks](./overview#background-tasks) and starts all (CLI, C#) applications after the build tasks are completed.
> `Start All` doesn't build the C# applications before running. If you're running it for the first time or if you've made changes, you should build the applications. You can simply use the `Build & Start All`.
> You can change the current profile while applications are running in the previous profile. The applications continue to run under the previous profile. For example if we start the `Acme.BookStore.AdministrationService`, `Acme.BookStore.IdentityService` applications when current profile is *team-1* and after change the current profile to *team-2* the applications continue to run under *team-1*. > You can change the current profile while applications are running in the previous profile. The applications continue to run under the previous profile. For example, if we start the `Acme.BookStore.AdministrationService`, `Acme.BookStore.IdentityService` applications when the current profile is *team-1* and after changing the current profile to *team-2* the applications continue to run under *team-1*.
### Build ### Build
We can use common [dotnet](https://learn.microsoft.com/en-us/dotnet/core/tools) commands in this option. Go to root of the tree and right-click to view the context menu, in this example *Acme.Bookstore(Default)* -> *Build*, there are 4 options available: We can use common [dotnet](https://learn.microsoft.com/en-us/dotnet/core/tools) commands in this option. Go to the root of the tree and right-click to view the context menu, in this example *Acme.Bookstore(Default)* -> *Build*, there are 4 options available:
![profile-root-context-menu-build](images/solution-runner/profile-root-context-menu-build.png) ![profile-root-context-menu-build](images/solution-runner/profile-root-context-menu-build.png)
@ -80,7 +75,7 @@ We can add 3 different item type to *Profile* for defining the tree structure. T
#### C# Application #### C# Application
When we go to root of the tree and right-click, in this example *Acme.BookStore(Default)* -> *Add* -> *C# Application* it opens the *Add Application* window. There are two methods to add applications: *This solution* and *External*. To add via the *This solution* tab, follow these steps: When we go to the root of the tree and right-click, in this example *Acme.BookStore(Default)* -> *Add* -> *C# Application* it opens the *Add Application* window. There are two methods to add applications: *This solution* and *External*. To add via the *This solution* tab, follow these steps:
![profile-root-add-csharp-application](images/solution-runner/profile-root-add-csharp-application.png) ![profile-root-add-csharp-application](images/solution-runner/profile-root-add-csharp-application.png)
@ -98,7 +93,7 @@ The C# project doesn't have to be within the current [Solution Explorer](./solut
- `Path`: Provide the path to the .csproj file you wish to add. The path will be [normalized](https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#path-normalization), allowing the project location to be flexible, as long as it's accessible from the current [ABP Solution](./concepts.md#solution). - `Path`: Provide the path to the .csproj file you wish to add. The path will be [normalized](https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#path-normalization), allowing the project location to be flexible, as long as it's accessible from the current [ABP Solution](./concepts.md#solution).
- `Name`: Give an arbitrary name to see in solution runner. This name should be unique for each profile. - `Name`: Give an arbitrary name to see in solution runner. This name should be unique for each profile.
- `Launch url`: Is the url when we want to browse. But if added project doesn't have launch url we can leave it empty. - `Launch url`: This is the url when we want to browse. But if the added project doesn't have launch url we can leave it empty.
- `Kubernetes service`: If you're not using the *Kubernetes* panel leave it empty. But if there is a helm chart for added application we should give the correct regex pattern. It's necessary for browse, when we connect the kubernetes cluster we should browse the services instead *Launch url*. Give the matching regex pattern for your helm chart kubernetes service name. - `Kubernetes service`: If you're not using the *Kubernetes* panel leave it empty. But if there is a helm chart for added application we should give the correct regex pattern. It's necessary for browse, when we connect the kubernetes cluster we should browse the services instead *Launch url*. Give the matching regex pattern for your helm chart kubernetes service name.
You can click the `OK` button to add the C# application to the profile. You can click the `OK` button to add the C# application to the profile.
@ -137,17 +132,27 @@ You can click the `OK` button to add the folder to the profile.
- To remove a folder from the tree, open the context menu by right-clicking the folder and selecting *Delete*. - To remove a folder from the tree, open the context menu by right-clicking the folder and selecting *Delete*.
- When starting applications, they continue to restart until the application starts gracefully. To stop the restarting process when attempting to restart the application, click the icon on the left. Additionally, you can review the *Logs* to understand why the application isn't starting gracefully. - When starting applications, they continue to restart until the application starts gracefully. To stop the restarting process when attempting to restart the application, click the icon on the left. Additionally, you can review the *Logs* to understand why the application isn't starting gracefully.
### Manage Start Actions
This command will open a dialog where you can set start actions and start orders of sub-applications and sub-folders.
![manage-start-actions](images/solution-runner/manage-start-actions.png)
You can order the applications by dragging the icon in the first column. In the screenshot above, applications & folders are ordered like this: *Applications under infrastructure* > *Applications under services* > *Applications under gateways* > *AuthServer* > *Angular*. You can also set starting order and other actions for each folder by performing `right click > Manage Start Actions` on them.
- **Action**: There are two options: `Start` and `Don't start`. This is usefull if you want to exclude applications from batch start.
- **Build**: This option allows to disable/enable build before starting the application. If you are working on a single application, you can exclude the other applications from build to save time. This option can also be set by performing `right click > properties` on applications.
- **Watch**: When enabled, changes in your code are watched and dotnet hot-reloads the application or restarts it if needed. This option also can be set by performing `right click > properties` on applications.
## Folder ## Folder
We already now why we need folder in the [previous](./running-applications.md#folder) section, we can use collective commands within this folder items. To do that go to folder and open the context menu by right-clicking, which includes 5 options `Start`, `Build`, `Add`, `Rename` and `Delete`. We already now why we need folder in the [previous](./running-applications.md#folder) section, we can use collective commands within this folder items. To do that go to folder and open the context menu by right-clicking, which includes 5 options `Start`, `Stop`, `Build`, `Add`, `Manage Start Actions`, `Rename` and `Delete`.
![folder-context-menu](images/solution-runner/folder-context-menu.png) ![folder-context-menu](images/solution-runner/folder-context-menu.png)
### Start ### Start/Stop
You can see the context menu by right-clicking *Folder* -> *Start*, it's [similar](#run) like *Acme.BookStore(Default)* -> *Run* options, there are 3 options available. The only difference with root of the tree and folder is gonna be execute in selected folder.
![folder-context-menu-start](images/solution-runner/folder-context-menu-start.png) You can see the context menu by right-clicking *Folder*. It will start/stop all the applications under the folder.
### Build ### Build
@ -157,7 +162,7 @@ You can see the context menu by right-clicking *Folder* -> *Start*, it's [simila
### Add ### Add
*Folder* -> *Add* context menu, it's the [same](#add) options like *Acme.BookStore(Default)* -> *Add* there are 3 options avaiable. The only difference, it's gonna add item to selected folder. *Folder* -> *Add* context menu, it's the [same](#add) options like *Acme.BookStore(Default)* -> *Add* there are 3 options avaiable. The only difference, it's gonna add item to the selected folder.
![folder-context-menu-add](images/solution-runner/folder-context-menu-add.png) ![folder-context-menu-add](images/solution-runner/folder-context-menu-add.png)
@ -168,29 +173,16 @@ You can see the context menu by right-clicking *Folder* -> *Start*, it's [simila
## C# Application ## C# Application
The .NET icon indicates that the application is a C# project. After we [add](#c-application) the C# applications to root of the tree or folder, we can go to any C# application and right-click to view the context menu; `Run`, `Build`, `Browse`, `Requests`, `Exceptions`, `Logs`, `Copy URL`, `Properties`, `Remove`. The .NET icon indicates that the application is a C# project. After we [add](#c-application) the C# applications to the root of the tree or folder, we can go to any C# application and right-click to view the context menu; `Start`, `Build`, `Browse`, `Requests`, `Exceptions`, `Logs`, `Copy URL`, `Properties`, `Remove`.
![csharp-application-context-menu](images/solution-runner/csharp-application-context-menu.png) ![csharp-application-context-menu](images/solution-runner/csharp-application-context-menu.png)
### Run ### Start
We have several options in C# applications. Those options are `Start`(If the application started this option shown as `Stop`), `Build & Start`(If the application started this option shown as `Build & Restart`), `Enable Watch`(If the watch is enabled this option shown as `Disable Watch`), `Restart`(It's only shown when the application started)
![csharp-application-context-menu-run](images/solution-runner/csharp-application-context-menu-run.png)
- `Start`: Starts the selected application. This option doesn't build before run. If you're running it for the first time or if you've made changes, you should build the application. If the application is started this option changed as `Stop`. Starts the selected application. Once it is started, *Stop* and *Restart* options will be available.
- `Build & Start`: We can simply use if we wanna build first and start. If the application is started this option changes to `Build & Restart`.
- `Enable Watch`: When this option is enabled, there's no need to perform `Build & Start` after any change. ABP Studio watches for changes, re-builds, and re-runs your application automatically upon saving. If this option is enabled it changes to `Disable Watch`.
- `Restart`: Restarts the application. This option visible only if the application started.
> When you start the C# application, you should see a *chain* icon next to the application name, that means the started application connected to ABP Studio. C# applications can connect to ABP Studio even when running from outside the ABP Studio environment, for example debugging with Visual Studio. If the application is run from outside the ABP Studio environment, it will display *(external)* information next to the chain icon. > When you start the C# application, you should see a *chain* icon next to the application name, that means the started application connected to ABP Studio. C# applications can connect to ABP Studio even when running from outside the ABP Studio environment, for example debugging with Visual Studio. If the application is run from outside the ABP Studio environment, it will display *(external)* information next to the chain icon.
> When *Watch* is enable you should see an *eye* icon next to the application name.
> Hint: Performing CTRL+Click on the start icon left to a stopped C# application equals to `Build & Start` command. Same applies for folders.
![csharp-application-context-menu-run-connection](images/solution-runner/csharp-application-context-menu-run-connection.png)
### Build ### Build
It's the [similar](#build) options like root of the tree options. The only difference between them it's gonna be execute the selected application. It's the [similar](#build) options like root of the tree options. The only difference between them it's gonna be execute the selected application.
@ -214,7 +206,10 @@ We can open the *Application Properties* window to change *Launch url*, *Kuberne
![solutioın-runner-properties](images/solution-runner/solutioın-runner-properties.png) ![solutioın-runner-properties](images/solution-runner/solutioın-runner-properties.png)
You can click the `OK` button to save the changes. - **Skip build before starting**: When enabled, application is started without build and it makes starting faster. This is useful when you are working on a single application out of multiple, so you don't need to build others everytime they start.
- **Watch changes while running**: When enabled, you should see an *eye* icon next to the application name.
![csharp-application-context-menu-run-connection](images/solution-runner/csharp-application-context-menu-run-connection.png)
### Miscellaneous ### Miscellaneous
@ -228,7 +223,7 @@ CLI applications uses the [powershell](https://learn.microsoft.com/en-us/powersh
![cli-application-context-menu](images/solution-runner/cli-application-context-menu.png) ![cli-application-context-menu](images/solution-runner/cli-application-context-menu.png)
- `Run`: This option includes 3 actions: *Start*, *Stop*, and *Restart* for the CLI application. - `Start`: Starts the application. Once it is started, *Start* and *Restart* options will be available.
- `Browse`: This option is available when a *Launch URL* is specified upon adding the CLI application. It opens the *Browse* tab, can be clicked while the application is running. - `Browse`: This option is available when a *Launch URL* is specified upon adding the CLI application. It opens the *Browse* tab, can be clicked while the application is running.
- `Logs`: It opens the *Logs* tab, we can see the logs for *Start* and *Stop* commands. - `Logs`: It opens the *Logs* tab, we can see the logs for *Start* and *Stop* commands.
- `Copy URL`: This option copies the *Launch URL* of the selected application. It is visible if there is a specified *Launch URL* - `Copy URL`: This option copies the *Launch URL* of the selected application. It is visible if there is a specified *Launch URL*

1
docs/en/studio/version-mapping.md

@ -4,6 +4,7 @@ This document provides a general overview of the relationship between various ve
| **ABP Studio Version** | **ABP Version of Startup Template** | | **ABP Studio Version** | **ABP Version of Startup Template** |
|------------------------|---------------------------| |------------------------|---------------------------|
| 0.9.15 | 9.0.1 |
| 0.9.9 to 0.9.14 | 9.0.0 | | 0.9.9 to 0.9.14 | 9.0.0 |
| 0.9.8 | 8.3.4 | | 0.9.8 | 8.3.4 |
| 0.9.5 to 0.9.7 | 8.3.3 | | 0.9.5 to 0.9.7 | 8.3.3 |

7
docs/en/tutorials/book-store-with-abp-suite/part-01.md

@ -10,6 +10,10 @@
````json ````json
//[doc-nav] //[doc-nav]
{ {
"Previous": {
"Name": "Overview",
"Path": "tutorials/book-store-with-abp-suite/index"
},
"Next": { "Next": {
"Name": "Creating the Books", "Name": "Creating the Books",
"Path": "tutorials/book-store-with-abp-suite/part-02" "Path": "tutorials/book-store-with-abp-suite/part-02"
@ -21,11 +25,14 @@ Before starting the development, create a new solution named `Acme.BookStore` an
You can use the following configurations: You can use the following configurations:
* **Solution Template:** Application (Layered)
* **Solution Name:** `Acme.BookStore` * **Solution Name:** `Acme.BookStore`
* **UI Framework:** {{if UI=="MVC"}} ASP.NET Core MVC / Razor Pages {{end}} * **UI Framework:** {{if UI=="MVC"}} ASP.NET Core MVC / Razor Pages {{end}}
* **UI Theme:** LeptonX * **UI Theme:** LeptonX
* **Mobile Framework:** None * **Mobile Framework:** None
* **Database Provider:** {{if DB=="EF"}} Entity Framework Core {{end}} * **Database Provider:** {{if DB=="EF"}} Entity Framework Core {{end}}
* **Public Website:** No
* **Tiered:** No
You can select the other options based on your preference. You can select the other options based on your preference.

62
docs/en/tutorials/book-store-with-abp-suite/part-02.md

@ -36,7 +36,28 @@ After clicking the related command, pre-integrated browser of ABP Studio should
## Creating the Book Entity ## Creating the Book Entity
Let's create a `Book` entity with some properties. First, type `Book` for the *Name* field and leave the other options as is. ABP Suite automatically calculates proper values for the rest of the inputs for you: Before creating the `Book` entity, first we can create a `BookType` enum in the `Acme.BookStore.Domain.Shared` project under the **Books** folder as follows:
```csharp
namespace Acme.BookStore.Books;
public enum BookType
{
Undefined,
Adventure,
Biography,
Dystopia,
Fantastic,
Horror,
Science,
ScienceFiction,
Poetry
}
```
After creating an _enum_ file in your project, you can define it as a property while creating the entity. ABP Suite asks for an enum path to read the enum file, and set the namespace, and enum name in the generated code accordingly. Then, you can create the `Book` entity with some properties.
Type `Book` for the *Name* field and leave the other options as is. ABP Suite automatically calculates proper values for the rest of the inputs for you:
![](./images/suite-book-entity-1.png) ![](./images/suite-book-entity-1.png)
@ -55,10 +76,16 @@ After, specifying the entity metadata, open the *Properties* tab and create the
![](./images/suite-book-entity-3.png) ![](./images/suite-book-entity-3.png)
Here the details: While defining the properties, you define a *Type* property with the type of *enum*. ABP Suite asks for an enum path and fill the all other inputs by reading the specified enum file. Therefore, you can specify the enum path for the `Type` property like in the following figure:
![](./images/suite-book-entity-4.png)
> After you select the enum file, ABP Suite automatically sets the namespace and enum name, and lists your enum values in the next section. You can change these values, but for now, you can leave as is.
Here is the all details for the `Book` entity:
* `Name` is **required**, it's a **string** property and maximum length is **128**. * `Name` is **required**, it's a **string** property and maximum length is **128**.
* `Type` is an **enum** and the enum file path is *\Acme.BookStore.Domain.Shared\Books\BookType.cs* (we will create the file, in the next section). * `Type` is an **enum** and the enum file path is *\Acme.BookStore.Domain.Shared\Books\BookType.cs*.
* `PublishDate` is a **DateTime** property and **not nullable**. * `PublishDate` is a **DateTime** property and **not nullable**.
* `Price` is a **float** property and **required**. * `Price` is a **float** property and **required**.
@ -66,33 +93,6 @@ You can leave the other configurations as default.
> ABP Suite allows you to define properties with a great range of options, for example, you can specify the property type as *string*, *int*, *float*, *Guid*, *DateTime*, and even *File* (for file upload) and also you can set any options while defining your properties, such as specifying it as *required*, or *nullable*, setting *max-min length*, *default value* and more... > ABP Suite allows you to define properties with a great range of options, for example, you can specify the property type as *string*, *int*, *float*, *Guid*, *DateTime*, and even *File* (for file upload) and also you can set any options while defining your properties, such as specifying it as *required*, or *nullable*, setting *max-min length*, *default value* and more...
While defining the properties, you defined a *Type* property with the type of *enum*. ABP Suite asks for an enum path to read the enum file, and set the namespace, and enum name in the generated code.
For that purpose, you should create a `BookType` enum in the `Acme.BookStore.Domain.Shared` project under the **Books** folder as follows:
```csharp
namespace Acme.BookStore.Books;
public enum BookType
{
Undefined,
Adventure,
Biography,
Dystopia,
Fantastic,
Horror,
Science,
ScienceFiction,
Poetry
}
```
Then, you can specify the enum path for the `Type` property in ABP Suite like in the following figure:
![](./images/suite-book-entity-4.png)
> After you select the enum file, ABP Suite automatically sets the namespace and enum name, and lists your enum values in the next section. You can change these values, but for now, you can leave as is.
After that, you can click the **Save and Generate** button to start the code generation process: After that, you can click the **Save and Generate** button to start the code generation process:
![](./images/suite-book-entity-5.png) ![](./images/suite-book-entity-5.png)
@ -106,7 +106,7 @@ ABP Suite will generate the necessary code for you. It generates:
* **Unit & integration tests**, * **Unit & integration tests**,
* A new **migration** (and also applies to the database), * A new **migration** (and also applies to the database),
* All related **permission**, **object mapping** and **navigation menu item** configurations, * All related **permission**, **object mapping** and **navigation menu item** configurations,
* and all required **UI components and pages**. * and all required **UI components and pages**...
It will take some time to complete the process. After the process is completed, you will see a success message, you can click the *Ok* button, and build & start the application by clicking the *Run -> Build & Start* button in the *Solution Runner* panel: It will take some time to complete the process. After the process is completed, you will see a success message, you can click the *Ok* button, and build & start the application by clicking the *Run -> Build & Start* button in the *Solution Runner* panel:

4
docs/en/tutorials/book-store-with-abp-suite/part-03.md

@ -50,9 +50,9 @@ After, specifying the entity metadata, open the *Properties* tab and create the
Here the details: Here the details:
* `Name` is **required**, it's a **string** property, and it's a **textarea**. Minimum length is **2** and maximum length is **128**. * `Name` is **required**, it's a **string** property. Minimum length is **2** and maximum length is **128**.
* `BirthDate` is a **DateTime** property and **not nullable**. * `BirthDate` is a **DateTime** property and **not nullable**.
* `ShortBio` is a **string** property, it's **required**, maximum length is **256**. * `ShortBio` is **required**, it's a **string** property, it's a **textarea**, maximum length is **256**.
You can leave the other configurations as default. You can leave the other configurations as default.

2
docs/en/tutorials/book-store-with-abp-suite/part-04.md

@ -49,6 +49,8 @@ Here is the details:
* Selected the display property as *Name*, this will be used in the dropdown component to set an author with a book & also it will be shown in the datatable of the *Books* page. * Selected the display property as *Name*, this will be used in the dropdown component to set an author with a book & also it will be shown in the datatable of the *Books* page.
* Also, made the relation **required** and set it **filterable** so books can be filterable by authors. * Also, made the relation **required** and set it **filterable** so books can be filterable by authors.
> **Note**: You should delete all existing books in the database (if any), before the code generation. Because, a new foreign-key will be added to the _books_ table and if there is any record in the table, then a new migration can't apply to the database and you may need to update the database manually.
After, specifying the metadata, you can click the *Ok* button to close the modal. Then, click the **Save and generate** button to start code generation process. ABP Suite will establish one-to-many relationship between the entities, and will generate all necessary code automatically: After, specifying the metadata, you can click the *Ok* button to close the modal. Then, click the **Save and generate** button to start code generation process. ABP Suite will establish one-to-many relationship between the entities, and will generate all necessary code automatically:
![](./images/suite-end-of-generation-modal.png) ![](./images/suite-end-of-generation-modal.png)

12
docs/en/tutorials/book-store/part-02.md

@ -577,8 +577,6 @@ Open the `Books.razor` and replace the content as the following:
@using Volo.Abp.Application.Dtos @using Volo.Abp.Application.Dtos
@using Acme.BookStore.Books @using Acme.BookStore.Books
@using Acme.BookStore.Localization @using Acme.BookStore.Localization
@using Microsoft.Extensions.Localization
@inject IStringLocalizer<BookStoreResource> L
@inherits AbpCrudPageBase<IBookAppService, BookDto, Guid, PagedAndSortedResultRequestDto, CreateUpdateBookDto> @inherits AbpCrudPageBase<IBookAppService, BookDto, Guid, PagedAndSortedResultRequestDto, CreateUpdateBookDto>
<Card> <Card>
@ -625,13 +623,21 @@ Open the `Books.razor` and replace the content as the following:
</DataGrid> </DataGrid>
</CardBody> </CardBody>
</Card> </Card>
@code
{
public Books() // Constructor
{
LocalizationResource = typeof(BookStoreResource);
}
}
```` ````
> If you see some syntax errors, you can ignore them if your application is properly built and running. Visual Studio still has some bugs with Blazor. > If you see some syntax errors, you can ignore them if your application is properly built and running. Visual Studio still has some bugs with Blazor.
* Inherited from `AbpCrudPageBase<IBookAppService, BookDto, Guid, PagedAndSortedResultRequestDto, CreateUpdateBookDto>` which implements all the CRUD details for us. * Inherited from `AbpCrudPageBase<IBookAppService, BookDto, Guid, PagedAndSortedResultRequestDto, CreateUpdateBookDto>` which implements all the CRUD details for us.
* `Entities`, `TotalCount`, `PageSize`, `OnDataGridReadAsync` are defined in the base class. * `Entities`, `TotalCount`, `PageSize`, `OnDataGridReadAsync` are defined in the base class.
* Injected `IStringLocalizer<BookStoreResource>` (as `L` object) and used for localization. * `LocalizationResource` is set to the `BookStoreResource` to localize the texts.
While the code above is pretty easy to understand, you can check the Blazorise [Card](https://blazorise.com/docs/components/card/) and [DataGrid](https://blazorise.com/docs/extensions/datagrid/) documents to understand them better. While the code above is pretty easy to understand, you can check the Blazorise [Card](https://blazorise.com/docs/components/card/) and [DataGrid](https://blazorise.com/docs/extensions/datagrid/) documents to understand them better.

11
docs/en/tutorials/book-store/part-03.md

@ -1351,7 +1351,6 @@ Here's the complete code to create the book management CRUD page, that has been
@using Acme.BookStore.Localization @using Acme.BookStore.Localization
@using Microsoft.Extensions.Localization @using Microsoft.Extensions.Localization
@using Volo.Abp.AspNetCore.Components.Web @using Volo.Abp.AspNetCore.Components.Web
@inject IStringLocalizer<BookStoreResource> L
@inject AbpBlazorMessageLocalizerHelper<BookStoreResource> LH @inject AbpBlazorMessageLocalizerHelper<BookStoreResource> LH
@inherits AbpCrudPageBase<IBookAppService, BookDto, Guid, PagedAndSortedResultRequestDto, CreateUpdateBookDto> @inherits AbpCrudPageBase<IBookAppService, BookDto, Guid, PagedAndSortedResultRequestDto, CreateUpdateBookDto>
@ -1396,7 +1395,7 @@ Here's the complete code to create the book management CRUD page, that has been
Field="@nameof(BookDto.Type)" Field="@nameof(BookDto.Type)"
Caption="@L["Type"]"> Caption="@L["Type"]">
<DisplayTemplate> <DisplayTemplate>
@L[$"Enum:BookType.{context.Type}"] @L[$"Enum:BookType.{context.Type:D}"]
</DisplayTemplate> </DisplayTemplate>
</DataGridColumn> </DataGridColumn>
<DataGridColumn TItem="BookDto" <DataGridColumn TItem="BookDto"
@ -1527,6 +1526,14 @@ Here's the complete code to create the book management CRUD page, that has been
</Form> </Form>
</ModalContent> </ModalContent>
</Modal> </Modal>
@code
{
public Books() // Constructor
{
LocalizationResource = typeof(BookStoreResource);
}
}
```` ````
{{end}} {{end}}

28
docs/en/tutorials/book-store/part-05.md

@ -420,6 +420,8 @@ Add the following code block to the end of the `Books.razor` file:
{ {
public Books() // Constructor public Books() // Constructor
{ {
LocalizationResource = typeof(BookStoreResource);
CreatePolicyName = BookStorePermissions.Books.Create; CreatePolicyName = BookStorePermissions.Books.Create;
UpdatePolicyName = BookStorePermissions.Books.Edit; UpdatePolicyName = BookStorePermissions.Books.Edit;
DeletePolicyName = BookStorePermissions.Books.Delete; DeletePolicyName = BookStorePermissions.Books.Delete;
@ -509,14 +511,11 @@ var bookStoreMenu = new ApplicationMenuItem(
context.Menu.AddItem(bookStoreMenu); context.Menu.AddItem(bookStoreMenu);
//CHECK the PERMISSION //CHECK the PERMISSION
if (await context.IsGrantedAsync(BookStorePermissions.Books.Default)) bookStoreMenu.AddItem(new ApplicationMenuItem(
{ "BooksStore.Books",
bookStoreMenu.AddItem(new ApplicationMenuItem( l["Menu:Books"],
"BooksStore.Books", url: "/books"
l["Menu:Books"], ).RequirePermissions(BookStorePermissions.Books.Default));
url: "/books"
));
}
```` ````
You also need to add `async` keyword to the `ConfigureMenuAsync` method and re-arrange the return value. The final `ConfigureMainMenuAsync` method should be the following: You also need to add `async` keyword to the `ConfigureMenuAsync` method and re-arrange the return value. The final `ConfigureMainMenuAsync` method should be the following:
@ -545,14 +544,11 @@ private async Task ConfigureMainMenuAsync(MenuConfigurationContext context)
context.Menu.AddItem(bookStoreMenu); context.Menu.AddItem(bookStoreMenu);
//CHECK the PERMISSION //CHECK the PERMISSION
if (await context.IsGrantedAsync(BookStorePermissions.Books.Default)) bookStoreMenu.AddItem(new ApplicationMenuItem(
{ "BooksStore.Books",
bookStoreMenu.AddItem(new ApplicationMenuItem( l["Menu:Books"],
"BooksStore.Books", url: "/books"
l["Menu:Books"], ).RequirePermissions(BookStorePermissions.Books.Default));
url: "/books"
));
}
} }
```` ````

2
docs/en/tutorials/book-store/part-06.md

@ -41,7 +41,6 @@ Create an `Authors` folder (namespace) in the `Acme.BookStore.Domain` project an
````csharp ````csharp
using System; using System;
using JetBrains.Annotations;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.Domain.Entities.Auditing; using Volo.Abp.Domain.Entities.Auditing;
@ -115,7 +114,6 @@ Created this class inside the `Acme.BookStore.Domain.Shared` project since we wi
````csharp ````csharp
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.Domain.Services; using Volo.Abp.Domain.Services;

7
docs/en/tutorials/book-store/part-09.md

@ -1214,14 +1214,11 @@ You will need to declare a `using Acme.BookStore.Authors;` statement to the begi
Open the `BookStoreMenuContributor.cs` in the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project and add the following code to the end of the `ConfigureMainMenuAsync` method: Open the `BookStoreMenuContributor.cs` in the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project and add the following code to the end of the `ConfigureMainMenuAsync` method:
````csharp ````csharp
if (await context.IsGrantedAsync(BookStorePermissions.Authors.Default)) context.Menu.AddItem(new ApplicationMenuItem(
{
context.Menu.AddItem(new ApplicationMenuItem(
"BooksStore.Authors", "BooksStore.Authors",
l["Menu:Authors"], l["Menu:Authors"],
url: "/authors" url: "/authors"
)); ).RequirePermissions(BookStorePermissions.Books.Default));
}
```` ````
### Localizations ### Localizations

2
docs/en/tutorials/book-store/part-10.md

@ -1132,6 +1132,8 @@ The final `@code` block should be the following:
public Books() // Constructor public Books() // Constructor
{ {
LocalizationResource = typeof(BookStoreResource);
CreatePolicyName = BookStorePermissions.Books.Create; CreatePolicyName = BookStorePermissions.Books.Create;
UpdatePolicyName = BookStorePermissions.Books.Edit; UpdatePolicyName = BookStorePermissions.Books.Edit;
DeletePolicyName = BookStorePermissions.Books.Delete; DeletePolicyName = BookStorePermissions.Books.Delete;

33
framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs

@ -15,6 +15,7 @@ using Volo.Abp.AspNetCore.Auditing;
using Volo.Abp.AspNetCore.ExceptionHandling; using Volo.Abp.AspNetCore.ExceptionHandling;
using Volo.Abp.AspNetCore.Security; using Volo.Abp.AspNetCore.Security;
using Volo.Abp.AspNetCore.Security.Claims; using Volo.Abp.AspNetCore.Security.Claims;
using Volo.Abp.AspNetCore.StaticFiles;
using Volo.Abp.AspNetCore.Tracing; using Volo.Abp.AspNetCore.Tracing;
using Volo.Abp.AspNetCore.Uow; using Volo.Abp.AspNetCore.Uow;
using Volo.Abp.AspNetCore.VirtualFileSystem; using Volo.Abp.AspNetCore.VirtualFileSystem;
@ -126,6 +127,38 @@ public static class AbpApplicationBuilderExtensions
return app.UseMiddleware<AbpDynamicClaimsMiddleware>(); return app.UseMiddleware<AbpDynamicClaimsMiddleware>();
} }
/// <summary>
/// Configures the application to serve static files that match the specified filename patterns with the WebRootFileProvider of the application.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder"/> used to configure the application pipeline.</param>
/// <param name="includeFileNamePatterns">The file name patterns to include when serving static files (e.g., "appsettings*.json").
/// Supports glob patterns. See <see href="https://learn.microsoft.com/en-us/dotnet/core/extensions/file-globbing">Glob patterns documentation</see>.
/// </param>
/// <returns>The <see cref="IApplicationBuilder"/> instance.</returns>
public static IApplicationBuilder UseStaticFilesForPatterns(this IApplicationBuilder app, params string[] includeFileNamePatterns)
{
return UseStaticFilesForPatterns(app, includeFileNamePatterns, app.ApplicationServices.GetRequiredService<IWebHostEnvironment>().WebRootFileProvider);
}
/// <summary>
/// Configures the application to serve static files that match the specified filename patterns with the specified file provider.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder"/> used to configure the application pipeline.</param>
/// <param name="includeFileNamePatterns">The file name patterns to include when serving static files (e.g., "appsettings*.json").
/// Supports glob patterns. See <see href="https://learn.microsoft.com/en-us/dotnet/core/extensions/file-globbing">Glob patterns documentation</see>.
/// </param>
/// <param name="fileProvider">The <see cref="IFileProvider"/> </param>
/// <returns>The <see cref="IApplicationBuilder"/> instance.</returns>
public static IApplicationBuilder UseStaticFilesForPatterns(this IApplicationBuilder app, string[] includeFileNamePatterns, IFileProvider fileProvider)
{
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new AbpStaticFileProvider(includeFileNamePatterns, fileProvider)
});
return app;
}
/// <summary> /// <summary>
/// MapAbpStaticAssets is used to serve the files from the abp virtual file system embedded resources(js/css) and call the MapStaticAssets. /// MapAbpStaticAssets is used to serve the files from the abp virtual file system embedded resources(js/css) and call the MapStaticAssets.
/// </summary> /// </summary>

42
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/StaticFiles/AbpStaticFileProvider.cs

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.FileSystemGlobbing;
using Microsoft.Extensions.Primitives;
namespace Volo.Abp.AspNetCore.StaticFiles;
public class AbpStaticFileProvider : IFileProvider
{
private readonly Matcher _matcher;
private readonly IFileProvider _fileProvider;
/// <param name="fileProvider">The file provider to be used to get the files.</param>
/// <param name="fileNamePatterns">The file name patterns to include when serving static files (e.g., "appsettings*.json").
/// Supports glob patterns. See <see href="https://learn.microsoft.com/en-us/dotnet/core/extensions/file-globbing">Glob patterns documentation</see>.
/// </param>
public AbpStaticFileProvider(IReadOnlyList<string> fileNamePatterns, IFileProvider fileProvider)
{
_fileProvider = fileProvider;
_matcher = new Matcher(StringComparison.OrdinalIgnoreCase);
_matcher.AddIncludePatterns(fileNamePatterns);
}
public IDirectoryContents GetDirectoryContents(string subpath)
{
return new NotFoundDirectoryContents();
}
public IFileInfo GetFileInfo(string subpath)
{
return _matcher.Match(Path.GetFileName(subpath)).HasMatches ?
_fileProvider.GetFileInfo(subpath) :
new NotFoundFileInfo(subpath);
}
public IChangeToken Watch(string filter)
{
return NullChangeToken.Singleton;
}
}

6
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/AuthService.cs

@ -85,7 +85,11 @@ public class AuthService : IAuthService, ITransientDependency
} }
var accessToken = await AuthenticationService.GetAccessTokenAsync(configuration); var accessToken = await AuthenticationService.GetAccessTokenAsync(configuration);
if (!Directory.Exists(CliPaths.Root))
{
Directory.CreateDirectory(CliPaths.Root);
}
File.WriteAllText(CliPaths.AccessToken, accessToken, Encoding.UTF8); File.WriteAllText(CliPaths.AccessToken, accessToken, Encoding.UTF8);
} }

53
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/VoloNugetPackagesVersionUpdater.cs

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using NuGet.Versioning; using NuGet.Versioning;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -39,6 +40,7 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency
var latestVersionInfo = await _packageVersionCheckerService.GetLatestVersionOrNullAsync("Volo.Abp.Core", includeReleaseCandidates: includeReleaseCandidates); var latestVersionInfo = await _packageVersionCheckerService.GetLatestVersionOrNullAsync("Volo.Abp.Core", includeReleaseCandidates: includeReleaseCandidates);
var latestReleaseCandidateVersionInfo = await _packageVersionCheckerService.GetLatestVersionOrNullAsync("Volo.Abp.Core", includeReleaseCandidates: true); var latestReleaseCandidateVersionInfo = await _packageVersionCheckerService.GetLatestVersionOrNullAsync("Volo.Abp.Core", includeReleaseCandidates: true);
var latestVersionFromMyGet = await GetLatestVersionFromMyGet("Volo.Abp.Core"); var latestVersionFromMyGet = await GetLatestVersionFromMyGet("Volo.Abp.Core");
var latestStableVersions = await _packageVersionCheckerService.GetLatestStableVersionsAsync();
async Task UpdateAsync(string filePath) async Task UpdateAsync(string filePath)
{ {
@ -55,7 +57,8 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency
latestVersionInfo.Version, latestVersionInfo.Version,
latestReleaseCandidateVersionInfo.Version, latestReleaseCandidateVersionInfo.Version,
latestVersionFromMyGet, latestVersionFromMyGet,
version); version,
latestStableVersions: latestStableVersions);
fs.Seek(0, SeekOrigin.Begin); fs.Seek(0, SeekOrigin.Begin);
fs.SetLength(0); fs.SetLength(0);
@ -83,6 +86,7 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency
var latestVersionInfo = await _packageVersionCheckerService.GetLatestVersionOrNullAsync("Volo.Abp.Core"); var latestVersionInfo = await _packageVersionCheckerService.GetLatestVersionOrNullAsync("Volo.Abp.Core");
var latestReleaseCandidateVersionInfo = await _packageVersionCheckerService.GetLatestVersionOrNullAsync("Volo.Abp.Core", includeReleaseCandidates: true); var latestReleaseCandidateVersionInfo = await _packageVersionCheckerService.GetLatestVersionOrNullAsync("Volo.Abp.Core", includeReleaseCandidates: true);
var latestVersionFromMyGet = await GetLatestVersionFromMyGet("Volo.Abp.Core"); var latestVersionFromMyGet = await GetLatestVersionFromMyGet("Volo.Abp.Core");
var latestStableVersions = await _packageVersionCheckerService.GetLatestStableVersionsAsync();
using (var fs = File.Open(projectPath, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) using (var fs = File.Open(projectPath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
{ {
@ -97,7 +101,8 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency
latestVersionInfo.Version, latestVersionInfo.Version,
latestReleaseCandidateVersionInfo.Version, latestReleaseCandidateVersionInfo.Version,
latestVersionFromMyGet, latestVersionFromMyGet,
version); version,
latestStableVersions: latestStableVersions);
fs.Seek(0, SeekOrigin.Begin); fs.Seek(0, SeekOrigin.Begin);
fs.SetLength(0); fs.SetLength(0);
@ -114,13 +119,20 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency
protected virtual async Task UpdateInternalAsync(string projectPath, bool includeNightlyPreviews = false, bool includeReleaseCandidates = false, bool switchToStable = false) protected virtual async Task UpdateInternalAsync(string projectPath, bool includeNightlyPreviews = false, bool includeReleaseCandidates = false, bool switchToStable = false)
{ {
var latestStableVersions = await _packageVersionCheckerService.GetLatestStableVersionsAsync();
using (var fs = File.Open(projectPath, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) using (var fs = File.Open(projectPath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
{ {
using (var sr = new StreamReader(fs, Encoding.Default, true)) using (var sr = new StreamReader(fs, Encoding.Default, true))
{ {
var fileContent = await sr.ReadToEndAsync(); var fileContent = await sr.ReadToEndAsync();
var updatedContent = await UpdateVoloPackagesAsync(fileContent, includeNightlyPreviews, includeReleaseCandidates, switchToStable); var updatedContent = await UpdateVoloPackagesAsync(
fileContent,
includeNightlyPreviews,
includeReleaseCandidates,
switchToStable,
latestStableVersions: latestStableVersions);
fs.Seek(0, SeekOrigin.Begin); fs.Seek(0, SeekOrigin.Begin);
fs.SetLength(0); fs.SetLength(0);
@ -153,7 +165,8 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency
SemanticVersion latestNugetVersion = null, SemanticVersion latestNugetVersion = null,
SemanticVersion latestNugetReleaseCandidateVersion = null, SemanticVersion latestNugetReleaseCandidateVersion = null,
string latestMyGetVersion = null, string latestMyGetVersion = null,
string specifiedVersion = null) string specifiedVersion = null,
List<PackageVersionCheckerService.LatestStableVersionResult> latestStableVersions = null)
{ {
string packageId = null; string packageId = null;
@ -206,29 +219,39 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency
if (!specifiedVersion.IsNullOrWhiteSpace()) if (!specifiedVersion.IsNullOrWhiteSpace())
{ {
if (isLeptonXPackage || isStudioPackage) var leptonXPackageVersion = latestStableVersions?
.FirstOrDefault(v => v.Version.Equals(specifiedVersion, StringComparison.InvariantCultureIgnoreCase))?.LeptonX?.Version;
if ((isLeptonXPackage && string.IsNullOrWhiteSpace(leptonXPackageVersion)) || isStudioPackage)
{ {
Logger.LogWarning("Package: {PackageId} could not be updated. Please manually update the package version yourself to prevent version mismatches!", packageId); Logger.LogWarning("Package: {PackageId} could not be updated. Please manually update the package version yourself to prevent version mismatches!", packageId);
continue; continue;
} }
if (await SpecifiedVersionExists(specifiedVersion, packageId)) var isLeptonXPackageWithVersion = isLeptonXPackage && !string.IsNullOrWhiteSpace(leptonXPackageVersion);
if (isLeptonXPackageWithVersion || await SpecifiedVersionExists(specifiedVersion, packageId))
{
TryUpdatingPackage(isLeptonXPackageWithVersion ? leptonXPackageVersion : specifiedVersion);
}
else
{ {
var specifiedSemanticVersion = SemanticVersion.Parse(specifiedVersion); Logger.LogWarning("Package \"{PackageId}\" specified version v{SpecifiedVersion} does not exist!", packageId, specifiedVersion);
}
void TryUpdatingPackage(string versionToUpdate)
{
var specifiedSemanticVersion = SemanticVersion.Parse(versionToUpdate);
if (specifiedSemanticVersion > currentSemanticVersion) if (specifiedSemanticVersion > currentSemanticVersion)
{ {
Logger.LogInformation("Updating package \"{PackageId}\" from v{CurrentVersion} to v{SpecifiedVersion}", packageId, currentVersion, specifiedVersion); Logger.LogInformation("Updating package \"{PackageId}\" from v{CurrentVersion} to v{SpecifiedVersion}", packageId, currentVersion, versionToUpdate);
versionAttribute.Value = specifiedVersion; versionAttribute.Value = versionToUpdate;
} }
else else
{ {
Logger.LogWarning("Unable to update package \"{PackageId}\" version v{CurrentVersion} to v{SpecifiedVersion}", packageId, currentVersion, specifiedVersion); Logger.LogWarning("Unable to update package \"{PackageId}\" version v{CurrentVersion} to v{SpecifiedVersion}", packageId, currentVersion, versionToUpdate);
} }
} }
else
{
Logger.LogWarning("Package \"{PackageId}\" specified version v{SpecifiedVersion} does not exist!", packageId, specifiedVersion);
}
} }
else else
{ {
@ -252,7 +275,7 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency
} }
else else
{ {
latestVersion = latestMyGetVersion == null ? await GetLatestVersionFromMyGet(packageId) : latestMyGetVersion; latestVersion = latestMyGetVersion ?? await GetLatestVersionFromMyGet(packageId);
} }
if(latestVersion == null) if(latestVersion == null)

30
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Version/PackageVersionCheckerService.cs

@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Cli.Http; using Volo.Abp.Cli.Http;
@ -111,6 +112,11 @@ public class PackageVersionCheckerService : ITransientDependency
? new LatestVersionInfo(semanticVersion, latestStableVersionResult.Message) ? new LatestVersionInfo(semanticVersion, latestStableVersionResult.Message)
: null; : null;
} }
public async Task<List<LatestStableVersionResult>> GetLatestStableVersionsAsync()
{
return await GetLatestStableVersionsInternalAsync();
}
private static ConcurrentDictionary<string, bool> CommercialPackagesCache { get; } = new (); private static ConcurrentDictionary<string, bool> CommercialPackagesCache { get; } = new ();
@ -225,7 +231,7 @@ public class PackageVersionCheckerService : ITransientDependency
_apiKeyResult ??= await _apiKeyService.GetApiKeyOrNullAsync(); _apiKeyResult ??= await _apiKeyService.GetApiKeyOrNullAsync();
} }
private async Task<LatestStableVersionResult> GetLatestStableVersionOrNullAsync() private async Task<List<LatestStableVersionResult>> GetLatestStableVersionsInternalAsync()
{ {
try try
{ {
@ -241,16 +247,24 @@ public class PackageVersionCheckerService : ITransientDependency
var content = await responseMessage.Content.ReadAsStringAsync(); var content = await responseMessage.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<List<LatestStableVersionResult>>(content); var result = JsonSerializer.Deserialize<List<LatestStableVersionResult>>(content);
return result.OrderBy(q => q.Type.ToLowerInvariant() == "stable").ThenBy(q => SemanticVersion.Parse(q.Version)).ToList();
return result.FirstOrDefault(x => x.Type.ToLowerInvariant() == "stable");
} }
} }
catch catch
{ {
return null; return [];
} }
} }
private async Task<LatestStableVersionResult> GetLatestStableVersionOrNullAsync()
{
var latestStableVersionsResult = await GetLatestStableVersionsInternalAsync();
return latestStableVersionsResult.Count <= 0
? null
: latestStableVersionsResult.FirstOrDefault();
}
public class NuGetSearchResultDto public class NuGetSearchResultDto
{ {
public int TotalHits { get; set; } public int TotalHits { get; set; }
@ -270,6 +284,11 @@ public class PackageVersionCheckerService : ITransientDependency
public List<string> Versions { get; set; } public List<string> Versions { get; set; }
} }
public class LeptonXThemeInfo
{
public string Version { get; set; }
}
public class LatestStableVersionResult public class LatestStableVersionResult
{ {
public string Version { get; set; } public string Version { get; set; }
@ -279,5 +298,8 @@ public class PackageVersionCheckerService : ITransientDependency
public string Type { get; set; } public string Type { get; set; }
public string Message { get; set; } public string Message { get; set; }
[CanBeNull]
public LeptonXThemeInfo LeptonX { get; set; }
} }
} }

1
framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo.Abp.EntityFrameworkCore.Oracle.csproj

@ -21,7 +21,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" />
<PackageReference Include="Oracle.EntityFrameworkCore" /> <PackageReference Include="Oracle.EntityFrameworkCore" />
</ItemGroup> </ItemGroup>

23
latest-versions.json

@ -3,6 +3,27 @@
"version": "9.0.1", "version": "9.0.1",
"releaseDate": "", "releaseDate": "",
"type": "stable", "type": "stable",
"message": "" "message": "",
"leptonx": {
"version": "4.0.1"
}
},
{
"version": "9.0.0",
"releaseDate": "",
"type": "stable",
"message": "",
"leptonx": {
"version": "4.0.0"
}
},
{
"version": "8.3.1",
"releaseDate": "",
"type": "stable",
"message": "",
"leptonx": {
"version": "3.3.1"
}
} }
] ]

2
modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.cs

@ -154,7 +154,7 @@ public partial class PermissionManagementModal
var updateDto = new UpdatePermissionsDto var updateDto = new UpdatePermissionsDto
{ {
Permissions = _groups Permissions = _allGroups
.SelectMany(g => g.Permissions) .SelectMany(g => g.Permissions)
.Select(p => new UpdatePermissionDto { IsGranted = p.IsGranted, Name = p.Name }) .Select(p => new UpdatePermissionDto { IsGranted = p.IsGranted, Name = p.Name })
.ToArray() .ToArray()

Loading…
Cancel
Save