Skip to content

Commit 37b6d46

Browse files
committed
Add documentation for using incremental setup with Aspire
1 parent fb33eba commit 37b6d46

4 files changed

Lines changed: 243 additions & 0 deletions

File tree

aspnetcore/migration/fx-to-core/areas/authentication.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,8 @@ There are just a few small code changes needed to enable remote authentication i
181181

182182
First, follow the [remote app setup](xref:migration/fx-to-core/inc/remote-app-setup) instructions to connect the ASP.NET Core and ASP.NET apps. Then, there are just a couple extra extension methods to call to enable remote app authentication.
183183

184+
:::zone pivot="manual"
185+
184186
#### ASP.NET app configuration
185187

186188
The ASP.NET app needs to be configured to add the authentication endpoint. Adding the authentication endpoint is done by calling the `AddAuthenticationServer` extension method to set up the HTTP module that watches for requests to the authentication endpoint. Note that remote authentication scenarios typically want to add proxy support as well, so that any authentication related redirects correctly route to the ASP.NET Core app rather than the ASP.NET one.
@@ -195,6 +197,25 @@ Next, the ASP.NET Core app needs to be configured to enable the authentication h
195197

196198
The boolean that is passed to the `AddAuthenticationClient` call specifies whether remote app authentication should be the default authentication scheme. Passing `true` will cause the user to be authenticated via remote app authentication for all requests, whereas passing `false` means that the user will only be authenticated with remote app authentication if the remote app scheme is specifically requested (with `[Authorize(AuthenticationSchemes = RemoteAppAuthenticationDefaults.AuthenticationScheme)]` on a controller or action method, for example). Passing false for this parameter has the advantage of only making HTTP requests to the original ASP.NET app for authentication for endpoints that require remote app authentication but has the disadvantage of requiring annotating all such endpoints to indicate that they will use remote app auth.
197199

200+
:::zone-end
201+
202+
:::zone pivot="aspire"
203+
When using Aspire, the configuration will be done via environment variables and are set by the AppHost. To enable remote session, the option must be enabled:
204+
205+
```csharp
206+
...
207+
208+
var coreApp = builder.AddProject<Projects.AuthRemoteIdentityCore>("core")
209+
.WithHttpHealthCheck()
210+
.WaitFor(frameworkApp)
211+
.WithIncrementalMigrationFallback(frameworkApp, options => options.RemoteAuthentication = RemoteAuthentication.DefaultScheme);
212+
213+
...
214+
```
215+
216+
Once this is done, it will be automatically hooked up in both the framework and core applications.
217+
:::zone-end
218+
198219
#### Using Remote Authentication with Specific Endpoints
199220

200221
When you set the default scheme to `false`, you can specify remote authentication for specific controllers or actions:

aspnetcore/migration/fx-to-core/areas/session.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ monikerRange: '>= aspnetcore-6.0'
77
ms.date: 11/9/2022
88
ms.topic: article
99
uid: migration/fx-to-core/areas/session
10+
zone_pivot_groups: migration-remote-app-setup
1011
---
1112

1213
# Migrate ASP.NET Framework Session to ASP.NET Core
@@ -178,6 +179,7 @@ Out of the box, there is a simple JSON serializer that allows each session key t
178179

179180
### Application configuration
180181

182+
:::zone pivot="manual"
181183
**ASP.NET Core configuration:**
182184

183185
Call `AddRemoteAppSession` and `AddJsonSessionSerializer` to register known session item types:
@@ -200,6 +202,26 @@ Add this change to `Global.asax.cs`:
200202

201203
:::code language="csharp" source="~/migration/fx-to-core/areas/session/samples/remote/Global.asax.cs":::
202204

205+
:::zone-end
206+
207+
:::zone pivot="aspire"
208+
When using Aspire, the configuration will be done via environment variables and are set by the AppHost. To enable remote session, the option must be enabled:
209+
210+
```csharp
211+
...
212+
213+
var coreApp = builder.AddProject<Projects.CoreApplication>("core")
214+
.WithHttpHealthCheck()
215+
.WaitFor(frameworkApp)
216+
.WithIncrementalMigrationFallback(frameworkApp, options => options.RemoteSession = RemoteSession.Enabled);
217+
218+
...
219+
```
220+
221+
Once this is done, it will be automatically hooked up in both the framework and core applications.
222+
223+
:::zone-end
224+
203225
### Communication protocol
204226

