diff --git a/src/Components/Aspire.Azure.Messaging.EventHubs/EventHubsComponent.cs b/src/Components/Aspire.Azure.Messaging.EventHubs/EventHubsComponent.cs
index 30cee2f2f8..3e33e1f1ed 100644
--- a/src/Components/Aspire.Azure.Messaging.EventHubs/EventHubsComponent.cs
+++ b/src/Components/Aspire.Azure.Messaging.EventHubs/EventHubsComponent.cs
@@ -1,7 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using System.Security.Cryptography;
using Aspire.Azure.Common;
using Aspire.Azure.Messaging.EventHubs;
using Azure.Core;
@@ -56,15 +55,15 @@ protected static string GetNamespaceFromSettings(AzureMessagingEventHubsSettings
: new Uri(settings.FullyQualifiedNamespace).Host;
// This is likely to be similar to {yournamespace}.servicebus.windows.net or {yournamespace}.servicebus.chinacloudapi.cn
- if (ns.Contains(".servicebus", StringComparison.OrdinalIgnoreCase))
+ var serviceBusIndex = ns.IndexOf(".servicebus", StringComparison.OrdinalIgnoreCase);
+ if (serviceBusIndex != -1)
{
- ns = ns[..ns.IndexOf(".servicebus")];
+ ns = ns[..serviceBusIndex];
}
else
{
- // Use a random prefix if no meaningful name is found e.g., "localhost", "127.0.0.1".
- // This is used to create blob containers names that are unique in the referenced storage account.
- RandomNumberGenerator.GetHexString(12, true);
+ // sanitize the namespace if it's not a servicebus namespace
+ ns = ns.Replace(".", "-");
}
}
catch (Exception ex) when (ex is FormatException or IndexOutOfRangeException)
diff --git a/src/Components/Aspire.Azure.Messaging.EventHubs/EventProcessorClientComponent.cs b/src/Components/Aspire.Azure.Messaging.EventHubs/EventProcessorClientComponent.cs
index 6700975ff8..3384ecc3ad 100644
--- a/src/Components/Aspire.Azure.Messaging.EventHubs/EventProcessorClientComponent.cs
+++ b/src/Components/Aspire.Azure.Messaging.EventHubs/EventProcessorClientComponent.cs
@@ -97,17 +97,14 @@ private static BlobContainerClient GetBlobContainerClient(
// name specified in the settings.
bool shouldTryCreateIfNotExists = false;
+ // Do we have a container name provided in the settings?
if (string.IsNullOrWhiteSpace(settings.BlobContainerName))
{
+ // If not, we'll create a container name based on the namespace, event hub name and consumer group
var ns = GetNamespaceFromSettings(settings);
- // Do we have a container name provided in the settings?
- if (string.IsNullOrWhiteSpace(settings.BlobContainerName))
- {
- // If not, we'll create a container name based on the namespace, event hub name and consumer group
- settings.BlobContainerName = $"{ns}-{settings.EventHubName}-{consumerGroup}";
- shouldTryCreateIfNotExists = true;
- }
+ settings.BlobContainerName = $"{ns}-{settings.EventHubName}-{consumerGroup}";
+ shouldTryCreateIfNotExists = true;
}
var containerClient = blobClient.GetBlobContainerClient(settings.BlobContainerName);
diff --git a/tests/Aspire.Azure.Messaging.EventHubs.Tests/Aspire.Azure.Messaging.EventHubs.Tests.csproj b/tests/Aspire.Azure.Messaging.EventHubs.Tests/Aspire.Azure.Messaging.EventHubs.Tests.csproj
index ace3db5c39..28bf694c86 100644
--- a/tests/Aspire.Azure.Messaging.EventHubs.Tests/Aspire.Azure.Messaging.EventHubs.Tests.csproj
+++ b/tests/Aspire.Azure.Messaging.EventHubs.Tests/Aspire.Azure.Messaging.EventHubs.Tests.csproj
@@ -11,6 +11,8 @@
+
+
diff --git a/tests/Aspire.Azure.Messaging.EventHubs.Tests/AspireEventHubsExtensionsTests.cs b/tests/Aspire.Azure.Messaging.EventHubs.Tests/AspireEventHubsExtensionsTests.cs
index fda1d43424..08272a039b 100644
--- a/tests/Aspire.Azure.Messaging.EventHubs.Tests/AspireEventHubsExtensionsTests.cs
+++ b/tests/Aspire.Azure.Messaging.EventHubs.Tests/AspireEventHubsExtensionsTests.cs
@@ -1,6 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Text;
+using Azure.Core;
using Azure.Identity;
using Azure.Messaging.EventHubs;
using Azure.Messaging.EventHubs.Consumer;
@@ -476,7 +478,7 @@ private static void AssertFullyQualifiedNamespace(string expectedNamespace, obje
EventHubConsumerClient consumer => consumer.FullyQualifiedNamespace,
EventProcessorClient processor => processor.FullyQualifiedNamespace,
PartitionReceiver receiver => receiver.FullyQualifiedNamespace,
- EventHubBufferedProducerClient producer => producer.FullyQualifiedNamespace,
+ EventHubBufferedProducerClient producer => producer.FullyQualifiedNamespace,
_ => throw new InvalidOperationException()
});
}
@@ -580,4 +582,48 @@ public void CanAddMultipleKeyedServices(int clientIndex)
public static string CreateConfigKey(string prefix, string? key, string suffix)
=> string.IsNullOrEmpty(key) ? $"{prefix}:{suffix}" : $"{prefix}:{key}:{suffix}";
+
+ ///
+ /// Tests that the BlobContainerName defaults correctly when the connection string doesn't contain ".servicebus" and
+ /// contains invalid container name characters.
+ ///
+ [Fact]
+ public void ProcessorBlobContainerNameDefaultsCorrectly()
+ {
+ var builder = Host.CreateEmptyApplicationBuilder(null);
+ builder.Configuration.AddInMemoryCollection([
+ new KeyValuePair("ConnectionStrings:eh1", "Endpoint=sb://127.0.0.1:53589;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"),
+ new KeyValuePair("Aspire:Azure:Messaging:EventHubs:EventProcessorClient:EventHubName", "MyHub"),
+ ]);
+
+ var mockTransport = new MockTransport(
+ CreateResponse("""{}"""));
+ var blobClient = new BlobServiceClient(new Uri(BlobsConnectionString), new BlobClientOptions() { Transport = mockTransport });
+ builder.Services.AddSingleton(blobClient);
+
+ builder.AddAzureEventProcessorClient("eh1");
+
+ using var host = builder.Build();
+
+ var client = host.Services.GetRequiredService();
+ Assert.NotNull(client);
+
+ Assert.Single(mockTransport.Requests);
+ // the container name should be based on the Endpoint, EventHubName, and ConsumerGroup
+ Assert.Equal("https://fake.blob.core.windows.net/127-0-0-1-MyHub-default?restype=container", mockTransport.Requests[0].Uri.ToString());
+ }
+
+ private static MockResponse CreateResponse(string content)
+ {
+ var buffer = Encoding.UTF8.GetBytes(content);
+ var response = new MockResponse(201)
+ {
+ ClientRequestId = Guid.NewGuid().ToString(),
+ ContentStream = new MemoryStream(buffer),
+ };
+
+ response.AddHeader(new HttpHeader("Content-Type", "application/json; charset=utf-8"));
+
+ return response;
+ }
}