diff --git a/src/CommunityToolkit.Aspire.Hosting.Dapr/DaprPolyglotOptions.cs b/src/CommunityToolkit.Aspire.Hosting.Dapr/DaprPolyglotOptions.cs
index a759a1c50..202fe8bcd 100644
--- a/src/CommunityToolkit.Aspire.Hosting.Dapr/DaprPolyglotOptions.cs
+++ b/src/CommunityToolkit.Aspire.Hosting.Dapr/DaprPolyglotOptions.cs
@@ -56,6 +56,7 @@ internal sealed record DaprSidecarExportOptions
public string? RuntimePath { get; init; }
public string? SchedulerHostAddress { get; init; }
public string? UnixDomainSocket { get; init; }
+ public string? SidecarName { get; init; }
public DaprSidecarOptions ToDaprSidecarOptions()
{
@@ -93,7 +94,8 @@ public DaprSidecarOptions ToDaprSidecarOptions()
RunFile = RunFile,
RuntimePath = RuntimePath,
SchedulerHostAddress = SchedulerHostAddress,
- UnixDomainSocket = UnixDomainSocket
+ UnixDomainSocket = UnixDomainSocket,
+ SidecarName = SidecarName
};
#pragma warning restore CS0618
}
diff --git a/src/CommunityToolkit.Aspire.Hosting.Dapr/DaprSidecarOptions.cs b/src/CommunityToolkit.Aspire.Hosting.Dapr/DaprSidecarOptions.cs
index 3ef4bca3d..95116c150 100644
--- a/src/CommunityToolkit.Aspire.Hosting.Dapr/DaprSidecarOptions.cs
+++ b/src/CommunityToolkit.Aspire.Hosting.Dapr/DaprSidecarOptions.cs
@@ -241,4 +241,12 @@ public string? DaprReadBufferSize
/// If specified, the Dapr sidecar will use Unix Domain Sockets for API calls.
///
public string? UnixDomainSocket { get; init; }
+
+ ///
+ /// Gets or sets the name of the Dapr sidecar resource as it appears in the Aspire dashboard.
+ ///
+ ///
+ /// When null or whitespace, the default name {resourceName}-dapr is used.
+ ///
+ public string? SidecarName { get; init; }
}
diff --git a/src/CommunityToolkit.Aspire.Hosting.Dapr/IDistributedApplicationComponentBuilderExtensions.cs b/src/CommunityToolkit.Aspire.Hosting.Dapr/IDistributedApplicationComponentBuilderExtensions.cs
index 423775c63..89b237e56 100644
--- a/src/CommunityToolkit.Aspire.Hosting.Dapr/IDistributedApplicationComponentBuilderExtensions.cs
+++ b/src/CommunityToolkit.Aspire.Hosting.Dapr/IDistributedApplicationComponentBuilderExtensions.cs
@@ -36,7 +36,10 @@ public static IResourceBuilder WithDaprSidecar(this IResourceBuilder bu
[AspireExportIgnore(Reason = "Use the exported DTO-based overload instead to avoid ambiguous polyglot wrapper generation.")]
public static IResourceBuilder WithDaprSidecar(this IResourceBuilder builder, DaprSidecarOptions? options = null) where T : IResource
{
- return builder.WithDaprSidecar(
+ var sidecarName = !string.IsNullOrWhiteSpace(options?.SidecarName) ? options.SidecarName : null;
+
+ return builder.WithDaprSidecarCore(
+ sidecarName,
sidecarBuilder =>
{
if (options is not null)
@@ -61,11 +64,18 @@ internal static IResourceBuilder WithDaprSidecarExport(this IResourceBuild
/// The resource builder instance.
[AspireExport("configureDaprSidecar", MethodName = "configureDaprSidecar", Description = "Adds a Dapr sidecar to the resource and exposes it for callback configuration")]
public static IResourceBuilder WithDaprSidecar(this IResourceBuilder builder, Action> configureSidecar) where T : IResource
+ {
+ return builder.WithDaprSidecarCore(null, configureSidecar);
+ }
+
+ private static IResourceBuilder WithDaprSidecarCore(this IResourceBuilder builder, string? sidecarName, Action> configureSidecar) where T : IResource
{
// Add Dapr is idempotent, so we can call it multiple times.
builder.ApplicationBuilder.AddDapr();
- var sidecarBuilder = builder.ApplicationBuilder.AddResource(new DaprSidecarResource($"{builder.Resource.Name}-dapr"))
+ var name = !string.IsNullOrWhiteSpace(sidecarName) ? sidecarName : $"{builder.Resource.Name}-dapr";
+
+ var sidecarBuilder = builder.ApplicationBuilder.AddResource(new DaprSidecarResource(name))
.WithInitialState(new()
{
Properties = [],
diff --git a/tests/CommunityToolkit.Aspire.Hosting.Dapr.Tests/WithDaprSidecarTests.cs b/tests/CommunityToolkit.Aspire.Hosting.Dapr.Tests/WithDaprSidecarTests.cs
index 5d3b39a59..a433644a4 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.Dapr.Tests/WithDaprSidecarTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.Dapr.Tests/WithDaprSidecarTests.cs
@@ -154,6 +154,63 @@ public void ResourceWithWaitAnnotationAndDaprSidecar_SetsUpCorrectDependencies()
Assert.Equal(sidecarResource, sidecarAnnotation.Sidecar);
}
+ [Fact]
+ public void SidecarNameCanBeSetViaOptions()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+
+ builder.AddProject("test")
+ .WithDaprSidecar(new DaprSidecarOptions { SidecarName = "my-custom-sidecar" });
+
+ var resource = Assert.Single(builder.Resources.OfType());
+ Assert.Equal("my-custom-sidecar", resource.Name);
+ }
+
+ [Fact]
+ public void SidecarNameDefaultsToResourceNameWhenNotSet()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+
+ builder.AddProject("test")
+ .WithDaprSidecar();
+
+ var resource = Assert.Single(builder.Resources.OfType());
+ Assert.Equal("test-dapr", resource.Name);
+ }
+
+ [Fact]
+ public void SidecarNameDefaultsToResourceNameWhenSetToWhitespace()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+
+ builder.AddProject("test")
+ .WithDaprSidecar(new DaprSidecarOptions { SidecarName = " " });
+
+ var resource = Assert.Single(builder.Resources.OfType());
+ Assert.Equal("test-dapr", resource.Name);
+ }
+
+ [Fact]
+ public void SidecarNameCanBeSetWithAppId()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+
+ builder.AddProject("my-service")
+ .WithDaprSidecar(new DaprSidecarOptions
+ {
+ SidecarName = "my-custom-sidecar",
+ AppId = "my-service"
+ });
+
+ var resource = Assert.Single(builder.Resources.OfType());
+ Assert.Equal("my-custom-sidecar", resource.Name);
+
+ var annotation = Assert.Single(resource.Annotations.OfType());
+ Assert.Equal("my-service", annotation.Options.AppId);
+ Assert.Equal("my-custom-sidecar", annotation.Options.SidecarName);
+ }
+
+
[Fact]
public void ResourceWithMultipleWaitAnnotationsAndDaprSidecar_HasAllWaitDependencies()
{