microsoft / microsoft/aspire

Service discovery endpoint env vars won't override appsettings.json

Open
#5,096 3 comments 1 reaction 0 assignees View on GitHub
area-service-discovery
Dominant language
C#
Stars
6.3k
Forks
991
Avg merge
2d 12h
Merged PRs (30d)
201

Description

### Is there an existing issue for this?

- [X] I have searched the existing issues

### Describe the bug

I'm trying to enable a setup where I can run my frontend and my backend API in my box, which live in different repos, without Aspire orchestration if needed. For this I'm using the standard configuration based service discovery mechanism enabled in .NET via `Microsoft.Extensions.ServiceDiscovery`.

However I noticed that once I enable service discovery via appsettings.json, and later run frontend and backend with Aspire orchestration, the Aspire orchestrator will not override appsettings.json configuration with environment variables, but instead will honor appsettings.json, which is unexpected.

### Expected Behavior

Endpoint environment variables used in service discovery set by Aspire orchestration should always be prioritized over appsettings.json settings defined by any of the orchestrated projects.

### Steps To Reproduce

1. Enable a frontend project to discover the backend service url via a configuration like this:

```json
"Services": {
"catalog-service": {
"https": [
"http://localhost:5274"
]
}
}
```

2. Configure the frontend's HttpClient like this:

```csharp
builder.Services.AddHttpClient(
client => client.BaseAddress = new Uri("https+http://catalog-service"))
```

3. Also ensure the frontend is enabling service discovery via the standard ServiceDefaults mechanism like this:

```csharp
builder.AddServiceDefaults();
```

4. Run backend and frontend independently, without Aspire's orchestration, and confirm frontend can discover backend's endpoint without issues.

5. Next enable standard Aspire service discovery in AppHost Program.cs file like this:

```csharp
var catalogService = builder.AddProject("catalog-service");

builder.AddProject("gamestore-frontend")
.WithReference(catalogService)
```

7. Run AppHost, browse to frontend and confirm frontend can still discover backend's endpoint without issues.

8. Now update appsetting.json in Frontend to an invalid backend discovery address:

```json
"Services": {
"catalog-service": {
"https": [
"http://WRONG-HOST:9999"
]
}
}
```

9. Run AppHost and browse to frontend.

10. Frontend throws exception complaining it can't find the backend host:

warn: Polly[3]
Execution attempt. Source: '-standard//Standard-Retry', Operation Key: '', Result: 'No such host is known. (wrong-host:9999)', Handled: 'True', Attempt: '0', Execution Time: '2711.9191'
System.Net.Http.HttpRequestException: No such host is known. (wrong-host:9999)
---> System.Net.Sockets.SocketException (11001): No such host is known.
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)

On top of that the frontend's env var clearly points to the correct backend host, but somehow it is not used:

![image](https://github.com/user-attachments/assets/703dc579-3722-4dc9-88c0-09e3d5549290)

### Exceptions (if any)

warn: Polly[3]
Execution attempt. Source: '-standard//Standard-Retry', Operation Key: '', Result: 'No such host is known. (wrong-host:9999)', Handled: 'True', Attempt: '0', Execution Time: '2711.9191'
System.Net.Http.HttpRequestException: No such host is known. (wrong-host:9999)
---> System.Net.Sockets.SocketException (11001): No such host is known.
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)
at System.Net.Sockets.Socket.g__WaitForConnectWithCancellation|285_0(AwaitableSocketAsyncEventArgs saea, ValueTask connectTask, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.AddHttp11ConnectionAsync(QueueItem queueItem)
at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellationAsync(CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.HttpConnectionWaiter`1.WaitForConnectionWithTelemetryAsync(HttpRequestMessage request, HttpConnectionPool pool, Boolean async, CancellationToken requestCancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.Metrics.MetricsHandler.SendAsyncWithMetrics(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler.g__Core|5_0(HttpRequestMessage request, Boolean useAsync, CancellationToken cancellationToken)
at GameStore.Frontend.Authorization.AuthorizationHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) in D:\projects\GameStore\frontend\src\GameStore.Frontend\Authorization\AuthorizationHandler.cs:line 20
at Microsoft.Extensions.ServiceDiscovery.Http.ResolvingHttpDelegatingHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) in /_/src/Microsoft.Extensions.ServiceDiscovery/Http/ResolvingHttpDelegatingHandler.cs:line 53

### .NET Version info

.NET SDK:
Version: 8.0.303
Commit: 29ab8e3268
Workload version: 8.0.300-manifests.d7126b9e
MSBuild version: 17.10.4+10fbfbf2e

Runtime Environment:
OS Name: Windows
OS Version: 10.0.22631
OS Platform: Windows
RID: win-x64
Base Path: C:\Program Files\dotnet\sdk\8.0.303\

.NET workloads installed:
[aspire]
Installation Source: SDK 8.0.300
Manifest Version: 8.1.0/8.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.sdk.aspire\8.1.0\WorkloadManifest.json
Install Type: Msi

Host:
Version: 8.0.7
Architecture: x64
Commit: 2aade6beb0

.NET SDKs installed:
8.0.107 [C:\Program Files\dotnet\sdk]
8.0.200 [C:\Program Files\dotnet\sdk]
8.0.206 [C:\Program Files\dotnet\sdk]
8.0.303 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
Microsoft.AspNetCore.App 8.0.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 8.0.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 8.0.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 8.0.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 8.0.2 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 8.0.6 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 8.0.7 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Other architectures found:
x86 [C:\Program Files (x86)\dotnet]
registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]

Environment variables:
Not set

global.json file:
Not found

Learn more:
https://aka.ms/dotnet/info

Download .NET:
https://aka.ms/dotnet/download

### Anything else?

Versions: .NET 8 and .NET Aspire 8.1
IDE: VS Code

Contributor guide

Open the contributing guide

Research direction

Start with the service discovery configuration in appsettings.json and the AppHost Program.cs entry point, then trace Microsoft.Extensions.ServiceDiscovery.Http.ResolvingHttpDelegatingHandler.cs. Compare the environment endpoint shown in the report with the configured endpoint, and add or update coverage so orchestration-provided endpoints take precedence over appsettings.json.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
networking
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.