diff --git a/src/Aspire.Hosting/ApplicationModel/ExpressionResolver.cs b/src/Aspire.Hosting/ApplicationModel/ExpressionResolver.cs index 5764bdf362f..876920347d4 100644 --- a/src/Aspire.Hosting/ApplicationModel/ExpressionResolver.cs +++ b/src/Aspire.Hosting/ApplicationModel/ExpressionResolver.cs @@ -158,7 +158,9 @@ async Task ResolveConnectionStringReferenceAsync(ConnectionString // However, ConnectionStringReference#GetValueAsync will throw if the connection string is not optional but is not present. // so we need to do the same here. var value = await ResolveInternalAsync(cs.Resource.ConnectionStringExpression).ConfigureAwait(false); - if (string.IsNullOrEmpty(value.Value) && !cs.Optional) + + // While pre-processing the endpoints, we never throw + if (!Preprocess && string.IsNullOrEmpty(value.Value) && !cs.Optional) { cs.ThrowConnectionStringUnavailableException(); } diff --git a/tests/Aspire.Hosting.Tests/ExpressionResolverTests.cs b/tests/Aspire.Hosting.Tests/ExpressionResolverTests.cs index 9519e92b88f..2c7c868a732 100644 --- a/tests/Aspire.Hosting.Tests/ExpressionResolverTests.cs +++ b/tests/Aspire.Hosting.Tests/ExpressionResolverTests.cs @@ -163,6 +163,41 @@ public async Task HostUrlPropertyGetsResolvedInOtlpExporterEndpoint(bool contain var config = await EnvironmentVariableEvaluator.GetEnvironmentVariablesAsync(test.Resource, DistributedApplicationOperation.Run, TestServiceProvider.Instance, "ContainerHostName").DefaultTimeout(); Assert.Equal(expectedValue, config["OTEL_EXPORTER_OTLP_ENDPOINT"]); } + + [Fact] + public async Task ContainerToContainerEndpointShouldResolve() + { + var builder = DistributedApplication.CreateBuilder(); + + var connectionStringResource = builder.AddResource(new MyContainerResource("myContainer")) + .WithImage("redis") + .WithHttpEndpoint(targetPort: 8080) + .WithEndpoint("http", e => + { + e.AllocatedEndpoint = new AllocatedEndpoint(e, "localhost", 8001, "ContainerHostName", "{{ targetPort }}"); + }); + + var dep = builder.AddContainer("container", "redis") + .WithReference(connectionStringResource) + .WaitFor(connectionStringResource); + + var config = await EnvironmentVariableEvaluator.GetEnvironmentVariablesAsync(dep.Resource, DistributedApplicationOperation.Run, TestServiceProvider.Instance, "ContainerHostName").DefaultTimeout(); + + Assert.Equal("http://myContainer:8080", config["ConnectionStrings__myContainer"]); + } +} + +sealed class MyContainerResource : ContainerResource, IResourceWithConnectionString +{ + public MyContainerResource(string name) : base(name) + { + PrimaryEndpoint = new(this, "http"); + } + + public EndpointReference PrimaryEndpoint { get; } + + public ReferenceExpression ConnectionStringExpression => + ReferenceExpression.Create($"{PrimaryEndpoint.Property(EndpointProperty.Url)}"); } sealed class TestValueProviderResource(string name) : Resource(name), IValueProvider