Skip to content

Commit b3cc78f

Browse files
davidfowlCopilot
andauthored
Added overload of AddConnectionString using the builder pattern to make it more approachable (#8251)
* Enhance connection string resource handling with a builder pattern and improve documentation * Update src/Aspire.Hosting/ConnectionStringBuilderExtensions.cs Co-authored-by: Copilot <[email protected]> * Add overload for AppendFormatted method to support IResourceBuilder and update tests for consistency * Update src/Aspire.Hosting/ConnectionStringBuilderExtensions.cs --------- Co-authored-by: Copilot <[email protected]>
1 parent e5014c7 commit b3cc78f

File tree

3 files changed

+74
-8
lines changed

3 files changed

+74
-8
lines changed

src/Aspire.Hosting/ApplicationModel/ReferenceExpression.cs

+11
Original file line numberDiff line numberDiff line change
@@ -251,5 +251,16 @@ public void AppendFormatted<T>(T valueProvider) where T : IValueProvider, IManif
251251
{
252252
builder.AppendFormatted(valueProvider);
253253
}
254+
255+
/// <summary>
256+
/// Appends a formatted value to the expression. The value must implement <see cref="IValueProvider"/> and <see cref="IManifestExpressionProvider"/>.
257+
/// </summary>
258+
/// <param name="valueProvider">An instance of an object which implements <see cref="IValueProvider"/> and <see cref="IManifestExpressionProvider"/>.</param>
259+
/// <exception cref="InvalidOperationException"></exception>
260+
public void AppendFormatted<T>(IResourceBuilder<T> valueProvider)
261+
where T : IResource, IValueProvider, IManifestExpressionProvider
262+
{
263+
builder.AppendFormatted(valueProvider.Resource);
264+
}
254265
}
255266
}

src/Aspire.Hosting/ConnectionStringBuilderExtensions.cs

+36-6
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,13 @@ public static class ConnectionStringBuilderExtensions
2323
/// <code language="csharp">
2424
/// var builder = DistributedApplication.CreateBuilder(args);
2525
///
26-
/// var postgres = builder
27-
/// .AddPostgres("postgres")
26+
/// var apiKey = builder.AddParameter("apiKey", secret: true);
2827
///
29-
/// var database = postgres.AddDatabase("database");
30-
///
31-
/// var cs = builder.AddConnectionString("cs", $"{database};Include Error Details=true");
28+
/// var cs = builder.AddConnectionString("cs", ReferenceExpression.Create($"Endpoint=http://something;Key={apiKey}"));
3229
///
3330
/// var backend = builder
3431
/// .AddProject&lt;Projects.Backend&gt;("backend")
35-
/// .WithReference(cs) // cs is the connection string name, not database
32+
/// .WithReference(cs)
3633
/// .WaitFor(database);
3734
///
3835
/// builder.Build().Run();
@@ -50,4 +47,37 @@ public static IResourceBuilder<ConnectionStringResource> AddConnectionString(thi
5047
Properties = []
5148
});
5249
}
50+
51+
/// <summary>
52+
/// Adds a connection string resource to the distributed application with the specified expression.
53+
/// </summary>
54+
/// <remarks>
55+
/// This method also enables appending custom data to the connection string based on other resources that expose connection strings.
56+
/// </remarks>
57+
/// <param name="builder">Distributed application builder</param>
58+
/// <param name="name">The name of the resource.</param>
59+
/// <param name="connectionStringBuilder">The callback to configure the connection string expression.</param>
60+
/// <returns>An <see cref="IResourceBuilder{ConnectionStringResource}"/> instance.</returns>
61+
/// <example>
62+
/// <code language="csharp">
63+
/// var builder = DistributedApplication.CreateBuilder(args);
64+
///
65+
/// var apiKey = builder.AddParameter("apiKey", secret: true);
66+
///
67+
/// var cs = builder.AddConnectionString("cs", b => b.Append($"Endpoint=http://something;Key={apiKey}"));
68+
///
69+
/// var backend = builder
70+
/// .AddProject&lt;Projects.Backend&gt;("backend")
71+
/// .WithReference(cs)
72+
/// .WaitFor(database);
73+
///
74+
/// builder.Build().Run();
75+
/// </code>
76+
/// </example>
77+
public static IResourceBuilder<ConnectionStringResource> AddConnectionString(this IDistributedApplicationBuilder builder, [ResourceName] string name, Action<ReferenceExpressionBuilder> connectionStringBuilder)
78+
{
79+
var rb = new ReferenceExpressionBuilder();
80+
connectionStringBuilder(rb);
81+
return builder.AddConnectionString(name, rb.Build());
82+
}
5383
}

tests/Aspire.Hosting.Tests/WithReferenceTests.cs

+27-2
Original file line numberDiff line numberDiff line change
@@ -247,15 +247,15 @@ public async Task ConnectionStringResourceWithConnectionString()
247247
}
248248

249249
[Fact]
250-
public async Task ConnectionStringResourceWithExpressiononnectionString()
250+
public async Task ConnectionStringResourceWithExpressionConnectionString()
251251
{
252252
using var builder = TestDistributedApplicationBuilder.Create();
253253

254254
var endpoint = builder.AddParameter("endpoint", "http://localhost:3452");
255255
var key = builder.AddParameter("key", "secretKey", secret: true);
256256

257257
var cs = ReferenceExpression.Create($"Endpoint={endpoint};Key={key}");
258-
258+
259259
// Get the service provider.
260260
var resource = builder.AddConnectionString("cs", cs);
261261

@@ -270,6 +270,31 @@ public async Task ConnectionStringResourceWithExpressiononnectionString()
270270
Assert.Equal("Endpoint=http://localhost:3452;Key=secretKey", config["ConnectionStrings__cs"]);
271271
}
272272

273+
[Fact]
274+
public async Task ConnectionStringResourceWithExpressionConnectionStringBuilder()
275+
{
276+
using var builder = TestDistributedApplicationBuilder.Create();
277+
278+
var endpoint = builder.AddParameter("endpoint", "http://localhost:3452");
279+
var key = builder.AddParameter("key", "secretKey", secret: true);
280+
281+
// Get the service provider.
282+
var resource = builder.AddConnectionString("cs", b =>
283+
{
284+
b.Append($"Endpoint={endpoint};Key={key}");
285+
});
286+
287+
var projectB = builder.AddProject<ProjectB>("projectb")
288+
.WithReference(resource);
289+
290+
// Call environment variable callbacks.
291+
var config = await EnvironmentVariableEvaluator.GetEnvironmentVariablesAsync(projectB.Resource, DistributedApplicationOperation.Run, TestServiceProvider.Instance).DefaultTimeout();
292+
293+
var servicesKeysCount = config.Keys.Count(k => k.StartsWith("ConnectionStrings__"));
294+
Assert.Equal(1, servicesKeysCount);
295+
Assert.Equal("Endpoint=http://localhost:3452;Key=secretKey", config["ConnectionStrings__cs"]);
296+
}
297+
273298
[Fact]
274299
public async Task ConnectionStringResourceWithConnectionStringOverwriteName()
275300
{

0 commit comments

Comments
 (0)