diff --git a/docs/en/cli/new-command-samples.md b/docs/en/cli/new-command-samples.md index 6b168b538c..a8d469b10b 100644 --- a/docs/en/cli/new-command-samples.md +++ b/docs/en/cli/new-command-samples.md @@ -221,6 +221,79 @@ As seen below, ABP libraries are local project references. ``` +## Using Existing Configuration + +If you want to programmaticaly create solutions, you can use an existing configuration instead of passing parameters to CLI one by one. ABP Studio keeps the solution creation history locally in `(UserProfile)\.abp\studio\solution-creation-history.json` file, there you can find the configurations of the solutions created in your machine. + +### Using a Solution Id + +In `*.abpsln` file of the solutions, there is an ID field that you can use to recreate a solution. To do this, pass the id to cli using `-shi or --solution-history-id` parameters. + +```bash +abp new -shi dbb1afa9-190e-419a-842d-2780bb1bad1f +abp new -shi dbb1afa9-190e-419a-842d-2780bb1bad1f -o D:\test\Acme.BookStore +``` + +### Using a JSON Configuration File + +You can also use a configuration file to create solutions. You need to use `-rcp or ready-config-path` parameters to do that. + +```bash +abp new -rcp MyTests\config.json +abp new -rcp D:\MyTests\config.json +abp new -rcp D:\MyTests\config.json -o D:\test\Acme.BookStore +``` + +To prepare a config file, you can check the records in `solution-creation-history.json` file mentioned above. An example config file would look like that: + +```json +{ + "solutionName": { + "fullName": "Acme.BookStore", + "companyName": "Acme", + "projectName": "BookStore" + }, + "pro": true, + "useOpenSourceTemplate": false, + "booksSample": false, + "databaseProvider": "ef", + "createInitialMigration": true, + "runDbMigrator": true, + "uiFramework": "angular", + "theme": "leptonx", + "themeStyle": "system", + "mobileFramework": "none", + "databaseManagementSystem": "sqlserver", + "databaseManagementSystemBuilderExtensionMethod": "UseSqlServer", + "connectionString": "Server=(LocalDb)\\\\MSSQLLocalDB;Database=BookStore;Trusted_Connection=True;TrustServerCertificate=true", + "mauiBlazorApplicationIdGuid": "d3499a09-f3d4-4bb7-9d58-4c7b1caee331", + "tiered": false, + "publicWebsite": false, + "cmskit": false, + "openIddictAdmin": true, + "languageManagement": true, + "textTemplateManagement": true, + "multiTenancy": true, + "auditLogging": false, + "gdpr": true, + "chat": false, + "fileManagement": false, + "socialLogins": true, + "includeTests": true, + "distributedEventBus": "none", + "publicRedis": false, + "separateTenantSchema": false, + "progressiveWebApp": false, + "runProgressiveWebAppSupport": false, + "runInstallLibs": false, + "runBundling": false, + "kubernetesConfiguration": true, + "templateName": "app" + } +``` + + + ## See Also * [ABP CLI documentation](../cli/index.md) diff --git a/docs/en/deployment/forwarded-headers.md b/docs/en/deployment/forwarded-headers.md new file mode 100644 index 0000000000..b6b74205c3 --- /dev/null +++ b/docs/en/deployment/forwarded-headers.md @@ -0,0 +1,84 @@ +# Forwarded Headers + +Reverse proxies and load balancers play a crucial role in modern web application architectures. When an application is deployed behind these proxies and load balancers, several specific issues can arise. This document will discuss these issues in detail, explain how ASP.NET Core's forwarded headers middleware can address them, and provide a code example for configuring forwarded headers in an ABP application. + +## Possible problem in a Reverse Proxy Environment + +When requests pass through a reverse proxy or load balancer, the following common issues can occur: + +### 1. Loss of Original Request Information + +A reverse proxy or load balancer typically modifies the original HTTP request headers. For example, the proxy may replace the client's `X-Forwarded-For` header, or the `Host` header might be set to the proxy's address. This can result in the backend application being unable to directly access the client's IP address, the true hostname, and the protocol used. + +### 2. HTTPS vs HTTP Protocol Confusion + +When a request is forwarded by a proxy server, it is often upgraded to HTTPS to ensure secure transmission. The proxy server will send a header like `X-Forwarded-Proto` to indicate whether the original request was HTTP or HTTPS. If the backend application does not correctly handle this header, it may generate URLs with the wrong protocol. + +### 3. Path Handling Issues + +Since load balancers and proxies might modify or map the request URL paths differently, the backend application could encounter path inconsistencies. For example, a reverse proxy might forward a request from `/api` to `/myapp/api`. If the backend application is not correctly configured, path parsing errors may occur. + +### 4. IP Address and Security + +Reverse proxies might replace the original client IP address with their own, which can affect logging, authentication, and access control mechanisms. To retrieve the actual client IP address, the `X-Forwarded-For` header must be correctly parsed and trusted. + +### 5. Load Balancer Impact + +Load balancers might distribute requests to different backend servers using different algorithms. This can create session affinity problems. If session data is stored on a single server and the load balancer directs subsequent requests to different servers, session loss or inconsistency may occur. + +## Forwarded Headers Middleware in ABP web application + +To resolve the above issues, ASP.NET Core provides a built-in middleware, `ForwardedHeadersMiddleware`, which processes the headers forwarded by reverse proxies. This middleware helps the application recover the correct original request information, such as the client’s IP address, protocol, and host. + +### Configuring `ForwardedHeadersMiddleware` + +ASP.NET Core’s `ForwardedHeadersMiddleware` supports several HTTP headers: + +- **X-Forwarded-For**: Contains the original client’s IP address. +- **X-Forwarded-Proto**: Indicates whether the original request was HTTP or HTTPS. +- **X-Forwarded-Host**: Contains the original host requested by the client. +- **X-Forwarded-Port**: Indicates the original port of the request. + +To configure this middleware: + +1. In the `ConfigureServices` method of your module, configure the `ForwardedHeadersOptions`: + +```csharp +public override void ConfigureServices(ServiceConfigurationContext context) +{ + context.Services.Configure(options => + { + options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; + }); +} +``` + +2. In the `OnApplicationInitialization` method of your module, add the middleware: + +> Forwarded Headers Middleware should run before other middleware. This ordering ensures that the middleware relying on forwarded headers information can consume the header values for processing. Forwarded Headers Middleware can run after diagnostics and error handling, but it must be run before calling UseHsts: + +```csharp +public override void OnApplicationInitialization(ApplicationInitializationContext context) +{ + var app = context.GetApplicationBuilder(); + var env = context.GetEnvironment(); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + app.UseForwardedHeaders(); + } + else + { + app.UseErrorPage(); + app.UseForwardedHeaders(); + app.UseHsts(); + } + + // Other middleware configurations... +} +``` + +## References + +- [ASP.NET Core Proxy and Load Balancer Configuration](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-9.0) diff --git a/docs/en/deployment/index.md b/docs/en/deployment/index.md index 3537e4593e..245c8bdaf0 100644 --- a/docs/en/deployment/index.md +++ b/docs/en/deployment/index.md @@ -12,3 +12,4 @@ However, there are some topics that you should care about when you are deploying * [Optimization for Production](./optimizing-production.md): Tips and suggestions for optimizing your application in production environments. * [Deploying to a Clustered Environment](./clustered-environment.md): Explains how to configure your application when you want to run multiple instances of your application concurrently. * [Deploying Distributed / Microservice Solutions](./distributed-microservice.md): Deployment notes for solutions consisting of multiple applications and/or services. +* [Forwarded Headers](./forwarded-headers): Explains how to configure the application to trust headers forwarded by reverse proxies and recover the original request information from the `X-Forwarded-For` and `X-Forwarded-Proto` headers. \ No newline at end of file diff --git a/docs/en/docs-params.json b/docs/en/docs-params.json index 46e496f248..e108f1b554 100644 --- a/docs/en/docs-params.json +++ b/docs/en/docs-params.json @@ -7,6 +7,7 @@ "MVC": "MVC / Razor Pages", "Blazor": "Blazor WebAssembly", "BlazorServer": "Blazor Server", + "BlazorWebApp": "Blazor WebApp", "NG": "Angular" } }, diff --git a/docs/en/get-started/layered-web-application.md b/docs/en/get-started/layered-web-application.md index 188e0cfd15..e8896b8666 100644 --- a/docs/en/get-started/layered-web-application.md +++ b/docs/en/get-started/layered-web-application.md @@ -3,7 +3,7 @@ ````json //[doc-params] { - "UI": ["MVC", "Blazor", "BlazorServer", "NG"], + "UI": ["MVC", "Blazor", "BlazorServer", "BlazorWebApp", "NG"], "DB": ["EF", "Mongo"], "Tiered": ["Yes", "No"] } @@ -162,7 +162,7 @@ You can start the following application(s): {{ else if UI == "Blazor" }} {{ if Tiered == "No" }}- `Acme.BookStore.HttpApi.Host`{{ end }} - `Acme.BookStore.Blazor` -{{ else if UI == "BlazorServer" }} +{{ else if UI == "BlazorServer" || UI == "BlazorWebApp" }} - `Acme.BookStore.Blazor` {{ else }} - `Acme.BookStore.Web` @@ -174,7 +174,7 @@ You can start the following application(s): > Notice that the services running in docker-compose are exposed to your localhost. If any service in your localhost is already using the same port(s), you will get an error. In that case, stop your local services first. {{ end }} -Once the `Acme.BookStore.{{ if UI == "NG" }}Angular{{ else if UI == "BlazorServer" || UI == "Blazor" }}Blazor{{ else }}Web{{ end }}` application started, you can right-click it and select the *Browse* command: +Once the `Acme.BookStore.{{ if UI == "NG" }}Angular{{ else if UI == "BlazorServer" || UI == "Blazor" || UI == "BlazorWebApp" }}Blazor{{ else }}Web{{ end }}` application started, you can right-click it and select the *Browse* command: ![abp-studio-quick-start-browse-command](images/abp-studio-quick-start-browse-command.png) @@ -206,7 +206,7 @@ Once the solution is opened in Visual Studio, you should see a screen like shown ![visual-studio-bookstore-application](images/visual-studio-bookstore-application.png) -Right-click the `Acme.BookStore.{{ if UI == "NG" || UI == "Blazor" }}HttpApi.Host{{ else if UI == "BlazorServer" }}Blazor{{ else }}Web{{ end }}` project and select the *Set as Startup Project* command. You can then hit *F5* or *Ctrl + F5* to run the web application. It will run and open the application UI in your default browser: +Right-click the `Acme.BookStore.{{ if UI == "NG" || UI == "Blazor" }}HttpApi.Host{{ else if UI == "BlazorServer" || UI == "BlazorWebApp" }}Blazor{{ else }}Web{{ end }}` project and select the *Set as Startup Project* command. You can then hit *F5* or *Ctrl + F5* to run the web application. It will run and open the application UI in your default browser: ![bookstore-browser-users-page](images/bookstore-browser-users-page.png) @@ -242,4 +242,4 @@ Before starting the mobile application, ensure that you configure it for [react- > For example in non-tiered MVC with public website application: -![solution-runner-public-website](images/solution-runner-public-website.png) \ No newline at end of file +![solution-runner-public-website](images/solution-runner-public-website.png) diff --git a/docs/en/release-info/release-notes.md b/docs/en/release-info/release-notes.md index e94086e14f..b86da2c079 100644 --- a/docs/en/release-info/release-notes.md +++ b/docs/en/release-info/release-notes.md @@ -4,11 +4,9 @@ This document contains **brief release notes** for each release. Release notes o > If you want to read the release notes for each ABP Studio release, check it out from [here](../studio/release-notes.md). -## 9.0 (2024-10-22) +## 9.0 (2024-11-19) -> This version is currently in preview. The final release date is planned for November, 2024. - -See the detailed **[blog post / announcement](https://abp.io/blog/announcing-abp-9-0-release-candidate)** for the v9.0 release. +See the detailed **[blog post / announcement](https://abp.io/blog/abp-9-0-stable-release-with-dotnet-9-0)** for the v9.0 release. * Upgraded to .NET 9.0 * Introducing the `Extension Property Policy` diff --git a/docs/en/studio/release-notes.md b/docs/en/studio/release-notes.md index c817e3a794..5937a556ed 100644 --- a/docs/en/studio/release-notes.md +++ b/docs/en/studio/release-notes.md @@ -2,6 +2,10 @@ 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.8 (2024-11-20) + +* Upgraded templates to version `8.3.4` + ## 0.9.7 (2024-11-19) * Added `AppearanceStyles` component to blazor server templates diff --git a/docs/en/studio/version-mapping.md b/docs/en/studio/version-mapping.md index 0318468ca9..63c6bd7f0f 100644 --- a/docs/en/studio/version-mapping.md +++ b/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** | |------------------------|---------------------------| +| 0.9.8 | 8.3.4 | | 0.9.5 to 0.9.7 | 8.3.3 | | 0.9.2 to 0.9.4 | 8.3.2 | | 0.8.4 - 0.9.1 | 8.3.1 | diff --git a/docs/en/tutorials/modular-crm/part-01.md b/docs/en/tutorials/modular-crm/part-01.md index 61698fb48a..316aff6150 100644 --- a/docs/en/tutorials/modular-crm/part-01.md +++ b/docs/en/tutorials/modular-crm/part-01.md @@ -10,7 +10,7 @@ } ```` -Follow the *[Get Stared](../../get-started/layered-web-application.md)* guide to create a new layered web application with the following configuration: +Follow the *[Get Started](../../get-started/layered-web-application.md)* guide to create a new layered web application with the following configuration: * **Solution name**: `ModularCrm` * **UI Framework**: ASP.NET Core MVC / Razor Pages @@ -34,4 +34,4 @@ Initially, you see a `ModularCrm` solution and a `ModularCrm` module under that ## Summary -We've created the initial layered monolith solution. In the next part, we will learn how to create a new application module and install it to the main application. \ No newline at end of file +We've created the initial layered monolith solution. In the next part, we will learn how to create a new application module and install it to the main application. diff --git a/docs/en/tutorials/todo/layered/index.md b/docs/en/tutorials/todo/layered/index.md index 2eef34bbd2..a67076dad1 100644 --- a/docs/en/tutorials/todo/layered/index.md +++ b/docs/en/tutorials/todo/layered/index.md @@ -74,7 +74,7 @@ dotnet tool install -g Volo.Abp.Studio.Cli Create an empty folder, open a command-line terminal and execute the following command in the terminal: ````bash -abp new TodoApp{{if UI=="Blazor"}} -u blazor{{else if UI=="BlazorServer"}} -u blazor-server{{else if UI=="NG"}} -u angular{{end}}{{if DB=="Mongo"}} -d mongodb{{end}} +abp new TodoApp{{if UI=="Blazor"}} -u blazor{{else if UI=="BlazorServer"}} -u blazor-server{{else if UI=="BlazorWebApp"}} -u blazor-webapp{{else if UI=="NG"}} -u angular{{end}}{{if DB=="Mongo"}} -d mongodb{{end}} ```` {{if UI=="NG"}} @@ -113,13 +113,14 @@ abp install-libs > We suggest you install [Yarn](https://classic.yarnpkg.com/) to prevent possible package inconsistencies, if you haven't installed it yet. -{{if UI=="Blazor" || UI=="BlazorServer"}} +{{if UI=="Blazor" || UI=="BlazorWebApp"}} #### Bundling and Minification `abp bundle` command offers bundling and minification support for client-side resources (JavaScript and CSS files) for Blazor projects. This command automatically run when you create a new solution with the [ABP CLI](../../../cli/index.md). -However, sometimes you might need to run this command manually. To update script & style references without worrying about dependencies, ordering, etc. in a project, you can run this command in the directory of your blazor application: +However, sometimes you might need to run this command manually. To update script & style references without worrying about dependencies, ordering, etc. in a project, you can run this command in the directory of your `Blazor.Client` application: + ````bash abp bundle @@ -131,7 +132,7 @@ abp bundle ### Run the Application -{{if UI=="MVC" || UI=="BlazorServer"}} +{{if UI=="MVC" || UI=="BlazorServer" || UI=="BlazorWebApp"}} It is good to run the application before starting the development. Ensure the {{if UI=="BlazorServer"}}`TodoApp.Blazor`{{else}}`TodoApp.Web`{{end}} project is the startup project, then run the application (Ctrl+F5 in Visual Studio) to see the initial UI: @@ -148,10 +149,6 @@ Ensure the `TodoApp.HttpApi.Host` project is the startup project, then run the a You can explore and test your HTTP API with this UI. Now, we can set the `TodoApp.Blazor` as the startup project and run it to open the actual Blazor application UI: -{{else if UI=="BlazorWebApp" }} - -It is good to run the application before starting the development. Ensure the `TodoApp.Blazor` project is the startup project, then run the application (Ctrl+F5 in Visual Studio) to see the initial UI: - {{else if UI=="NG"}} It is good to run the application before starting the development. The solution has two main applications: @@ -589,7 +586,7 @@ If you open the [Swagger UI](https://swagger.io/tools/swagger-ui/) by entering t ### Index.razor.cs -Open the `Index.razor.cs` file in the `Pages` folder of the {{if UI=="BlazorWebApp"}} *TodoApp.Blazor.Client* {{else}}*TodoApp.Blazor*{{end}} project and replace the content with the following code block: +Open the `Index.razor.cs` file in the `Pages` folder of the {{if UI=="Blazor" || UI=="BlazorWebApp"}} *TodoApp.Blazor.Client* {{else}}*TodoApp.Blazor*{{end}} project and replace the content with the following code block: ```csharp using Microsoft.AspNetCore.Components; @@ -638,7 +635,7 @@ See the *Dynamic C# Proxies & Auto API Controllers* section below to learn how w ### Index.razor -Open the `Index.razor` file in the `Pages` folder of the {{if UI=="BlazorWebApp"}} *TodoApp.Blazor.Client* {{else}} *TodoApp.Blazor* {{end}} project and replace the content with the following code block: +Open the `Index.razor` file in the `Pages` folder of the {{if UI=="Blazor" || UI=="BlazorWebApp"}} *TodoApp.Blazor.Client* {{else}} *TodoApp.Blazor* {{end}} project and replace the content with the following code block: ```xml @page "/" @@ -680,7 +677,7 @@ Open the `Index.razor` file in the `Pages` folder of the {{if UI=="BlazorWebApp" ### Index.razor.css -As the final touch, open the `Index.razor.css` file in the `Pages` folder of the {{if UI=="BlazorWebApp"}}*TodoApp.Blazor.Client*{{else}}*TodoApp.Blazor*{{end}} project and replace it with the following content: +As the final touch, open the `Index.razor.css` file in the `Pages` folder of the {{if UI=="Blazor" || UI=="BlazorWebApp"}}*TodoApp.Blazor.Client*{{else}}*TodoApp.Blazor*{{end}} project and replace it with the following content: ```css #TodoList{ diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpDynamicClaimsMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpDynamicClaimsMiddleware.cs index b2bbb78e7b..36012a123b 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpDynamicClaimsMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpDynamicClaimsMiddleware.cs @@ -2,7 +2,6 @@ using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Features.Authentication; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Volo.Abp.AspNetCore.Middleware; @@ -27,12 +26,10 @@ public class AbpDynamicClaimsMiddleware : AbpMiddlewareBase, ITransientDependenc var abpClaimsPrincipalFactory = context.RequestServices.GetRequiredService(); var user = await abpClaimsPrincipalFactory.CreateDynamicAsync(context.User); - authenticateResultFeature.AuthenticateResult = AuthenticateResult.Success(new AuthenticationTicket(user, authenticationType)); - var httpAuthenticationFeature = context.Features.Get(); - if (httpAuthenticationFeature != null) - { - httpAuthenticationFeature.User = authenticateResultFeature.AuthenticateResult.Principal; - } + authenticateResultFeature.AuthenticateResult = AuthenticateResult.Success(new AuthenticationTicket( + user, + authenticateResultFeature?.AuthenticateResult?.Properties, + authenticationType)); } if (context.User.Identity?.IsAuthenticated == false)