diff --git a/src/Aspire.Hosting.AWS/AWSProvisioningException.cs b/src/Aspire.Hosting.AWS/AWSProvisioningException.cs
index 8f97208ff9..877839f35a 100644
--- a/src/Aspire.Hosting.AWS/AWSProvisioningException.cs
+++ b/src/Aspire.Hosting.AWS/AWSProvisioningException.cs
@@ -1,6 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+
namespace Aspire.Hosting.AWS;
///
@@ -8,6 +11,14 @@ namespace Aspire.Hosting.AWS;
///
///
///
-public class AWSProvisioningException(string message, Exception? innerException = null) : Exception(message, innerException)
+public class AWSProvisioningException(string message, Exception? innerException = null)
+ : Exception(ThrowIfNullOrEmpty(message), innerException)
{
+ private static string ThrowIfNullOrEmpty(
+ [NotNull] string? argument,
+ [CallerArgumentExpression(nameof(argument))] string? paramName = null)
+ {
+ ArgumentException.ThrowIfNullOrEmpty(argument, paramName);
+ return argument;
+ }
}
diff --git a/src/Aspire.Hosting.AWS/SDKResourceExtensions.cs b/src/Aspire.Hosting.AWS/SDKResourceExtensions.cs
index ed45335020..be30246c58 100644
--- a/src/Aspire.Hosting.AWS/SDKResourceExtensions.cs
+++ b/src/Aspire.Hosting.AWS/SDKResourceExtensions.cs
@@ -19,6 +19,8 @@ public static class SDKResourceExtensions
///
public static IAWSSDKConfig AddAWSSDKConfig(this IDistributedApplicationBuilder builder)
{
+ ArgumentNullException.ThrowIfNull(builder);
+
var config = new AWSSDKConfig();
return config;
@@ -32,6 +34,9 @@ public static IAWSSDKConfig AddAWSSDKConfig(this IDistributedApplicationBuilder
///
public static IAWSSDKConfig WithProfile(this IAWSSDKConfig config, string profile)
{
+ ArgumentNullException.ThrowIfNull(config);
+ ArgumentException.ThrowIfNullOrEmpty(profile);
+
config.Profile = profile;
return config;
}
@@ -43,6 +48,9 @@ public static IAWSSDKConfig WithProfile(this IAWSSDKConfig config, string profil
/// The AWS region.
public static IAWSSDKConfig WithRegion(this IAWSSDKConfig config, RegionEndpoint region)
{
+ ArgumentNullException.ThrowIfNull(config);
+ ArgumentNullException.ThrowIfNull(region);
+
config.Region = region;
return config;
}
@@ -56,6 +64,9 @@ public static IAWSSDKConfig WithRegion(this IAWSSDKConfig config, RegionEndpoint
public static IResourceBuilder WithReference(this IResourceBuilder builder, IAWSSDKConfig awsSdkConfig)
where TDestination : IResourceWithEnvironment
{
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentNullException.ThrowIfNull(awsSdkConfig);
+
builder.WithEnvironment(context =>
{
if (context.ExecutionContext.IsPublishMode)
diff --git a/src/Aspire.Hosting.Dapr/DaprComponentResource.cs b/src/Aspire.Hosting.Dapr/DaprComponentResource.cs
index 6a74e8df74..da2077ba69 100644
--- a/src/Aspire.Hosting.Dapr/DaprComponentResource.cs
+++ b/src/Aspire.Hosting.Dapr/DaprComponentResource.cs
@@ -1,28 +1,29 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
using Aspire.Hosting.ApplicationModel;
namespace Aspire.Hosting.Dapr;
///
-/// Represents a Dapr component resource.
+/// Initializes a new instance of .
///
-public sealed class DaprComponentResource : Resource, IDaprComponentResource
+/// The resource name.
+/// The Dapr component type. This may be a generic "state" or "pubsub" if Aspire should choose an appropriate type when running or deploying.
+public sealed class DaprComponentResource(string name, string type) : Resource(ThrowIfNullOrEmpty(name)), IDaprComponentResource
{
- ///
- /// Initializes a new instance of .
- ///
- /// The resource name.
- /// The Dapr component type. This may be a generic "state" or "pubsub" if Aspire should choose an appropriate type when running or deploying.
- public DaprComponentResource(string name, string type) : base(name)
- {
- this.Type = type;
- }
-
///
- public string Type { get; }
+ public string Type { get; } = ThrowIfNullOrEmpty(type);
///
public DaprComponentOptions? Options { get; init; }
+
+ private static string ThrowIfNullOrEmpty([NotNull] string? argument,
+ [CallerArgumentExpression(nameof(argument))] string? paramName = null)
+ {
+ ArgumentException.ThrowIfNullOrEmpty(argument, paramName);
+ return argument;
+ }
}
diff --git a/src/Aspire.Hosting.Dapr/IDistributedApplicationBuilderExtensions.cs b/src/Aspire.Hosting.Dapr/IDistributedApplicationBuilderExtensions.cs
index 889173b146..93e9ed179e 100644
--- a/src/Aspire.Hosting.Dapr/IDistributedApplicationBuilderExtensions.cs
+++ b/src/Aspire.Hosting.Dapr/IDistributedApplicationBuilderExtensions.cs
@@ -23,6 +23,8 @@ public static class IDistributedApplicationBuilderExtensions
/// The distributed application builder instance.
public static IDistributedApplicationBuilder AddDapr(this IDistributedApplicationBuilder builder, Action? configure = null)
{
+ ArgumentNullException.ThrowIfNull(builder);
+
if (configure is not null)
{
builder.Services.Configure(configure);
@@ -42,6 +44,8 @@ public static IDistributedApplicationBuilder AddDapr(this IDistributedApplicatio
/// A reference to the .
public static IResourceBuilder AddDaprComponent(this IDistributedApplicationBuilder builder, string name, string type, DaprComponentOptions? options = null)
{
+ ArgumentNullException.ThrowIfNull(builder);
+
var resource = new DaprComponentResource(name, type) { Options = options };
return builder
diff --git a/src/Aspire.Hosting.Dapr/IDistributedApplicationComponentBuilderExtensions.cs b/src/Aspire.Hosting.Dapr/IDistributedApplicationComponentBuilderExtensions.cs
index dd1c03daed..c6b60511d7 100644
--- a/src/Aspire.Hosting.Dapr/IDistributedApplicationComponentBuilderExtensions.cs
+++ b/src/Aspire.Hosting.Dapr/IDistributedApplicationComponentBuilderExtensions.cs
@@ -20,6 +20,9 @@ public static class IDistributedApplicationResourceBuilderExtensions
/// The resource builder instance.
public static IResourceBuilder WithDaprSidecar(this IResourceBuilder builder, string appId) where T : IResource
{
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(appId);
+
return builder.WithDaprSidecar(new DaprSidecarOptions { AppId = appId });
}
@@ -32,6 +35,8 @@ public static IResourceBuilder WithDaprSidecar(this IResourceBuilder bu
/// The resource builder instance.
public static IResourceBuilder WithDaprSidecar(this IResourceBuilder builder, DaprSidecarOptions? options = null) where T : IResource
{
+ ArgumentNullException.ThrowIfNull(builder);
+
return builder.WithDaprSidecar(
sidecarBuilder =>
{
@@ -51,6 +56,9 @@ public static IResourceBuilder WithDaprSidecar(this IResourceBuilder bu
/// The resource builder instance.
public static IResourceBuilder WithDaprSidecar(this IResourceBuilder builder, Action> configureSidecar) where T : IResource
{
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentNullException.ThrowIfNull(configureSidecar);
+
// Add Dapr is idempotent, so we can call it multiple times.
builder.ApplicationBuilder.AddDapr();
@@ -75,6 +83,9 @@ public static IResourceBuilder WithDaprSidecar(this IResourceBuilder bu
/// The Dapr sidecar resource builder instance.
public static IResourceBuilder WithOptions(this IResourceBuilder builder, DaprSidecarOptions options)
{
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentNullException.ThrowIfNull(options);
+
return builder.WithAnnotation(new DaprSidecarOptionsAnnotation(options));
}
@@ -86,6 +97,9 @@ public static IResourceBuilder WithOptions(this IResourceB
/// The Dapr component to use with the sidecar.
public static IResourceBuilder WithReference(this IResourceBuilder builder, IResourceBuilder component) where TDestination : IResource
{
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentNullException.ThrowIfNull(component);
+
return builder.WithAnnotation(new DaprComponentReferenceAnnotation(component.Resource));
}
}
diff --git a/src/Aspire.Hosting.Garnet/GarnetBuilderExtensions.cs b/src/Aspire.Hosting.Garnet/GarnetBuilderExtensions.cs
index fd26b9b5dc..a8e6efb103 100644
--- a/src/Aspire.Hosting.Garnet/GarnetBuilderExtensions.cs
+++ b/src/Aspire.Hosting.Garnet/GarnetBuilderExtensions.cs
@@ -116,7 +116,7 @@ public static IResourceBuilder WithDataBindMount(this IResourceB
string source, bool isReadOnly = false)
{
ArgumentNullException.ThrowIfNull(builder);
- ArgumentNullException.ThrowIfNull(source);
+ ArgumentException.ThrowIfNullOrEmpty(source);
builder.WithBindMount(source, GarnetContainerDataDirectory, isReadOnly);
if (!isReadOnly)
diff --git a/src/Aspire.Hosting.Kafka/KafkaBuilderExtensions.cs b/src/Aspire.Hosting.Kafka/KafkaBuilderExtensions.cs
index 19fe7f78a5..b799ff1293 100644
--- a/src/Aspire.Hosting.Kafka/KafkaBuilderExtensions.cs
+++ b/src/Aspire.Hosting.Kafka/KafkaBuilderExtensions.cs
@@ -143,7 +143,7 @@ public static IResourceBuilder WithDataVolume(this IResourc
public static IResourceBuilder WithDataBindMount(this IResourceBuilder builder, string source, bool isReadOnly = false)
{
ArgumentNullException.ThrowIfNull(builder);
- ArgumentNullException.ThrowIfNull(source);
+ ArgumentException.ThrowIfNullOrEmpty(source);
return builder.WithBindMount(source, "/var/lib/kafka/data", isReadOnly);
}
diff --git a/src/Aspire.Hosting.Keycloak/KeycloakResourceBuilderExtensions.cs b/src/Aspire.Hosting.Keycloak/KeycloakResourceBuilderExtensions.cs
index 241b6f913f..f98342f7e3 100644
--- a/src/Aspire.Hosting.Keycloak/KeycloakResourceBuilderExtensions.cs
+++ b/src/Aspire.Hosting.Keycloak/KeycloakResourceBuilderExtensions.cs
@@ -122,7 +122,7 @@ public static IResourceBuilder WithDataVolume(this IResourceBu
public static IResourceBuilder WithDataBindMount(this IResourceBuilder builder, string source)
{
ArgumentNullException.ThrowIfNull(builder);
- ArgumentNullException.ThrowIfNull(source);
+ ArgumentException.ThrowIfNullOrEmpty(source);
return builder.WithBindMount(source, "/opt/keycloak/data", false);
}
@@ -150,7 +150,7 @@ public static IResourceBuilder WithRealmImport(
bool isReadOnly = false)
{
ArgumentNullException.ThrowIfNull(builder);
- ArgumentNullException.ThrowIfNull(importDirectory);
+ ArgumentException.ThrowIfNullOrEmpty(importDirectory);
var importDirectoryFullPath = Path.GetFullPath(importDirectory, builder.ApplicationBuilder.AppHostDirectory);
if (!Directory.Exists(importDirectoryFullPath))
diff --git a/src/Aspire.Hosting.Milvus/MilvusBuilderExtensions.cs b/src/Aspire.Hosting.Milvus/MilvusBuilderExtensions.cs
index a7de4edec5..84a19ef978 100644
--- a/src/Aspire.Hosting.Milvus/MilvusBuilderExtensions.cs
+++ b/src/Aspire.Hosting.Milvus/MilvusBuilderExtensions.cs
@@ -167,7 +167,7 @@ public static IResourceBuilder WithDataVolume(this IResour
public static IResourceBuilder WithDataBindMount(this IResourceBuilder builder, string source, bool isReadOnly = false)
{
ArgumentNullException.ThrowIfNull(builder);
- ArgumentNullException.ThrowIfNull(source);
+ ArgumentException.ThrowIfNullOrEmpty(source);
return builder.WithBindMount(source, "/var/lib/milvus", isReadOnly);
}
@@ -180,7 +180,7 @@ public static IResourceBuilder WithDataBindMount(this IRes
public static IResourceBuilder WithConfigurationBindMount(this IResourceBuilder builder, string configurationFilePath)
{
ArgumentNullException.ThrowIfNull(builder);
- ArgumentNullException.ThrowIfNull(configurationFilePath);
+ ArgumentException.ThrowIfNullOrEmpty(configurationFilePath);
return builder.WithBindMount(configurationFilePath, "/milvus/configs/milvus.yaml");
}
diff --git a/src/Aspire.Hosting.MongoDB/MongoDBBuilderExtensions.cs b/src/Aspire.Hosting.MongoDB/MongoDBBuilderExtensions.cs
index c86f2b4d3f..ad7430aa72 100644
--- a/src/Aspire.Hosting.MongoDB/MongoDBBuilderExtensions.cs
+++ b/src/Aspire.Hosting.MongoDB/MongoDBBuilderExtensions.cs
@@ -124,7 +124,7 @@ public static IResourceBuilder WithDataVolume(this IResou
public static IResourceBuilder WithDataBindMount(this IResourceBuilder builder, string source, bool isReadOnly = false)
{
ArgumentNullException.ThrowIfNull(builder);
- ArgumentNullException.ThrowIfNull(source);
+ ArgumentException.ThrowIfNullOrEmpty(source);
return builder.WithBindMount(source, "/data/db", isReadOnly);
}
@@ -139,7 +139,7 @@ public static IResourceBuilder WithDataBindMount(this IRe
public static IResourceBuilder WithInitBindMount(this IResourceBuilder builder, string source, bool isReadOnly = true)
{
ArgumentNullException.ThrowIfNull(builder);
- ArgumentNullException.ThrowIfNull(source);
+ ArgumentException.ThrowIfNullOrEmpty(source);
return builder.WithBindMount(source, "/docker-entrypoint-initdb.d", isReadOnly);
}
diff --git a/src/Aspire.Hosting.MongoDB/MongoDBDatabaseResource.cs b/src/Aspire.Hosting.MongoDB/MongoDBDatabaseResource.cs
index b41572913f..8c6242ac45 100644
--- a/src/Aspire.Hosting.MongoDB/MongoDBDatabaseResource.cs
+++ b/src/Aspire.Hosting.MongoDB/MongoDBDatabaseResource.cs
@@ -1,6 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+
namespace Aspire.Hosting.ApplicationModel;
///
@@ -14,9 +17,9 @@ public class MongoDBDatabaseResource : Resource, IResourceWithParentThe name of the resource.
/// The database name.
/// The MongoDB server resource associated with this database.
- public MongoDBDatabaseResource(string name, string databaseName, MongoDBServerResource parent) : base(name)
+ public MongoDBDatabaseResource(string name, string databaseName, MongoDBServerResource parent) : base(ThrowIfNullOrEmpty(name))
{
- ArgumentNullException.ThrowIfNull(databaseName);
+ ThrowIfNullOrEmpty(databaseName);
ArgumentNullException.ThrowIfNull(parent);
Parent = parent;
@@ -38,4 +41,12 @@ public ReferenceExpression ConnectionStringExpression
/// Gets the database name.
///
public string DatabaseName { get; }
+
+ private static string ThrowIfNullOrEmpty(
+ [NotNull] string? argument,
+ [CallerArgumentExpression(nameof(argument))] string? paramName = null)
+ {
+ ArgumentException.ThrowIfNullOrEmpty(argument, paramName);
+ return argument;
+ }
}
diff --git a/src/Aspire.Hosting.MySql/MySqlBuilderExtensions.cs b/src/Aspire.Hosting.MySql/MySqlBuilderExtensions.cs
index ccbe01b0e4..ba8efa4d4e 100644
--- a/src/Aspire.Hosting.MySql/MySqlBuilderExtensions.cs
+++ b/src/Aspire.Hosting.MySql/MySqlBuilderExtensions.cs
@@ -192,7 +192,7 @@ public static IResourceBuilder WithDataVolume(this IResourc
public static IResourceBuilder WithDataBindMount(this IResourceBuilder builder, string source, bool isReadOnly = false)
{
ArgumentNullException.ThrowIfNull(builder);
- ArgumentNullException.ThrowIfNull(source);
+ ArgumentException.ThrowIfNullOrEmpty(source);
return builder.WithBindMount(source, "/var/lib/mysql", isReadOnly);
}
@@ -207,7 +207,7 @@ public static IResourceBuilder WithDataBindMount(this IReso
public static IResourceBuilder WithInitBindMount(this IResourceBuilder builder, string source, bool isReadOnly = true)
{
ArgumentNullException.ThrowIfNull(builder);
- ArgumentNullException.ThrowIfNull(source);
+ ArgumentException.ThrowIfNullOrEmpty(source);
return builder.WithBindMount(source, "/docker-entrypoint-initdb.d", isReadOnly);
}
diff --git a/src/Aspire.Hosting.NodeJs/NodeAppResource.cs b/src/Aspire.Hosting.NodeJs/NodeAppResource.cs
index 381d54a620..7c57cc03e2 100644
--- a/src/Aspire.Hosting.NodeJs/NodeAppResource.cs
+++ b/src/Aspire.Hosting.NodeJs/NodeAppResource.cs
@@ -15,6 +15,10 @@ namespace Aspire.Hosting;
public class NodeAppResource(string name, string command, string workingDirectory)
: ExecutableResource(ThrowIfNull(name), ThrowIfNull(command), ThrowIfNull(workingDirectory)), IResourceWithServiceDiscovery
{
- private static string ThrowIfNull([NotNull] string? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null)
- => argument ?? throw new ArgumentNullException(paramName);
+ private static string ThrowIfNull([NotNull] string? argument,
+ [CallerArgumentExpression(nameof(argument))] string? paramName = null)
+ {
+ ArgumentException.ThrowIfNullOrEmpty(argument, paramName);
+ return argument;
+ }
}
diff --git a/src/Aspire.Hosting.NodeJs/NodeExtensions.cs b/src/Aspire.Hosting.NodeJs/NodeExtensions.cs
index dcae1462ca..7e43569946 100644
--- a/src/Aspire.Hosting.NodeJs/NodeExtensions.cs
+++ b/src/Aspire.Hosting.NodeJs/NodeExtensions.cs
@@ -23,8 +23,8 @@ public static class NodeAppHostingExtension
public static IResourceBuilder AddNodeApp(this IDistributedApplicationBuilder builder, string name, string scriptPath, string? workingDirectory = null, string[]? args = null)
{
ArgumentNullException.ThrowIfNull(builder);
- ArgumentNullException.ThrowIfNull(name);
- ArgumentNullException.ThrowIfNull(scriptPath);
+ ArgumentException.ThrowIfNullOrEmpty(name);
+ ArgumentException.ThrowIfNullOrEmpty(scriptPath);
args ??= [];
string[] effectiveArgs = [scriptPath, .. args];
@@ -51,9 +51,9 @@ public static IResourceBuilder AddNpmApp(this IDistributedAppli
{
ArgumentNullException.ThrowIfNull(builder);
- ArgumentNullException.ThrowIfNull(name);
- ArgumentNullException.ThrowIfNull(workingDirectory);
- ArgumentNullException.ThrowIfNull(scriptName);
+ ArgumentException.ThrowIfNullOrEmpty(name);
+ ArgumentException.ThrowIfNullOrEmpty(workingDirectory);
+ ArgumentException.ThrowIfNullOrEmpty(scriptName);
string[] allArgs = args is { Length: > 0 }
? ["run", scriptName, "--", .. args]
diff --git a/src/Aspire.Hosting.PostgreSQL/PostgresBuilderExtensions.cs b/src/Aspire.Hosting.PostgreSQL/PostgresBuilderExtensions.cs
index 62585ec72b..742ffc5da1 100644
--- a/src/Aspire.Hosting.PostgreSQL/PostgresBuilderExtensions.cs
+++ b/src/Aspire.Hosting.PostgreSQL/PostgresBuilderExtensions.cs
@@ -120,7 +120,7 @@ public static IResourceBuilder AddPostgres(this IDistrib
public static IResourceBuilder AddDatabase(this IResourceBuilder builder, string name, string? databaseName = null)
{
ArgumentNullException.ThrowIfNull(builder);
- ArgumentNullException.ThrowIfNull(name);
+ ArgumentException.ThrowIfNullOrEmpty(name);
// Use the resource name as the database name if it's not provided
databaseName ??= name;
@@ -378,7 +378,7 @@ public static IResourceBuilder WithDataVolume(this IReso
public static IResourceBuilder WithDataBindMount(this IResourceBuilder builder, string source, bool isReadOnly = false)
{
ArgumentNullException.ThrowIfNull(builder);
- ArgumentNullException.ThrowIfNull(source);
+ ArgumentException.ThrowIfNullOrEmpty(source);
return builder.WithBindMount(source, "/var/lib/postgresql/data", isReadOnly);
}
@@ -393,7 +393,7 @@ public static IResourceBuilder WithDataBindMount(this IR
public static IResourceBuilder WithInitBindMount(this IResourceBuilder builder, string source, bool isReadOnly = true)
{
ArgumentNullException.ThrowIfNull(builder);
- ArgumentNullException.ThrowIfNull(source);
+ ArgumentException.ThrowIfNullOrEmpty(source);
return builder.WithBindMount(source, "/docker-entrypoint-initdb.d", isReadOnly);
}
diff --git a/src/Aspire.Hosting.PostgreSQL/PostgresDatabaseResource.cs b/src/Aspire.Hosting.PostgreSQL/PostgresDatabaseResource.cs
index 967e8378e2..74c7a0c59a 100644
--- a/src/Aspire.Hosting.PostgreSQL/PostgresDatabaseResource.cs
+++ b/src/Aspire.Hosting.PostgreSQL/PostgresDatabaseResource.cs
@@ -12,12 +12,12 @@ namespace Aspire.Hosting.ApplicationModel;
/// The name of the resource.
/// The database name.
/// The PostgreSQL parent resource associated with this database.
-public class PostgresDatabaseResource(string name, string databaseName, PostgresServerResource postgresParentResource) : Resource(ThrowIfNull(name)), IResourceWithParent, IResourceWithConnectionString
+public class PostgresDatabaseResource(string name, string databaseName, PostgresServerResource postgresParentResource) : Resource(ThrowIfNullOrEmpty(name)), IResourceWithParent, IResourceWithConnectionString
{
///
/// Gets the parent PostgresSQL container resource.
///
- public PostgresServerResource Parent { get; } = ThrowIfNull(postgresParentResource);
+ public PostgresServerResource Parent { get; } = ThrowIfNullOrEmpty(postgresParentResource);
///
/// Gets the connection string expression for the Postgres database.
@@ -28,8 +28,19 @@ public class PostgresDatabaseResource(string name, string databaseName, Postgres
///
/// Gets the database name.
///
- public string DatabaseName { get; } = ThrowIfNull(databaseName);
+ public string DatabaseName { get; } = ThrowIfNullOrEmpty(databaseName);
- private static T ThrowIfNull([NotNull] T? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null)
- => argument ?? throw new ArgumentNullException(paramName);
+ private static T ThrowIfNullOrEmpty([NotNull] T? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null)
+ {
+ if (argument is string line)
+ {
+ ArgumentException.ThrowIfNullOrEmpty(line, paramName);
+ }
+ else
+ {
+ ArgumentNullException.ThrowIfNull(argument, paramName);
+ }
+
+ return argument;
+ }
}
diff --git a/src/Aspire.Hosting.Qdrant/QdrantBuilderExtensions.cs b/src/Aspire.Hosting.Qdrant/QdrantBuilderExtensions.cs
index 74174ca588..97e0020948 100644
--- a/src/Aspire.Hosting.Qdrant/QdrantBuilderExtensions.cs
+++ b/src/Aspire.Hosting.Qdrant/QdrantBuilderExtensions.cs
@@ -89,7 +89,7 @@ public static IResourceBuilder WithDataVolume(this IResour
public static IResourceBuilder WithDataBindMount(this IResourceBuilder builder, string source, bool isReadOnly = false)
{
ArgumentNullException.ThrowIfNull(builder);
- ArgumentNullException.ThrowIfNull(source);
+ ArgumentException.ThrowIfNullOrEmpty(source);
return builder.WithBindMount(source, "/qdrant/storage", isReadOnly);
}
diff --git a/src/Aspire.Hosting.RabbitMQ/RabbitMQBuilderExtensions.cs b/src/Aspire.Hosting.RabbitMQ/RabbitMQBuilderExtensions.cs
index 0f44460932..5971a136d0 100644
--- a/src/Aspire.Hosting.RabbitMQ/RabbitMQBuilderExtensions.cs
+++ b/src/Aspire.Hosting.RabbitMQ/RabbitMQBuilderExtensions.cs
@@ -75,7 +75,7 @@ public static IResourceBuilder WithDataVolume(this IReso
public static IResourceBuilder WithDataBindMount(this IResourceBuilder builder, string source, bool isReadOnly = false)
{
ArgumentNullException.ThrowIfNull(builder);
- ArgumentNullException.ThrowIfNull(source);
+ ArgumentException.ThrowIfNullOrEmpty(source);
return builder.WithBindMount(source, "/var/lib/rabbitmq", isReadOnly)
.RunWithStableNodeName();
diff --git a/src/Aspire.Hosting.Redis/RedisBuilderExtensions.cs b/src/Aspire.Hosting.Redis/RedisBuilderExtensions.cs
index 6c2ff6c27a..36d05104e4 100644
--- a/src/Aspire.Hosting.Redis/RedisBuilderExtensions.cs
+++ b/src/Aspire.Hosting.Redis/RedisBuilderExtensions.cs
@@ -185,7 +185,7 @@ public static IResourceBuilder WithDataVolume(this IResourceBuild
public static IResourceBuilder WithDataBindMount(this IResourceBuilder builder, string source, bool isReadOnly = false)
{
ArgumentNullException.ThrowIfNull(builder);
- ArgumentNullException.ThrowIfNull(source);
+ ArgumentException.ThrowIfNullOrEmpty(source);
builder.WithBindMount(source, "/data", isReadOnly);
if (!isReadOnly)
diff --git a/src/Components/Aspire.Azure.AI.OpenAI/AspireAzureOpenAIExtensions.cs b/src/Components/Aspire.Azure.AI.OpenAI/AspireAzureOpenAIExtensions.cs
index 78b7941be0..4a1756fd88 100644
--- a/src/Components/Aspire.Azure.AI.OpenAI/AspireAzureOpenAIExtensions.cs
+++ b/src/Components/Aspire.Azure.AI.OpenAI/AspireAzureOpenAIExtensions.cs
@@ -40,6 +40,9 @@ public static void AddAzureOpenAIClient(
Action? configureSettings = null,
Action>? configureClientBuilder = null)
{
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(connectionName);
+
new OpenAIComponent().AddClient(builder, DefaultConfigSectionName, configureSettings, configureClientBuilder, connectionName, serviceKey: null);
// Add the AzureOpenAIClient service as OpenAIClient. That way the service can be resolved by both service Types.
@@ -62,6 +65,7 @@ public static void AddKeyedAzureOpenAIClient(
Action? configureSettings = null,
Action>? configureClientBuilder = null)
{
+ ArgumentNullException.ThrowIfNull(builder);
ArgumentException.ThrowIfNullOrEmpty(name);
var configurationSectionName = OpenAIComponent.GetKeyedConfigurationSectionName(name, DefaultConfigSectionName);
diff --git a/src/Components/Aspire.Azure.Data.Tables/AspireTablesExtensions.cs b/src/Components/Aspire.Azure.Data.Tables/AspireTablesExtensions.cs
index 464f499903..3cde9c9b74 100644
--- a/src/Components/Aspire.Azure.Data.Tables/AspireTablesExtensions.cs
+++ b/src/Components/Aspire.Azure.Data.Tables/AspireTablesExtensions.cs
@@ -37,6 +37,9 @@ public static void AddAzureTableClient(
Action? configureSettings = null,
Action>? configureClientBuilder = null)
{
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(connectionName);
+
new TableServiceComponent().AddClient(builder, DefaultConfigSectionName, configureSettings, configureClientBuilder, connectionName, serviceKey: null);
}
@@ -56,6 +59,7 @@ public static void AddKeyedAzureTableClient(
Action? configureSettings = null,
Action>? configureClientBuilder = null)
{
+ ArgumentNullException.ThrowIfNull(builder);
ArgumentException.ThrowIfNullOrEmpty(name);
string configurationSectionName = TableServiceComponent.GetKeyedConfigurationSectionName(name, DefaultConfigSectionName);
diff --git a/src/Components/Aspire.Azure.Search.Documents/AspireAzureSearchExtensions.cs b/src/Components/Aspire.Azure.Search.Documents/AspireAzureSearchExtensions.cs
index 4c4aabb609..4aa9e2077c 100644
--- a/src/Components/Aspire.Azure.Search.Documents/AspireAzureSearchExtensions.cs
+++ b/src/Components/Aspire.Azure.Search.Documents/AspireAzureSearchExtensions.cs
@@ -37,6 +37,9 @@ public static void AddAzureSearchClient(
Action? configureSettings = null,
Action>? configureClientBuilder = null)
{
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(connectionName);
+
new AzureSearchComponent().AddClient(builder, DefaultConfigSectionName, configureSettings, configureClientBuilder, connectionName, serviceKey: null);
}
@@ -54,6 +57,7 @@ public static void AddKeyedAzureSearchClient(
Action? configureSettings = null,
Action>? configureClientBuilder = null)
{
+ ArgumentNullException.ThrowIfNull(builder);
ArgumentException.ThrowIfNullOrEmpty(name);
var configurationSectionName = AzureSearchComponent.GetKeyedConfigurationSectionName(name, DefaultConfigSectionName);
diff --git a/src/Components/Aspire.Azure.Security.KeyVault/AspireKeyVaultExtensions.cs b/src/Components/Aspire.Azure.Security.KeyVault/AspireKeyVaultExtensions.cs
index 322e884598..5d1b0d5d1f 100644
--- a/src/Components/Aspire.Azure.Security.KeyVault/AspireKeyVaultExtensions.cs
+++ b/src/Components/Aspire.Azure.Security.KeyVault/AspireKeyVaultExtensions.cs
@@ -39,6 +39,9 @@ public static void AddAzureKeyVaultClient(
Action? configureSettings = null,
Action>? configureClientBuilder = null)
{
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(connectionName);
+
new KeyVaultComponent().AddClient(builder, DefaultConfigSectionName, configureSettings, configureClientBuilder, connectionName, serviceKey: null);
}
@@ -58,6 +61,7 @@ public static void AddKeyedAzureKeyVaultClient(
Action? configureSettings = null,
Action>? configureClientBuilder = null)
{
+ ArgumentNullException.ThrowIfNull(builder);
ArgumentException.ThrowIfNullOrEmpty(name);
string configurationSectionName = KeyVaultComponent.GetKeyedConfigurationSectionName(name, DefaultConfigSectionName);
diff --git a/src/Components/Aspire.Azure.Storage.Queues/AspireQueueStorageExtensions.cs b/src/Components/Aspire.Azure.Storage.Queues/AspireQueueStorageExtensions.cs
index ffb815ab2a..427990d527 100644
--- a/src/Components/Aspire.Azure.Storage.Queues/AspireQueueStorageExtensions.cs
+++ b/src/Components/Aspire.Azure.Storage.Queues/AspireQueueStorageExtensions.cs
@@ -38,6 +38,9 @@ public static void AddAzureQueueClient(
Action? configureSettings = null,
Action>? configureClientBuilder = null)
{
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(connectionName);
+
new StorageQueueComponent().AddClient(builder, DefaultConfigSectionName, configureSettings, configureClientBuilder, connectionName, serviceKey: null);
}
@@ -57,6 +60,7 @@ public static void AddKeyedAzureQueueClient(
Action? configureSettings = null,
Action>? configureClientBuilder = null)
{
+ ArgumentNullException.ThrowIfNull(builder);
ArgumentException.ThrowIfNullOrEmpty(name);
string configurationSectionName = StorageQueueComponent.GetKeyedConfigurationSectionName(name, DefaultConfigSectionName);
diff --git a/src/Components/Aspire.Confluent.Kafka/AspireKafkaConsumerExtensions.cs b/src/Components/Aspire.Confluent.Kafka/AspireKafkaConsumerExtensions.cs
index 3a760ebb96..d2431b8139 100644
--- a/src/Components/Aspire.Confluent.Kafka/AspireKafkaConsumerExtensions.cs
+++ b/src/Components/Aspire.Confluent.Kafka/AspireKafkaConsumerExtensions.cs
@@ -109,6 +109,8 @@ private static void AddKafkaConsumerInternal(
string? serviceKey)
{
ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(configurationSectionName);
+ ArgumentException.ThrowIfNullOrEmpty(connectionName);
var settings = BuildConsumerSettings(builder, configurationSectionName, configureSettings, connectionName);
diff --git a/src/Components/Aspire.Confluent.Kafka/AspireKafkaProducerExtensions.cs b/src/Components/Aspire.Confluent.Kafka/AspireKafkaProducerExtensions.cs
index 06e696f5f5..d42d40cb56 100644
--- a/src/Components/Aspire.Confluent.Kafka/AspireKafkaProducerExtensions.cs
+++ b/src/Components/Aspire.Confluent.Kafka/AspireKafkaProducerExtensions.cs
@@ -109,6 +109,8 @@ private static void AddKafkaProducerInternal(
string? serviceKey)
{
ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(configurationSectionName);
+ ArgumentException.ThrowIfNullOrEmpty(connectionName);
var settings = BuildProducerSettings(builder, configurationSectionName, configureSettings, connectionName);
diff --git a/src/Components/Aspire.Elastic.Clients.Elasticsearch/AspireElasticClientsElasticsearchExtensions.cs b/src/Components/Aspire.Elastic.Clients.Elasticsearch/AspireElasticClientsElasticsearchExtensions.cs
index 4b85d66ea9..3bcd6fac52 100644
--- a/src/Components/Aspire.Elastic.Clients.Elasticsearch/AspireElasticClientsElasticsearchExtensions.cs
+++ b/src/Components/Aspire.Elastic.Clients.Elasticsearch/AspireElasticClientsElasticsearchExtensions.cs
@@ -30,14 +30,8 @@ public static void AddElasticsearchClient(
this IHostApplicationBuilder builder,
string connectionName,
Action? configureSettings = null,
- Action? configureClientSettings = null
- )
- {
- ArgumentNullException.ThrowIfNull(builder);
- ArgumentException.ThrowIfNullOrEmpty(connectionName);
-
- builder.AddElasticsearchClient(DefaultConfigSectionName, configureSettings, configureClientSettings, connectionName, serviceKey: null);
- }
+ Action? configureClientSettings = null)
+ => AddElasticsearchClient(builder, DefaultConfigSectionName, configureSettings, configureClientSettings, connectionName, serviceKey: null);
///
/// Registers instance for connecting to Elasticsearch with Elastic.Clients.Elasticsearch client.
@@ -53,10 +47,10 @@ public static void AddKeyedElasticsearchClient(
Action? configureSettings = null,
Action? configureClientSettings = null)
{
- ArgumentNullException.ThrowIfNull(builder);
ArgumentException.ThrowIfNullOrEmpty(name);
- builder.AddElasticsearchClient(
+ AddElasticsearchClient(
+ builder,
$"{DefaultConfigSectionName}:{name}",
configureSettings,
configureClientSettings,
@@ -65,7 +59,7 @@ public static void AddKeyedElasticsearchClient(
}
private static void AddElasticsearchClient(
- this IHostApplicationBuilder builder,
+ IHostApplicationBuilder builder,
string configurationSectionName,
Action? configureSettings,
Action? configureClientSettings,
@@ -73,6 +67,7 @@ private static void AddElasticsearchClient(
object? serviceKey)
{
ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(connectionName);
var configSection = builder.Configuration.GetSection(configurationSectionName);
diff --git a/src/Components/Aspire.Keycloak.Authentication/AspireKeycloakExtensions.cs b/src/Components/Aspire.Keycloak.Authentication/AspireKeycloakExtensions.cs
index 36b27e170a..3a6182e7b4 100644
--- a/src/Components/Aspire.Keycloak.Authentication/AspireKeycloakExtensions.cs
+++ b/src/Components/Aspire.Keycloak.Authentication/AspireKeycloakExtensions.cs
@@ -27,7 +27,7 @@ public static class AspireKeycloakExtensions
/// For example, if is "keycloak" and is "myrealm", the authority URL will be "https+http://keycloak/realms/myrealm".
///
public static AuthenticationBuilder AddKeycloakJwtBearer(this AuthenticationBuilder builder, string serviceName, string realm)
- => builder.AddKeycloakJwtBearer(serviceName, realm, JwtBearerDefaults.AuthenticationScheme, null);
+ => AddKeycloakJwtBearerInternal(builder, serviceName, realm, JwtBearerDefaults.AuthenticationScheme, null);
///
/// Adds Keycloak JWT Bearer authentication to the application.
@@ -41,7 +41,7 @@ public static AuthenticationBuilder AddKeycloakJwtBearer(this AuthenticationBuil
/// For example, if is "keycloak" and is "myrealm", the authority URL will be "https+http://keycloak/realms/myrealm".
///
public static AuthenticationBuilder AddKeycloakJwtBearer(this AuthenticationBuilder builder, string serviceName, string realm, string authenticationScheme)
- => builder.AddKeycloakJwtBearer(serviceName, realm, authenticationScheme, null);
+ => AddKeycloakJwtBearerInternal(builder, serviceName, realm, authenticationScheme, null);
///
/// Adds Keycloak JWT Bearer authentication to the application.
@@ -55,7 +55,7 @@ public static AuthenticationBuilder AddKeycloakJwtBearer(this AuthenticationBuil
/// For example, if is "keycloak" and is "myrealm", the authority URL will be "https+http://keycloak/realms/myrealm".
///
public static AuthenticationBuilder AddKeycloakJwtBearer(this AuthenticationBuilder builder, string serviceName, string realm, Action? configureOptions)
- => builder.AddKeycloakJwtBearer(serviceName, realm, JwtBearerDefaults.AuthenticationScheme, configureOptions);
+ => AddKeycloakJwtBearerInternal(builder, serviceName, realm, JwtBearerDefaults.AuthenticationScheme, configureOptions);
///
/// Adds Keycloak JWT Bearer authentication to the application.
@@ -75,22 +75,33 @@ public static AuthenticationBuilder AddKeycloakJwtBearer(
string realm,
string authenticationScheme,
Action? configureOptions)
+ => AddKeycloakJwtBearerInternal(builder, serviceName, realm, authenticationScheme, configureOptions);
+
+ private static AuthenticationBuilder AddKeycloakJwtBearerInternal(
+ AuthenticationBuilder builder,
+ string serviceName,
+ string realm,
+ string authenticationScheme,
+ Action? configureOptions)
{
ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(serviceName);
+ ArgumentException.ThrowIfNullOrEmpty(realm);
+ ArgumentException.ThrowIfNullOrEmpty(authenticationScheme);
builder.AddJwtBearer(authenticationScheme);
builder.Services.AddHttpClient(KeycloakBackchannel);
builder.Services
- .AddOptions(authenticationScheme)
- .Configure((options, configuration, httpClientFactory, hostEnvironment) =>
- {
- options.Backchannel = httpClientFactory.CreateClient(KeycloakBackchannel);
- options.Authority = GetAuthorityUri(serviceName, realm);
+ .AddOptions(authenticationScheme)
+ .Configure((options, configuration, httpClientFactory, hostEnvironment) =>
+ {
+ options.Backchannel = httpClientFactory.CreateClient(KeycloakBackchannel);
+ options.Authority = GetAuthorityUri(serviceName, realm);
- configureOptions?.Invoke(options);
- });
+ configureOptions?.Invoke(options);
+ });
return builder;
}
@@ -106,7 +117,7 @@ public static AuthenticationBuilder AddKeycloakJwtBearer(
/// For example, if is "keycloak" and is "myrealm", the authority URL will be "https+http://keycloak/realms/myrealm".
///
public static AuthenticationBuilder AddKeycloakOpenIdConnect(this AuthenticationBuilder builder, string serviceName, string realm)
- => builder.AddKeycloakOpenIdConnect(serviceName, realm, OpenIdConnectDefaults.AuthenticationScheme, null);
+ => AddKeycloakOpenIdConnectInternal(builder, serviceName, realm, OpenIdConnectDefaults.AuthenticationScheme, null);
///
/// Adds Keycloak OpenID Connect authentication to the application.
@@ -120,7 +131,7 @@ public static AuthenticationBuilder AddKeycloakOpenIdConnect(this Authentication
/// For example, if is "keycloak" and is "myrealm", the authority URL will be "https+http://keycloak/realms/myrealm".
///
public static AuthenticationBuilder AddKeycloakOpenIdConnect(this AuthenticationBuilder builder, string serviceName, string realm, string authenticationScheme)
- => builder.AddKeycloakOpenIdConnect(serviceName, realm, authenticationScheme, null);
+ => AddKeycloakOpenIdConnectInternal(builder, serviceName, realm, authenticationScheme, null);
///
/// Adds Keycloak OpenID Connect authentication to the application.
@@ -134,7 +145,7 @@ public static AuthenticationBuilder AddKeycloakOpenIdConnect(this Authentication
/// For example, if is "keycloak" and is "myrealm", the authority URL will be "https+http://keycloak/realms/myrealm".
///
public static AuthenticationBuilder AddKeycloakOpenIdConnect(this AuthenticationBuilder builder, string serviceName, string realm, Action? configureOptions)
- => builder.AddKeycloakOpenIdConnect(serviceName, realm, OpenIdConnectDefaults.AuthenticationScheme, configureOptions);
+ => AddKeycloakOpenIdConnectInternal(builder, serviceName, realm, OpenIdConnectDefaults.AuthenticationScheme, configureOptions);
///
/// Adds Keycloak OpenID Connect authentication to the application.
@@ -154,22 +165,34 @@ public static AuthenticationBuilder AddKeycloakOpenIdConnect(
string realm,
string authenticationScheme,
Action? configureOptions)
+ => AddKeycloakOpenIdConnectInternal(builder, serviceName, realm, authenticationScheme, configureOptions);
+
+ private static AuthenticationBuilder AddKeycloakOpenIdConnectInternal(
+ AuthenticationBuilder builder,
+ string serviceName,
+ string realm,
+ string authenticationScheme,
+ Action? configureOptions
+ )
{
ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(serviceName);
+ ArgumentException.ThrowIfNullOrEmpty(realm);
+ ArgumentException.ThrowIfNullOrEmpty(authenticationScheme);
builder.AddOpenIdConnect(authenticationScheme, options => { });
builder.Services.AddHttpClient(KeycloakBackchannel);
builder.Services
- .AddOptions(authenticationScheme)
- .Configure((options, configuration, httpClientFactory, hostEnvironment) =>
- {
- options.Backchannel = httpClientFactory.CreateClient(KeycloakBackchannel);
- options.Authority = GetAuthorityUri(serviceName, realm);
-
- configureOptions?.Invoke(options);
- });
+ .AddOptions(authenticationScheme)
+ .Configure((options, configuration, httpClientFactory, hostEnvironment) =>
+ {
+ options.Backchannel = httpClientFactory.CreateClient(KeycloakBackchannel);
+ options.Authority = GetAuthorityUri(serviceName, realm);
+
+ configureOptions?.Invoke(options);
+ });
return builder;
}
diff --git a/src/Components/Aspire.Microsoft.Azure.Cosmos/AspireMicrosoftAzureCosmosExtensions.cs b/src/Components/Aspire.Microsoft.Azure.Cosmos/AspireMicrosoftAzureCosmosExtensions.cs
index 529352b7a2..a522deef7c 100644
--- a/src/Components/Aspire.Microsoft.Azure.Cosmos/AspireMicrosoftAzureCosmosExtensions.cs
+++ b/src/Components/Aspire.Microsoft.Azure.Cosmos/AspireMicrosoftAzureCosmosExtensions.cs
@@ -32,9 +32,7 @@ public static void AddAzureCosmosClient(
string connectionName,
Action? configureSettings = null,
Action? configureClientOptions = null)
- {
- AddAzureCosmosClient(builder, DefaultConfigSectionName, configureSettings, configureClientOptions, connectionName, serviceKey: null);
- }
+ => AddAzureCosmosClient(builder, DefaultConfigSectionName, configureSettings, configureClientOptions, connectionName, serviceKey: null);
///
/// Registers as a singleton for given in the services provided by the .
@@ -52,6 +50,8 @@ public static void AddKeyedAzureCosmosClient(
Action? configureSettings = null,
Action? configureClientOptions = null)
{
+ ArgumentException.ThrowIfNullOrEmpty(name);
+
AddAzureCosmosClient(builder, $"{DefaultConfigSectionName}:{name}", configureSettings, configureClientOptions, connectionName: name, serviceKey: name);
}
@@ -64,6 +64,7 @@ private static void AddAzureCosmosClient(
string? serviceKey)
{
ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(connectionName);
var settings = new MicrosoftAzureCosmosSettings();
builder.Configuration.GetSection(configurationSectionName).Bind(settings);
diff --git a/src/Components/Aspire.Milvus.Client/AspireMilvusExtensions.cs b/src/Components/Aspire.Milvus.Client/AspireMilvusExtensions.cs
index a632ba7af9..ab2505799e 100644
--- a/src/Components/Aspire.Milvus.Client/AspireMilvusExtensions.cs
+++ b/src/Components/Aspire.Milvus.Client/AspireMilvusExtensions.cs
@@ -32,9 +32,6 @@ public static void AddMilvusClient(
string connectionName,
Action? configureSettings = null)
{
- ArgumentNullException.ThrowIfNull(builder);
- ArgumentException.ThrowIfNullOrEmpty(connectionName);
-
AddMilvus(builder, DefaultConfigSectionName, configureSettings, connectionName, serviceKey: null);
}
@@ -52,8 +49,8 @@ public static void AddKeyedMilvusClient(
string name,
Action? configureSettings = null)
{
- ArgumentNullException.ThrowIfNull(builder);
ArgumentException.ThrowIfNullOrEmpty(name);
+
AddMilvus(builder, $"{DefaultConfigSectionName}:{name}", configureSettings, connectionName: name, serviceKey: name);
}
@@ -65,6 +62,7 @@ private static void AddMilvus(
string? serviceKey)
{
ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(connectionName);
var settings = new MilvusClientSettings();
builder.Configuration.GetSection(configurationSectionName).Bind(settings);
diff --git a/src/Components/Aspire.MongoDB.Driver/AspireMongoDBDriverExtensions.cs b/src/Components/Aspire.MongoDB.Driver/AspireMongoDBDriverExtensions.cs
index b3d54cbbc6..5407a51d90 100644
--- a/src/Components/Aspire.MongoDB.Driver/AspireMongoDBDriverExtensions.cs
+++ b/src/Components/Aspire.MongoDB.Driver/AspireMongoDBDriverExtensions.cs
@@ -34,12 +34,7 @@ public static void AddMongoDBClient(
string connectionName,
Action? configureSettings = null,
Action? configureClientSettings = null)
- {
- ArgumentNullException.ThrowIfNull(builder);
- ArgumentException.ThrowIfNullOrEmpty(connectionName);
-
- builder.AddMongoDBClient(DefaultConfigSectionName, configureSettings, configureClientSettings, connectionName, serviceKey: null);
- }
+ => AddMongoDBClient(builder, DefaultConfigSectionName, configureSettings, configureClientSettings, connectionName, serviceKey: null);
///
/// Registers and instances for connecting MongoDB database with MongoDB.Driver client.
@@ -57,10 +52,10 @@ public static void AddKeyedMongoDBClient(
Action? configureSettings = null,
Action? configureClientSettings = null)
{
- ArgumentNullException.ThrowIfNull(builder);
ArgumentException.ThrowIfNullOrEmpty(name);
- builder.AddMongoDBClient(
+ AddMongoDBClient(
+ builder,
$"{DefaultConfigSectionName}:{name}",
configureSettings,
configureClientSettings,
@@ -69,7 +64,7 @@ public static void AddKeyedMongoDBClient(
}
private static void AddMongoDBClient(
- this IHostApplicationBuilder builder,
+ IHostApplicationBuilder builder,
string configurationSectionName,
Action? configureSettings,
Action? configureClientSettings,
@@ -77,6 +72,7 @@ private static void AddMongoDBClient(
object? serviceKey)
{
ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(connectionName);
var settings = builder.GetMongoDBSettings(
connectionName,
diff --git a/src/Components/Aspire.NATS.Net/AspireNatsClientExtensions.cs b/src/Components/Aspire.NATS.Net/AspireNatsClientExtensions.cs
index e890f044cf..f9f7f184ee 100644
--- a/src/Components/Aspire.NATS.Net/AspireNatsClientExtensions.cs
+++ b/src/Components/Aspire.NATS.Net/AspireNatsClientExtensions.cs
@@ -32,12 +32,7 @@ public static class AspireNatsClientExtensions
/// Thrown if mandatory is null.
/// Thrown when mandatory is not provided.
public static void AddNatsClient(this IHostApplicationBuilder builder, string connectionName, Action? configureSettings = null, Func? configureOptions = null)
- {
- ArgumentNullException.ThrowIfNull(builder);
- ArgumentException.ThrowIfNullOrEmpty(connectionName);
-
- AddNatsClient(builder, configurationSectionName: DefaultConfigSectionName, connectionName: connectionName, serviceKey: null, configureSettings: configureSettings, configureOptions: configureOptions);
- }
+ => AddNatsClient(builder, configurationSectionName: DefaultConfigSectionName, connectionName: connectionName, serviceKey: null, configureSettings: configureSettings, configureOptions: configureOptions);
///
/// Registers as a keyed service for given for connecting NATS server with NATS client.
@@ -52,7 +47,6 @@ public static void AddNatsClient(this IHostApplicationBuilder builder, string co
/// Thrown when mandatory is not provided.
public static void AddKeyedNatsClient(this IHostApplicationBuilder builder, string name, Action? configureSettings = null, Func? configureOptions = null)
{
- ArgumentNullException.ThrowIfNull(builder);
ArgumentException.ThrowIfNullOrEmpty(name);
AddNatsClient(builder, configurationSectionName: $"{DefaultConfigSectionName}:{name}", connectionName: name, serviceKey: name, configureSettings: configureSettings, configureOptions: configureOptions);
@@ -61,6 +55,7 @@ public static void AddKeyedNatsClient(this IHostApplicationBuilder builder, stri
private static void AddNatsClient(this IHostApplicationBuilder builder, string configurationSectionName, string connectionName, object? serviceKey, Action? configureSettings, Func? configureOptions)
{
ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(connectionName);
NatsClientSettings settings = new();
builder.Configuration.GetSection(configurationSectionName).Bind(settings);
diff --git a/src/Components/Common/AzureComponent.cs b/src/Components/Common/AzureComponent.cs
index 8fbe400a59..53afd9bdcd 100644
--- a/src/Components/Common/AzureComponent.cs
+++ b/src/Components/Common/AzureComponent.cs
@@ -48,8 +48,6 @@ internal void AddClient(
string connectionName,
string? serviceKey)
{
- ArgumentNullException.ThrowIfNull(builder);
-
var configSection = builder.Configuration.GetSection(configurationSectionName);
var settings = new TSettings();
diff --git a/src/Microsoft.Extensions.ServiceDiscovery.Abstractions/ServiceEndpoint.cs b/src/Microsoft.Extensions.ServiceDiscovery.Abstractions/ServiceEndpoint.cs
index 238e383a95..33e0eff4d6 100644
--- a/src/Microsoft.Extensions.ServiceDiscovery.Abstractions/ServiceEndpoint.cs
+++ b/src/Microsoft.Extensions.ServiceDiscovery.Abstractions/ServiceEndpoint.cs
@@ -28,5 +28,10 @@ public abstract class ServiceEndpoint
/// The endpoint being represented.
/// Features of the endpoint.
/// A newly initialized .
- public static ServiceEndpoint Create(EndPoint endPoint, IFeatureCollection? features = null) => new ServiceEndpointImpl(endPoint, features);
+ public static ServiceEndpoint Create(EndPoint endPoint, IFeatureCollection? features = null)
+ {
+ ArgumentNullException.ThrowIfNull(endPoint);
+
+ return new ServiceEndpointImpl(endPoint, features);
+ }
}
diff --git a/src/Microsoft.Extensions.ServiceDiscovery.Abstractions/ServiceEndpointQuery.cs b/src/Microsoft.Extensions.ServiceDiscovery.Abstractions/ServiceEndpointQuery.cs
index 600dc5cc28..20a17d0878 100644
--- a/src/Microsoft.Extensions.ServiceDiscovery.Abstractions/ServiceEndpointQuery.cs
+++ b/src/Microsoft.Extensions.ServiceDiscovery.Abstractions/ServiceEndpointQuery.cs
@@ -35,6 +35,8 @@ private ServiceEndpointQuery(string originalString, string[] includedSchemes, st
/// if the value was successfully parsed; otherwise .
public static bool TryParse(string input, [NotNullWhen(true)] out ServiceEndpointQuery? query)
{
+ ArgumentException.ThrowIfNullOrEmpty(input);
+
bool hasScheme;
if (!input.Contains("://", StringComparison.InvariantCulture)
&& Uri.TryCreate($"fakescheme://{input}", default, out var uri))
diff --git a/src/Microsoft.Extensions.ServiceDiscovery.Abstractions/ServiceEndpointSource.cs b/src/Microsoft.Extensions.ServiceDiscovery.Abstractions/ServiceEndpointSource.cs
index fb5bff1b28..28d987a2f3 100644
--- a/src/Microsoft.Extensions.ServiceDiscovery.Abstractions/ServiceEndpointSource.cs
+++ b/src/Microsoft.Extensions.ServiceDiscovery.Abstractions/ServiceEndpointSource.cs
@@ -25,6 +25,7 @@ public sealed class ServiceEndpointSource
public ServiceEndpointSource(List? endpoints, IChangeToken changeToken, IFeatureCollection features)
{
ArgumentNullException.ThrowIfNull(changeToken);
+ ArgumentNullException.ThrowIfNull(features);
_endpoints = endpoints;
Features = features;
diff --git a/src/Microsoft.Extensions.ServiceDiscovery/ServiceDiscoveryHttpClientBuilderExtensions.cs b/src/Microsoft.Extensions.ServiceDiscovery/ServiceDiscoveryHttpClientBuilderExtensions.cs
index 8a137aad4f..7d5b94c10c 100644
--- a/src/Microsoft.Extensions.ServiceDiscovery/ServiceDiscoveryHttpClientBuilderExtensions.cs
+++ b/src/Microsoft.Extensions.ServiceDiscovery/ServiceDiscoveryHttpClientBuilderExtensions.cs
@@ -21,6 +21,8 @@ public static class ServiceDiscoveryHttpClientBuilderExtensions
/// The builder.
public static IHttpClientBuilder AddServiceDiscovery(this IHttpClientBuilder httpClientBuilder)
{
+ ArgumentNullException.ThrowIfNull(httpClientBuilder);
+
var services = httpClientBuilder.Services;
services.AddServiceDiscoveryCore();
httpClientBuilder.AddHttpMessageHandler(services =>
diff --git a/src/Microsoft.Extensions.ServiceDiscovery/ServiceDiscoveryServiceCollectionExtensions.cs b/src/Microsoft.Extensions.ServiceDiscovery/ServiceDiscoveryServiceCollectionExtensions.cs
index a5d789b7e4..ac9c5f1f36 100644
--- a/src/Microsoft.Extensions.ServiceDiscovery/ServiceDiscoveryServiceCollectionExtensions.cs
+++ b/src/Microsoft.Extensions.ServiceDiscovery/ServiceDiscoveryServiceCollectionExtensions.cs
@@ -25,6 +25,8 @@ public static class ServiceDiscoveryServiceCollectionExtensions
/// The service collection.
public static IServiceCollection AddServiceDiscovery(this IServiceCollection services)
{
+ ArgumentNullException.ThrowIfNull(services);
+
return services.AddServiceDiscoveryCore()
.AddConfigurationServiceEndpointProvider()
.AddPassThroughServiceEndpointProvider();
@@ -38,6 +40,9 @@ public static IServiceCollection AddServiceDiscovery(this IServiceCollection ser
/// The service collection.
public static IServiceCollection AddServiceDiscovery(this IServiceCollection services, Action configureOptions)
{
+ ArgumentNullException.ThrowIfNull(services);
+ ArgumentNullException.ThrowIfNull(configureOptions);
+
return services.AddServiceDiscoveryCore(configureOptions: configureOptions)
.AddConfigurationServiceEndpointProvider()
.AddPassThroughServiceEndpointProvider();
@@ -48,7 +53,12 @@ public static IServiceCollection AddServiceDiscovery(this IServiceCollection ser
///
/// The service collection.
/// The service collection.
- public static IServiceCollection AddServiceDiscoveryCore(this IServiceCollection services) => services.AddServiceDiscoveryCore(configureOptions: _ => { });
+ public static IServiceCollection AddServiceDiscoveryCore(this IServiceCollection services)
+ {
+ ArgumentNullException.ThrowIfNull(services);
+
+ return services.AddServiceDiscoveryCore(configureOptions: _ => { });
+ }
///
/// Adds the core service discovery services.
@@ -58,6 +68,9 @@ public static IServiceCollection AddServiceDiscovery(this IServiceCollection ser
/// The service collection.
public static IServiceCollection AddServiceDiscoveryCore(this IServiceCollection services, Action configureOptions)
{
+ ArgumentNullException.ThrowIfNull(services);
+ ArgumentNullException.ThrowIfNull(configureOptions);
+
services.AddOptions();
services.AddLogging();
services.TryAddTransient, ServiceDiscoveryOptionsValidator>();
@@ -66,10 +79,7 @@ public static IServiceCollection AddServiceDiscoveryCore(this IServiceCollection
services.TryAddSingleton();
services.TryAddSingleton();
services.TryAddSingleton(sp => new ServiceEndpointResolver(sp.GetRequiredService(), sp.GetRequiredService()));
- if (configureOptions is not null)
- {
- services.Configure(configureOptions);
- }
+ services.Configure(configureOptions);
return services;
}
@@ -81,6 +91,8 @@ public static IServiceCollection AddServiceDiscoveryCore(this IServiceCollection
/// The service collection.
public static IServiceCollection AddConfigurationServiceEndpointProvider(this IServiceCollection services)
{
+ ArgumentNullException.ThrowIfNull(services);
+
return services.AddConfigurationServiceEndpointProvider(configureOptions: _ => { });
}
@@ -92,13 +104,13 @@ public static IServiceCollection AddConfigurationServiceEndpointProvider(this IS
/// The service collection.
public static IServiceCollection AddConfigurationServiceEndpointProvider(this IServiceCollection services, Action configureOptions)
{
+ ArgumentNullException.ThrowIfNull(services);
+ ArgumentNullException.ThrowIfNull(configureOptions);
+
services.AddServiceDiscoveryCore();
services.AddSingleton();
services.AddTransient, ConfigurationServiceEndpointProviderOptionsValidator>();
- if (configureOptions is not null)
- {
- services.Configure(configureOptions);
- }
+ services.Configure(configureOptions);
return services;
}
@@ -110,6 +122,8 @@ public static IServiceCollection AddConfigurationServiceEndpointProvider(this IS
/// The service collection.
public static IServiceCollection AddPassThroughServiceEndpointProvider(this IServiceCollection services)
{
+ ArgumentNullException.ThrowIfNull(services);
+
services.AddServiceDiscoveryCore();
services.AddSingleton();
return services;
diff --git a/tests/Aspire.Azure.AI.OpenAI.Tests/AzureAIOpenAIPublicApiTests.cs b/tests/Aspire.Azure.AI.OpenAI.Tests/AzureAIOpenAIPublicApiTests.cs
new file mode 100644
index 0000000000..877e47faae
--- /dev/null
+++ b/tests/Aspire.Azure.AI.OpenAI.Tests/AzureAIOpenAIPublicApiTests.cs
@@ -0,0 +1,80 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Azure.AI.OpenAI;
+using Azure.Core.Extensions;
+using Microsoft.Extensions.Hosting;
+using Xunit;
+
+namespace Aspire.Azure.AI.OpenAI.Tests;
+
+public class AzureAIOpenAIPublicApiTests
+{
+ [Fact]
+ public void AddAzureOpenAIClientShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string connectionName = "openai";
+
+ var action = () => builder.AddAzureOpenAIClient(
+ connectionName,
+ default(Action?),
+ default(Action>?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddAzureOpenAIClientShouldThrowWhenConnectionNameIsNullOrEmpty(bool isNull)
+ {
+ IHostApplicationBuilder builder = new HostApplicationBuilder();
+ var connectionName = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddAzureOpenAIClient(
+ connectionName,
+ default(Action?),
+ default(Action>?));
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(connectionName), exception.ParamName);
+ }
+
+ [Fact]
+ public void AddKeyedAzureOpenAIClientShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string name = "openai";
+
+ var action = () => builder.AddKeyedAzureOpenAIClient(
+ name,
+ default(Action?),
+ default(Action>?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddKeyedAzureOpenAIClientShouldThrowWhenNameIsNullOrEmpty(bool isNull)
+ {
+ IHostApplicationBuilder builder = new HostApplicationBuilder();
+ var name = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddKeyedAzureOpenAIClient(
+ name,
+ default(Action?),
+ default(Action>?));
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action); ;
+ Assert.Equal(nameof(name), exception.ParamName);
+ }
+}
diff --git a/tests/Aspire.Azure.Data.Tables.Tests/AspireTablesPublicApiTests.cs b/tests/Aspire.Azure.Data.Tables.Tests/AspireTablesPublicApiTests.cs
new file mode 100644
index 0000000000..522cdb94e3
--- /dev/null
+++ b/tests/Aspire.Azure.Data.Tables.Tests/AspireTablesPublicApiTests.cs
@@ -0,0 +1,76 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Azure.Core.Extensions;
+using Azure.Data.Tables;
+using Microsoft.Extensions.Hosting;
+using Xunit;
+
+namespace Aspire.Azure.Data.Tables.Tests;
+
+public class AspireTablesPublicApiTests
+{
+ [Fact]
+ public void AddAzureTableClientShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string connectionName = "tables";
+
+ var action = () => builder.AddAzureTableClient(
+ connectionName,
+ default(Action?),
+ default(Action>?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddAzureTableClientShouldThrowWhenConnectionNameIsNullOrEmpty(bool isNull)
+ {
+ var builder = new HostApplicationBuilder();
+ var connectionName = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddAzureTableClient(
+ connectionName,
+ default(Action?),
+ default(Action>?));
+
+ var exception = isNull ? Assert.Throws(action) : Assert.Throws(action);
+ Assert.Equal(nameof(connectionName), exception.ParamName);
+ }
+
+ [Fact]
+ public void AddKeyedAzureTableClientShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string name = "tables";
+
+ var action = () => builder.AddKeyedAzureTableClient(
+ name,
+ default(Action?),
+ default(Action>?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddKeyedAzureTableClientShouldThrowWhenNameIsNullOrEmpty(bool isNull)
+ {
+ var builder = new HostApplicationBuilder();
+ var name = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddKeyedAzureTableClient(
+ name,
+ default(Action?),
+ default(Action>?));
+
+ var exception = isNull ? Assert.Throws(action) : Assert.Throws(action);
+ Assert.Equal(nameof(name), exception.ParamName);
+ }
+}
diff --git a/tests/Aspire.Azure.Search.Documents.Tests/DocumentsPublicApiTests.cs b/tests/Aspire.Azure.Search.Documents.Tests/DocumentsPublicApiTests.cs
new file mode 100644
index 0000000000..7f761e18d0
--- /dev/null
+++ b/tests/Aspire.Azure.Search.Documents.Tests/DocumentsPublicApiTests.cs
@@ -0,0 +1,78 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Azure.Core.Extensions;
+using Azure.Search.Documents.Indexes;
+using Azure.Search.Documents;
+using Microsoft.Extensions.Hosting;
+using Xunit;
+
+namespace Aspire.Azure.Search.Documents.Tests;
+
+public class DocumentsPublicApiTests
+{
+ [Fact]
+ public void AddAzureSearchClientShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string connectionName = "search";
+
+ var action = () => builder.AddAzureSearchClient(
+ connectionName,
+ default(Action?),
+ default(Action>?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddAzureSearchClientShouldThrowWhenConnectionNameIsNullOrEmpty(bool isNull)
+ {
+ IHostApplicationBuilder builder = new HostApplicationBuilder();
+ var connectionName = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddAzureSearchClient(connectionName);
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(connectionName), exception.ParamName);
+ }
+
+ [Fact]
+ public void AddKeyedAzureSearchClientShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string name = "search";
+
+ var action = () => builder.AddKeyedAzureSearchClient(
+ name,
+ default(Action?),
+ default(Action>?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddKeyedAzureSearchClientShouldThrowWhenNameIsNullOrEmpty(bool isNull)
+ {
+ IHostApplicationBuilder builder = new HostApplicationBuilder();
+ var name = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddKeyedAzureSearchClient(
+ name,
+ default(Action?),
+ default(Action>?));
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(name), exception.ParamName);
+ }
+}
diff --git a/tests/Aspire.Azure.Security.KeyVault.Tests/KeyVaultPublicApiTests.cs b/tests/Aspire.Azure.Security.KeyVault.Tests/KeyVaultPublicApiTests.cs
new file mode 100644
index 0000000000..ed248f8ea2
--- /dev/null
+++ b/tests/Aspire.Azure.Security.KeyVault.Tests/KeyVaultPublicApiTests.cs
@@ -0,0 +1,118 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Azure.Core.Extensions;
+using Azure.Extensions.AspNetCore.Configuration.Secrets;
+using Azure.Security.KeyVault.Secrets;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Hosting;
+using Xunit;
+
+namespace Aspire.Azure.Security.KeyVault.Tests;
+
+public class KeyVaultPublicApiTests
+{
+ [Fact]
+ public void AddAzureKeyVaultClientShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string connectionName = "keyvault";
+
+ var action = () => builder.AddAzureKeyVaultClient(
+ connectionName,
+ default(Action?),
+ default(Action>?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddAzureKeyVaultClientShouldThrowWhenConnectionNameIsNullOrEmpty(bool isNull)
+ {
+ IHostApplicationBuilder builder = new HostApplicationBuilder();
+ var connectionName = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddAzureKeyVaultClient(
+ connectionName,
+ default(Action?),
+ default(Action>?));
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(connectionName), exception.ParamName);
+ }
+
+ [Fact]
+ public void AddKeyedAzureKeyVaultClientShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string name = "keyvault";
+
+ var action = () => builder.AddKeyedAzureKeyVaultClient(
+ name,
+ default(Action?),
+ default(Action>?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddKeyedAzureKeyVaultClientShouldThrowWhenNameIsNullOrEmpty(bool isNull)
+ {
+ IHostApplicationBuilder builder = new HostApplicationBuilder();
+ var name = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddKeyedAzureKeyVaultClient(
+ name,
+ default(Action?),
+ default(Action>?));
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(name), exception.ParamName);
+ }
+
+ [Fact]
+ public void AddAzureKeyVaultSecretsShouldThrowWhenConfigurationManagerIsNull()
+ {
+ IConfigurationManager configurationManager = null!;
+ const string connectionName = "secrets";
+
+ var action = () => configurationManager.AddAzureKeyVaultSecrets(
+ connectionName,
+ default(Action?),
+ default(Action?),
+ default(AzureKeyVaultConfigurationOptions?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(configurationManager), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddAzureKeyVaultSecretsShouldThrowWhenConnectionNameIsNullOrEmpty(bool isNull)
+ {
+ IConfigurationManager configurationManager = new ConfigurationManager();
+ var connectionName = isNull ? null! : string.Empty;
+
+ var action = () => configurationManager.AddAzureKeyVaultSecrets(
+ connectionName,
+ default(Action?),
+ default(Action?),
+ default(AzureKeyVaultConfigurationOptions?));
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(connectionName), exception.ParamName);
+ }
+}
diff --git a/tests/Aspire.Azure.Storage.Queues.Tests/QueuesPublicApiTests.cs b/tests/Aspire.Azure.Storage.Queues.Tests/QueuesPublicApiTests.cs
new file mode 100644
index 0000000000..49609a0659
--- /dev/null
+++ b/tests/Aspire.Azure.Storage.Queues.Tests/QueuesPublicApiTests.cs
@@ -0,0 +1,80 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Azure.Core.Extensions;
+using Azure.Storage.Queues;
+using Microsoft.Extensions.Hosting;
+using Xunit;
+
+namespace Aspire.Azure.Storage.Queues.Tests;
+
+public class QueuesPublicApiTests
+{
+ [Fact]
+ public void AddAzureQueueClientShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string connectionName = "queue";
+
+ var action = () => builder.AddAzureQueueClient(
+ connectionName,
+ default(Action?),
+ default(Action>?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddAzureQueueClientShouldThrowWhenConnectionNameIsNullOrEmpty(bool isNull)
+ {
+ IHostApplicationBuilder builder = new HostApplicationBuilder();
+ var connectionName = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddAzureQueueClient(
+ connectionName,
+ default(Action?),
+ default(Action>?));
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(connectionName), exception.ParamName);
+ }
+
+ [Fact]
+ public void AddKeyedAzureQueueClientShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string name = "queue";
+
+ var action = () => builder.AddKeyedAzureQueueClient(
+ name,
+ default(Action?),
+ default(Action>?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddKeyedAzureQueueClientShouldThrowWhenNameIsNullOrEmpty(bool isNull)
+ {
+ IHostApplicationBuilder builder = new HostApplicationBuilder();
+ var name = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddKeyedAzureQueueClient(
+ name,
+ default(Action?),
+ default(Action>?));
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(name), exception.ParamName);
+ }
+}
diff --git a/tests/Aspire.Confluent.Kafka.Tests/KafkaPublicApiTests.cs b/tests/Aspire.Confluent.Kafka.Tests/KafkaPublicApiTests.cs
new file mode 100644
index 0000000000..f4bb0991f5
--- /dev/null
+++ b/tests/Aspire.Confluent.Kafka.Tests/KafkaPublicApiTests.cs
@@ -0,0 +1,733 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Confluent.Kafka;
+using Microsoft.Extensions.Hosting;
+using Xunit;
+
+namespace Aspire.Confluent.Kafka.Tests;
+
+public class KafkaPublicApiTests
+{
+ [Fact]
+ public void AddKafkaConsumerShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string connectionName = "Kafka:Consumer";
+
+ var action = () => builder.AddKafkaConsumer(connectionName);
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddKafkaConsumerShouldThrowWhenConnectionNameIsNullOrEmpty(bool isNull)
+ {
+ IHostApplicationBuilder builder = new HostApplicationBuilder();
+ var connectionName = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddKafkaConsumer(connectionName);
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(connectionName), exception.ParamName);
+ }
+
+ [Fact]
+ public void AddKafkaConsumerWithConfigureSettingsShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string connectionName = "Kafka:Consumer";
+
+ var action = () => builder.AddKafkaConsumer(connectionName, default(Action?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddKafkaConsumerWithConfigureSettingsShouldThrowWhenConnectionNameIsNullOrEmpty(bool isNull)
+ {
+ IHostApplicationBuilder builder = new HostApplicationBuilder();
+ var connectionName = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddKafkaConsumer(connectionName, default(Action?));
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(connectionName), exception.ParamName);
+ }
+
+ [Fact]
+ public void AddKafkaConsumerWithConfigureBuilderShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string connectionName = "Kafka:Consumer";
+
+ var action = () => builder.AddKafkaConsumer(connectionName, default(Action>?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddKafkaConsumerWithConfigureBuilderShouldThrowWhenConnectionNameIsNullOrEmpty(bool isNull)
+ {
+ IHostApplicationBuilder builder = new HostApplicationBuilder();
+ var connectionName = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddKafkaConsumer(connectionName, default(Action>?));
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(connectionName), exception.ParamName);
+ }
+
+ [Fact]
+ public void AddKafkaConsumerWithConsumerBuilderShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string connectionName = "Kafka:Consumer";
+
+ var action = () => builder.AddKafkaConsumer(connectionName, default(Action