205227
#### Readonly sessions

aspnetcore/migration/fx-to-core/inc/remote-app-setup.md

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ monikerRange: '>= aspnetcore-6.0'
77
ms.date: 11/9/2022
88
ms.topic: article
99
uid: migration/fx-to-core/inc/remote-app-setup
10+
zone_pivot_groups: migration-remote-app-setup
1011
---
1112

1213
# Remote app setup
@@ -26,6 +27,8 @@ Common scenarios this enables:
2627
>
2728
> The virtual directory setup is used for route generation, authorization, and other services within the system. At this point, no reliable method has been found to enable different virtual directories due to how ASP.NET Framework works.
2829
30+
:::zone pivot="manual"
31+
2932
To enable the ASP.NET Core app to communicate with the ASP.NET app, it's necessary to make a couple small changes to each app.
3033

3134
You need to configure two configuration values in both applications:
@@ -144,6 +147,195 @@ To enable proxying from the ASP.NET Core application to the ASP.NET Framework ap
144147
app.Run();
145148
```
146149

150+
:::zone-end
151+
152+
:::zone pivot="aspire"
153+
154+
> [!NOTE]
155+
> This is still in preview and not available on NuGet.org, so you must configure your NuGet config to pull libraries from the .NET Libraries daily feed:
156+
>
157+
> ```xml
158+
> <?xml version="1.0" encoding="utf-8"?>
159+
> <configuration>
160+
> <packageSources>
161+
> <!--To inherit the global NuGet package sources remove the <clear/> line below -->
162+
> <clear />
163+
> <add key="nuget" value="https://api.nuget.org/v3/index.json" />
164+
> <add key=".NET Libraries Daily" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-libraries/nuget/v3/index.json" />
165+
> </packageSources>
166+
> </configuration>
167+
> ```
168+
169+
## Setup Aspire orchestration
170+
171+
1. Add Aspire orchestration for the ASP.NET Framework application
172+
1. Add a new ASP.NET Core application to the solution and add it to your Aspire orchestration
173+
1. Update the AppHost to target Windows as IIS integration requires that:
174+
```diff
175+
- <TargetFramework>net9.0</TargetFramework>
176+
+ <TargetFramework>net9.0-windows</TargetFramework>
177+
```
178+
1. Add the following Aspire integrations to your app host:
179+
* `Aspire.Hosting.IncrementalMigration`
180+
* `C3D.Extensions.Aspire.IISExpress`
181+
1. Configure IIS Express to locally host your framework application and configure incremental migration fallback:
182+
183+
```csharp
184+
var builder = DistributedApplication.CreateBuilder(args);
185+
186+
var frameworkApp = builder.AddIISExpress("iis")
187+
.AddSiteProject<Projects.FrameworkApplication>("framework")
188+
.WithDefaultIISExpressEndpoints()
189+
.WithOtlpExporter()
190+
.WithHttpHealthCheck(path: "/framework");
191+
192+
var coreApp = builder.AddProject<Projects.CoreApplication>("core")
193+
.WithHttpHealthCheck()
194+
.WaitFor(frameworkApp)
195+
.WithIncrementalMigrationFallback(frameworkApp, options => options.RemoteSession = RemoteSession.Enabled);
196+
197+
builder.Build().Run();
198+
```
199+
1. Configure the options of the incremental migration fallback for the scenarios you want to support.
200+
201+
## Configure ServiceDefaults to support ASP.NET Framework
202+
203+
1. Add the package `Aspire.Microsoft.AspNetCore.SystemWebAdapters` to your application.
204+
1. Update the ServiceDefaults project to support .NET Framework. This is based off of the default ServiceDefaults and may different if you have customized anything.
205+
* Update the target framework to multitarget:
206+
```diff
207+
- <TargetFramework>net9.0</TargetFramework>
208+
+ <TargetFrameworks>net9.0;net48</TargetFrameworks>
209+
```
210+
* Update the PackageReferences to account for the different frameworks:
211+
```xml
212+
<ItemGroup>
213+
<PackageReference Include="Microsoft.Extensions.Http.Resilience" />
214+
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" />
215+
<PackageReference Include="OpenTelemetry.Extensions.Hosting" />
216+
<PackageReference Include="OpenTelemetry.Instrumentation.Http" />
217+
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" />
218+
<PackageReference Include="OpenTelemetry.Instrumentation.SqlClient" />
219+
</ItemGroup>
220+
221+
<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0'">
222+
<FrameworkReference Include="Microsoft.AspNetCore.App" />
223+
224+
<PackageReference Include="Microsoft.Extensions.ServiceDiscovery" />
225+
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" />
226+
227+
<Compile Remove="Framework/**/*" />
228+
</ItemGroup>
229+
230+
<ItemGroup Condition=" '$(TargetFramework)' == 'net48' ">
231+
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" />
232+
<PackageReference Include="OpenTelemetry.Instrumentation.AspNet" />
233+
</ItemGroup>
234+
```
235+
* In the Extensions.cs file, you'll need to conditionally exclude the ServiceDiscovery APIs as those are currently not supported on .NET Framework:
236+
```diff
237+
+ #if NET
238+
builder.Services.AddServiceDiscovery();
239+
+ #endif
240+
241+
builder.Services.ConfigureHttpClientDefaults(http =>
242+
{
243+
// Turn on resilience by default
244+
http.AddStandardResilienceHandler();
245+
246+
+ #if NET
247+
// Turn on service discovery by default
248+
http.AddServiceDiscovery();
249+
+ #endif
250+
});
251+
```
252+
* To enable telemetry, update the metrics and tracing registrations:
253+
254+
```diff
255+
builder.Services.AddOpenTelemetry()
256+
.WithMetrics(metrics =>
257+
{
258+
metrics
259+
+ #if NET
260+
.AddAspNetCoreInstrumentation()
261+
+ #else
262+
+ .AddAspNetInstrumentation()
263+
+ #endif
264+
.AddSqlClientInstrumentation()
265+
.AddHttpClientInstrumentation()
266+
.AddRuntimeInstrumentation();
267+
})
268+
.WithTracing(tracing =>
269+
{
270+
tracing.AddSource(builder.Environment.ApplicationName)
271+
+ #if NET
272+
.AddAspNetCoreInstrumentation()
273+
+ #else
274+
+ .AddAspNetInstrumentation()
275+
+ #endif
276+
.AddSqlClientInstrumentation()
277+
.AddHttpClientInstrumentation();
278+
});
279+
```
280+
* Disable the default endpoints as that only applies for ASP.NET Core:
281+
282+
```diff
283+
+ #if NET
284+
public static WebApplication MapDefaultEndpoints(this WebApplication app)
285+
{
286+
// Default endpoint registrations
287+
}
288+
+ #endif
289+
```
290+
291+
## Configure ASP.NET Framework Application
292+
293+
1. Reference the ServiceDefaults project
294+
1. Add the configuration code to the `Application_Start` method in your `Global.asax.cs` file:
295+
296+
```CSharp
297+
protected void Application_Start()
298+
{
299+
HttpApplicationHost.RegisterHost(builder =>
300+
{
301+
builder.AddServiceDefaults();
302+
builder.AddSystemWebAdapters();
303+
});
304+
}
305+
```
306+
307+
## Configure ASP.NET Core Application
308+
309+
1. Reference the ServiceDefaults project
310+
1. Add the System.Web adapters in Programs.cs:
311+
312+
```diff
313+
var builder = WebApplication.CreateBuilder();
314+
315+
builder.AddServiceDefaults();
316+
+ builder.AddSystemWebAdapters();
317+
318+
...
319+
320+
var app = builder.Build();
321+
322+
...
323+
324+
+ // Must be placed after routing if manually added
325+
+ app.UseSystemWebAdapters();
326+
327+
...
328+
329+
+ app.MapRemoteAppFallback()
330+
+
331+
+ // Optional, but recommended unless middleware is needed
332+
+ .ShortCircuit();
333+
334+
app.Run();
335+
```
336+
337+
:::zone-end
338+
147339
With this configuration:
148340

149341
1. **Local routes take precedence**: If the ASP.NET Core application has a matching route, it will handle the request locally

aspnetcore/zone-pivot-groups.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,11 @@ groups:
118118
title: MSTest
119119
- id: nunit
120120
title: NUnit
121+
- id: migration-remote-app-setup
122+
title: Remote app setup
123+
prompt: Choose how to configure remote app
124+
pivots:
125+
- id: manual
126+
title: Manually
127+
- id: aspire
128+
title: Aspire

0 commit comments

Comments
 (0)