diff --git a/Aspire.sln b/Aspire.sln
index 67aaa7e232b..a76dfced011 100644
--- a/Aspire.sln
+++ b/Aspire.sln
@@ -160,6 +160,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.MySqlConnector.Tests
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestProject.IntegrationServiceA", "tests\testproject\TestProject.IntegrationServiceA\TestProject.IntegrationServiceA.csproj", "{DCF2D47A-921A-4900-B5B2-CF97B3531CE8}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.MongoDB.Driver", "src\Components\Aspire.MongoDB.Driver\Aspire.MongoDB.Driver.csproj", "{20A5A907-A135-4735-B4BF-E13514F360E3}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.MongoDB.Driver.Tests", "tests\Aspire.MongoDB.Driver.Tests\Aspire.MongoDB.Driver.Tests.csproj", "{E592E447-BA3C-44FA-86C1-EBEDC864A644}"
+EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject.LaunchSettings", "tests\testproject\TestProject.LaunchSettings\TestProject.LaunchSettings.csproj", "{A734177E-213B-4D68-98A4-6F5C00234053}"
EndProject
Global
@@ -432,6 +436,18 @@ Global
{DCF2D47A-921A-4900-B5B2-CF97B3531CE8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DCF2D47A-921A-4900-B5B2-CF97B3531CE8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DCF2D47A-921A-4900-B5B2-CF97B3531CE8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {20A5A907-A135-4735-B4BF-E13514F360E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {20A5A907-A135-4735-B4BF-E13514F360E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {20A5A907-A135-4735-B4BF-E13514F360E3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {20A5A907-A135-4735-B4BF-E13514F360E3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E592E447-BA3C-44FA-86C1-EBEDC864A644}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E592E447-BA3C-44FA-86C1-EBEDC864A644}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E592E447-BA3C-44FA-86C1-EBEDC864A644}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E592E447-BA3C-44FA-86C1-EBEDC864A644}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6472D59F-7C04-43DE-AD33-9F20BE3804BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6472D59F-7C04-43DE-AD33-9F20BE3804BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6472D59F-7C04-43DE-AD33-9F20BE3804BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6472D59F-7C04-43DE-AD33-9F20BE3804BF}.Release|Any CPU.Build.0 = Release|Any CPU
{A734177E-213B-4D68-98A4-6F5C00234053}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A734177E-213B-4D68-98A4-6F5C00234053}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A734177E-213B-4D68-98A4-6F5C00234053}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -510,6 +526,8 @@ Global
{6472D59F-7C04-43DE-AD33-9F20BE3804BF} = {975F6F41-B455-451D-A312-098DE4A167B6}
{CA283D7F-EB95-4353-B196-C409965D2B42} = {27381127-6C45-4B4C-8F18-41FF48DFE4B2}
{C8079F06-304F-49B1-A0C1-45AA3782A923} = {4981B3A5-4AFD-4191-BF7D-8692D9783D60}
+ {20A5A907-A135-4735-B4BF-E13514F360E3} = {27381127-6C45-4B4C-8F18-41FF48DFE4B2}
+ {E592E447-BA3C-44FA-86C1-EBEDC864A644} = {4981B3A5-4AFD-4191-BF7D-8692D9783D60}
{DCF2D47A-921A-4900-B5B2-CF97B3531CE8} = {975F6F41-B455-451D-A312-098DE4A167B6}
{A734177E-213B-4D68-98A4-6F5C00234053} = {975F6F41-B455-451D-A312-098DE4A167B6}
EndGlobalSection
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 28016362143..0254f2f56a6 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -35,6 +35,7 @@
+
@@ -71,6 +72,8 @@
+
+
diff --git a/src/Aspire.Hosting/MongoDB/IMongoDBResource.cs b/src/Aspire.Hosting/MongoDB/IMongoDBResource.cs
new file mode 100644
index 00000000000..8209c835abd
--- /dev/null
+++ b/src/Aspire.Hosting/MongoDB/IMongoDBResource.cs
@@ -0,0 +1,11 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Aspire.Hosting.ApplicationModel;
+
+///
+/// Represents a MongoDB resource that requires a connection string.
+///
+public interface IMongoDBResource : IResourceWithConnectionString
+{
+}
diff --git a/src/Aspire.Hosting/MongoDB/MongoDBBuilderExtensions.cs b/src/Aspire.Hosting/MongoDB/MongoDBBuilderExtensions.cs
new file mode 100644
index 00000000000..a2bffeddc3d
--- /dev/null
+++ b/src/Aspire.Hosting/MongoDB/MongoDBBuilderExtensions.cs
@@ -0,0 +1,86 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Net.Sockets;
+using Aspire.Hosting.ApplicationModel;
+using Aspire.Hosting.Publishing;
+
+namespace Aspire.Hosting;
+
+///
+/// Provides extension methods for adding MongoDB resources to an .
+///
+public static class MongoDBBuilderExtensions
+{
+ private const int DefaultContainerPort = 27017;
+
+ ///
+ /// Adds a MongoDB container to the application model. The default image is "mongo" and the tag is "latest".
+ ///
+ ///
+ /// The .
+ /// The name of the resource. This name will be used as the connection string name when referenced in a dependency.
+ /// The host port for MongoDB.
+ /// A reference to the .
+ public static IResourceBuilder AddMongoDBContainer(
+ this IDistributedApplicationBuilder builder,
+ string name,
+ int? port = null)
+ {
+ var mongoDBContainer = new MongoDBContainerResource(name);
+
+ return builder
+ .AddResource(mongoDBContainer)
+ .WithManifestPublishingCallback(WriteMongoDBContainerToManifest)
+ .WithAnnotation(new ServiceBindingAnnotation(ProtocolType.Tcp, port: port, containerPort: DefaultContainerPort)) // Internal port is always 27017.
+ .WithAnnotation(new ContainerImageAnnotation { Image = "mongo", Tag = "latest" });
+ }
+
+ ///
+ /// Adds a MongoDB connection to the application model. Connection strings can also be read from the connection string section of the configuration using the name of the resource.
+ ///
+ /// The .
+ /// The name of the resource. This name will be used as the connection string name when referenced in a dependency.
+ /// The MongoDB connection string (optional).
+ /// A reference to the .
+ public static IResourceBuilder AddMongoDBConnection(this IDistributedApplicationBuilder builder, string name, string? connectionString = null)
+ {
+ var mongoDBConnection = new MongoDBConnectionResource(name, connectionString);
+
+ return builder
+ .AddResource(mongoDBConnection)
+ .WithManifestPublishingCallback(context => context.WriteMongoDBConnectionToManifest(mongoDBConnection));
+ }
+
+ ///
+ /// Adds a MongoDB database to the application model.
+ ///
+ /// The MongoDB server resource builder.
+ /// The name of the resource. This name will be used as the connection string name when referenced in a dependency.
+ /// A reference to the .
+ public static IResourceBuilder AddDatabase(this IResourceBuilder builder, string name)
+ {
+ var mongoDBDatabase = new MongoDBDatabaseResource(name, builder.Resource);
+
+ return builder.ApplicationBuilder
+ .AddResource(mongoDBDatabase)
+ .WithManifestPublishingCallback(context => context.WriteMongoDBDatabaseToManifest(mongoDBDatabase));
+ }
+
+ private static void WriteMongoDBContainerToManifest(this ManifestPublishingContext context)
+ {
+ context.Writer.WriteString("type", "mongodb.server.v0");
+ }
+
+ private static void WriteMongoDBConnectionToManifest(this ManifestPublishingContext context, MongoDBConnectionResource mongoDbConnection)
+ {
+ context.Writer.WriteString("type", "mongodb.connection.v0");
+ context.Writer.WriteString("connectionString", mongoDbConnection.GetConnectionString());
+ }
+
+ private static void WriteMongoDBDatabaseToManifest(this ManifestPublishingContext context, MongoDBDatabaseResource mongoDbDatabase)
+ {
+ context.Writer.WriteString("type", "mongodb.database.v0");
+ context.Writer.WriteString("parent", mongoDbDatabase.Parent.Name);
+ }
+}
diff --git a/src/Aspire.Hosting/MongoDB/MongoDBConnectionResource.cs b/src/Aspire.Hosting/MongoDB/MongoDBConnectionResource.cs
new file mode 100644
index 00000000000..b3d749eddca
--- /dev/null
+++ b/src/Aspire.Hosting/MongoDB/MongoDBConnectionResource.cs
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Aspire.Hosting.ApplicationModel;
+
+///
+/// A resource that represents a MongoDB connection.
+///
+/// The name of the resource.
+/// The MongoDB connection string.
+public class MongoDBConnectionResource(string name, string? connectionString) : Resource(name), IMongoDBResource
+{
+ private readonly string? _connectionString = connectionString;
+
+ ///
+ /// Gets the connection string for the MongoDB server.
+ ///
+ /// The specified connection string.
+ public string? GetConnectionString() => _connectionString;
+}
diff --git a/src/Aspire.Hosting/MongoDB/MongoDBConnectionStringBuilder.cs b/src/Aspire.Hosting/MongoDB/MongoDBConnectionStringBuilder.cs
new file mode 100644
index 00000000000..874876e1e73
--- /dev/null
+++ b/src/Aspire.Hosting/MongoDB/MongoDBConnectionStringBuilder.cs
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Aspire.Hosting.MongoDB;
+
+internal class MongoDBConnectionStringBuilder
+{
+ private const string Scheme = "mongodb";
+
+ private string? _server;
+ private int _port;
+ private string? _userName;
+ private string? _password;
+
+ public MongoDBConnectionStringBuilder WithServer(string server)
+ {
+ ArgumentNullException.ThrowIfNullOrWhiteSpace(server, nameof(server));
+
+ _server = server;
+
+ return this;
+ }
+
+ public MongoDBConnectionStringBuilder WithPort(int port)
+ {
+ _port = port;
+
+ return this;
+ }
+
+ public MongoDBConnectionStringBuilder WithUserName(string userName)
+ {
+ ArgumentNullException.ThrowIfNullOrWhiteSpace(userName, nameof(userName));
+
+ _userName = userName;
+
+ return this;
+ }
+
+ public MongoDBConnectionStringBuilder WithPassword(string password)
+ {
+ ArgumentNullException.ThrowIfNullOrWhiteSpace(password, nameof(password));
+
+ _password = password;
+
+ return this;
+ }
+
+ public string Build()
+ {
+ var builder = new UriBuilder
+ {
+ Scheme = Scheme,
+ Host = _server,
+ Port = _port,
+ UserName = _userName,
+ Password = _password
+ };
+
+ return builder.ToString();
+ }
+}
diff --git a/src/Aspire.Hosting/MongoDB/MongoDBContainerResource.cs b/src/Aspire.Hosting/MongoDB/MongoDBContainerResource.cs
new file mode 100644
index 00000000000..fbb68f23811
--- /dev/null
+++ b/src/Aspire.Hosting/MongoDB/MongoDBContainerResource.cs
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Aspire.Hosting.MongoDB;
+
+namespace Aspire.Hosting.ApplicationModel;
+
+///
+/// A resource that represents a MongoDB container.
+///
+/// The name of the resource.
+public class MongoDBContainerResource(string name) : ContainerResource(name), IMongoDBResource
+{
+ ///
+ /// Gets the connection string for the MongoDB server.
+ ///
+ /// A connection string for the MongoDB server in the form "mongodb://host:port".
+ public string? GetConnectionString()
+ {
+ if (!this.TryGetAllocatedEndPoints(out var allocatedEndpoints))
+ {
+ throw new DistributedApplicationException("Expected allocated endpoints!");
+ }
+
+ var allocatedEndpoint = allocatedEndpoints.Single();
+
+ return new MongoDBConnectionStringBuilder()
+ .WithServer(allocatedEndpoint.Address)
+ .WithPort(allocatedEndpoint.Port)
+ .Build();
+ }
+}
diff --git a/src/Aspire.Hosting/MongoDB/MongoDBDatabaseResource.cs b/src/Aspire.Hosting/MongoDB/MongoDBDatabaseResource.cs
new file mode 100644
index 00000000000..7e0e4b45f37
--- /dev/null
+++ b/src/Aspire.Hosting/MongoDB/MongoDBDatabaseResource.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Aspire.Hosting.ApplicationModel;
+
+///
+/// A resource that represents a MongoDB database. This is a child resource of a .
+///
+/// The name of the resource.
+/// The MongoDB server resource associated with this database.
+public class MongoDBDatabaseResource(string name, MongoDBContainerResource mongoDBContainer)
+ : Resource(name), IMongoDBResource, IResourceWithParent
+{
+ public MongoDBContainerResource Parent => mongoDBContainer;
+
+ ///
+ /// Gets the connection string for the MongoDB database.
+ ///
+ /// A connection string for the MongoDB database.
+ public string? GetConnectionString()
+ {
+ if (Parent.GetConnectionString() is { } connectionString)
+ {
+ return connectionString.EndsWith('/') ?
+ $"{connectionString}{Name}" :
+ $"{connectionString}/{Name}";
+ }
+
+ throw new DistributedApplicationException("Parent resource connection string was null.");
+ }
+}
diff --git a/src/Components/Aspire.MongoDB.Driver/Aspire.MongoDB.Driver.csproj b/src/Components/Aspire.MongoDB.Driver/Aspire.MongoDB.Driver.csproj
new file mode 100644
index 00000000000..e8ed5a17692
--- /dev/null
+++ b/src/Components/Aspire.MongoDB.Driver/Aspire.MongoDB.Driver.csproj
@@ -0,0 +1,25 @@
+
+
+
+ $(NetCurrent)
+ true
+ $(ComponentDatabasePackageTags) MongoDB
+ A generic MongoDB client that integrates with Aspire.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Components/Aspire.MongoDB.Driver/AspireMongoDBDriverExtensions.cs b/src/Components/Aspire.MongoDB.Driver/AspireMongoDBDriverExtensions.cs
new file mode 100644
index 00000000000..d4594054b4a
--- /dev/null
+++ b/src/Components/Aspire.MongoDB.Driver/AspireMongoDBDriverExtensions.cs
@@ -0,0 +1,233 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Aspire;
+using Aspire.MongoDB.Driver;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using MongoDB.Driver;
+using MongoDB.Driver.Core.Configuration;
+using MongoDB.Driver.Core.Extensions.DiagnosticSources;
+
+namespace Microsoft.Extensions.Hosting;
+
+///
+/// Extension methods for connecting MongoDB database with MongoDB.Driver client.
+///
+public static class AspireMongoDBDriverExtensions
+{
+ private const string DefaultConfigSectionName = "Aspire:MongoDB:Driver";
+ private const string ActivityNameSource = "MongoDB.Driver.Core.Extensions.DiagnosticSources";
+
+ ///
+ /// Registers and instances for connecting MongoDB database with MongoDB.Driver client.
+ ///
+ /// The to read config from and add services to.
+ /// A name used to retrieve the connection string from the ConnectionStrings configuration section.
+ /// An optional delegate that can be used for customizing options. It's invoked after the settings are read from the configuration.
+ /// Reads the configuration from "Aspire:MongoDB:Driver" section.
+ /// An optional delegate that can be used for customizing MongoClientSettings.
+ /// Thrown when mandatory is not provided.
+ public static void AddMongoDBClient(
+ this IHostApplicationBuilder builder,
+ string connectionName,
+ Action? configureSettings = null,
+ Action? configureClientSettings = null)
+ => builder.AddMongoDBClient(DefaultConfigSectionName, configureSettings, configureClientSettings, connectionName, serviceKey: null);
+
+ ///
+ /// Registers and instances for connecting MongoDB database with MongoDB.Driver client.
+ ///
+ /// The to read config from and add services to.
+ /// The name of the component, which is used as the of the service and also to retrieve the connection string from the ConnectionStrings configuration section.
+ /// An optional delegate that can be used for customizing options. It's invoked after the settings are read from the configuration.
+ /// Reads the configuration from "Aspire:MongoDB:Driver:{name}" section.
+ /// An optional delegate that can be used for customizing MongoClientSettings.
+ /// Thrown if mandatory is null.
+ /// Thrown when mandatory is not provided.
+ public static void AddKeyedMongoDBClient(
+ this IHostApplicationBuilder builder,
+ string name,
+ Action? configureSettings = null,
+ Action? configureClientSettings = null)
+ {
+ ArgumentException.ThrowIfNullOrEmpty(name);
+
+ builder.AddMongoDBClient(
+ $"{DefaultConfigSectionName}:{name}",
+ configureSettings,
+ configureClientSettings,
+ connectionName: name,
+ serviceKey: name);
+ }
+
+ private static void AddMongoDBClient(
+ this IHostApplicationBuilder builder,
+ string configurationSectionName,
+ Action? configureSettings,
+ Action? configureClientSettings,
+ string connectionName,
+ object? serviceKey)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+
+ var settings = builder.GetMongoDBSettings(
+ connectionName,
+ configurationSectionName,
+ configureSettings);
+
+ builder.AddMongoClient(
+ settings,
+ connectionName,
+ configurationSectionName,
+ configureClientSettings,
+ serviceKey);
+
+ if (settings.Tracing)
+ {
+ builder.Services
+ .AddOpenTelemetry()
+ .WithTracing(tracer => tracer.AddSource(ActivityNameSource));
+ }
+
+ builder.AddMongoDatabase(settings.ConnectionString, serviceKey);
+ builder.AddHealthCheck(
+ serviceKey is null ? "MongoDB.Driver" : $"MongoDB.Driver_{connectionName}",
+ settings);
+ }
+
+ private static void AddMongoClient(
+ this IHostApplicationBuilder builder,
+ MongoDBSettings mongoDbSettings,
+ string connectionName,
+ string configurationSectionName,
+ Action? configureClientSettings,
+ object? serviceKey)
+ {
+ if (serviceKey is null)
+ {
+ builder
+ .Services
+ .AddSingleton(sp => sp.CreateMongoClient(connectionName, configurationSectionName, mongoDbSettings, configureClientSettings));
+ return;
+ }
+
+ builder
+ .Services
+ .AddKeyedSingleton(serviceKey, (sp, _) => sp.CreateMongoClient(connectionName, configurationSectionName, mongoDbSettings, configureClientSettings));
+ }
+
+ private static void AddMongoDatabase(
+ this IHostApplicationBuilder builder,
+ string? connectionString,
+ object? serviceKey = null)
+ {
+ if (string.IsNullOrWhiteSpace(connectionString))
+ {
+ return;
+ }
+
+ var mongoUrl = MongoUrl.Create(connectionString);
+
+ if (string.IsNullOrWhiteSpace(mongoUrl.DatabaseName))
+ {
+ return;
+ }
+
+ if (serviceKey is null)
+ {
+ builder.Services.AddSingleton(provider =>
+ {
+ return provider
+ .GetRequiredService()
+ .GetDatabase(mongoUrl.DatabaseName);
+ });
+
+ return;
+ }
+
+ builder.Services.AddKeyedSingleton(serviceKey, (provider, _) =>
+ {
+ return provider
+ .GetRequiredKeyedService(serviceKey)
+ .GetDatabase(mongoUrl.DatabaseName);
+ });
+ }
+
+ private static void AddHealthCheck(
+ this IHostApplicationBuilder builder,
+ string healthCheckName,
+ MongoDBSettings settings)
+ {
+ if (!settings.HealthChecks || string.IsNullOrWhiteSpace(settings.ConnectionString))
+ {
+ return;
+ }
+
+ builder.TryAddHealthCheck(
+ healthCheckName,
+ healthCheck => healthCheck.AddMongoDb(
+ settings.ConnectionString,
+ healthCheckName,
+ null,
+ null,
+ settings.HealthCheckTimeout > 0 ? TimeSpan.FromMilliseconds(settings.HealthCheckTimeout.Value) : null));
+ }
+
+ private static MongoClient CreateMongoClient(
+ this IServiceProvider serviceProvider,
+ string connectionName,
+ string configurationSectionName,
+ MongoDBSettings mongoDbSettings,
+ Action? configureClientSettings)
+ {
+ mongoDbSettings.ValidateSettings(connectionName, configurationSectionName);
+
+ var clientSettings = MongoClientSettings.FromConnectionString(mongoDbSettings.ConnectionString);
+
+ if (mongoDbSettings.Tracing)
+ {
+ clientSettings.ClusterConfigurator = cb => cb.Subscribe(new DiagnosticsActivityEventSubscriber());
+ }
+
+ configureClientSettings?.Invoke(clientSettings);
+
+ clientSettings.LoggingSettings ??= new LoggingSettings(serviceProvider.GetService());
+
+ return new MongoClient(clientSettings);
+ }
+
+ private static MongoDBSettings GetMongoDBSettings(
+ this IHostApplicationBuilder builder,
+ string connectionName,
+ string configurationSectionName,
+ Action? configureSettings)
+ {
+ var settings = new MongoDBSettings();
+
+ builder.Configuration
+ .GetSection(configurationSectionName)
+ .Bind(settings);
+
+ if (builder.Configuration.GetConnectionString(connectionName) is string connectionString)
+ {
+ settings.ConnectionString = connectionString;
+ }
+
+ configureSettings?.Invoke(settings);
+
+ return settings;
+ }
+
+ private static void ValidateSettings(
+ this MongoDBSettings settings,
+ string connectionName,
+ string configurationSectionName)
+ {
+ if (string.IsNullOrEmpty(settings.ConnectionString))
+ {
+ throw new InvalidOperationException($"ConnectionString is missing. It should be provided in 'ConnectionStrings:{connectionName}' or under the 'ConnectionString' key in '{configurationSectionName}' configuration section.");
+ }
+ }
+}
diff --git a/src/Components/Aspire.MongoDB.Driver/ConfigurationSchema.json b/src/Components/Aspire.MongoDB.Driver/ConfigurationSchema.json
new file mode 100644
index 00000000000..01e046d85e8
--- /dev/null
+++ b/src/Components/Aspire.MongoDB.Driver/ConfigurationSchema.json
@@ -0,0 +1,60 @@
+{
+ "definitions": {
+ "logLevel": {
+ "properties": {
+ "MongoDB": {
+ "$ref": "#/definitions/logLevelThreshold"
+ },
+ "MongoDB.Command": {
+ "$ref": "#/definitions/logLevelThreshold"
+ },
+ "MongoDB.SDAM": {
+ "$ref": "#/definitions/logLevelThreshold"
+ },
+ "MongoDB.ServerSelection": {
+ "$ref": "#/definitions/logLevelThreshold"
+ },
+ "MongoDB.Connection": {
+ "$ref": "#/definitions/logLevelThreshold"
+ },
+ "MongoDB.Internal": {
+ "$ref": "#/definitions/logLevelThreshold"
+ }
+ }
+ }
+ },
+ "properties": {
+ "Aspire": {
+ "type": "object",
+ "properties": {
+ "MongoDB": {
+ "type": "object",
+ "properties": {
+ "Driver": {
+ "type": "object",
+ "properties": {
+ "ConnectionString": {
+ "type": "string",
+ "description": "Gets or sets the connection string of the MongoDB database to connect to."
+ },
+ "HealthChecks": {
+ "type": "boolean",
+ "description": "Gets or sets a boolean value that indicates whether the MongoDB health check is enabled or not."
+ },
+ "HealthCheckTimeout": {
+ "type": "integer",
+ "description": "Gets or sets a integer value that indicates the MongoDB health check timeout in milliseconds."
+ },
+ "Tracing": {
+ "type": "boolean",
+ "description": "Gets or sets a boolean value that indicates whether the Open Telemetry tracing is enabled or not."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object"
+}
diff --git a/src/Components/Aspire.MongoDB.Driver/MongoDBSettings.cs b/src/Components/Aspire.MongoDB.Driver/MongoDBSettings.cs
new file mode 100644
index 00000000000..ebe1e838439
--- /dev/null
+++ b/src/Components/Aspire.MongoDB.Driver/MongoDBSettings.cs
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Aspire.MongoDB.Driver;
+
+///
+/// Provides the client configuration settings for connecting to a MongoDB database using MongoDB driver.
+///
+public sealed class MongoDBSettings
+{
+ ///
+ /// Gets or sets the connection string of the MongoDB database to connect to.
+ ///
+ public string? ConnectionString { get; set; }
+
+ ///
+ /// Gets or sets a boolean value that indicates whether the MongoDB health check is enabled or not.
+ ///
+ /// The default value is .
+ ///
+ ///
+ public bool HealthChecks { get; set; } = true;
+
+ ///
+ /// Gets or sets a integer value that indicates the MongoDB health check timeout in milliseconds.
+ ///
+ public int? HealthCheckTimeout { get; set; }
+
+ ///
+ /// Gets or sets a boolean value that indicates whether the Open Telemetry tracing is enabled or not.
+ ///
+ /// The default value is .
+ ///
+ ///
+ public bool Tracing { get; set; } = true;
+
+}
diff --git a/src/Components/Aspire.MongoDB.Driver/README.md b/src/Components/Aspire.MongoDB.Driver/README.md
new file mode 100644
index 00000000000..5d6e6194849
--- /dev/null
+++ b/src/Components/Aspire.MongoDB.Driver/README.md
@@ -0,0 +1,113 @@
+# Aspire.MongoDB.Driver library
+
+Registers [IMongoClient](https://www.mongodb.com/docs/drivers/csharp/current/quick-start/#add-mongodb-as-a-dependency) in the DI container for connecting MongoDB database.
+
+## Getting started
+
+### Prerequisites
+
+- MongoDB database and connection string for accessing the database.
+
+### Install the package
+
+Install the .NET Aspire MongoDB.Driver library with [NuGet](https://www.nuget.org):
+
+```dotnetcli
+dotnet add package Aspire.MongoDB.Driver
+```
+
+## Usage example
+
+In the _Program.cs_ file of your project, call the `AddMongoDBClient` extension method to register a `IMongoClient` for use via the dependency injection container. The method takes a connection name parameter.
+
+```csharp
+builder.AddMongoDBClient("mongodb");
+```
+
+You can then retrieve a `IMongoClient` instance using dependency injection. For example, to retrieve a connection from a Web API controller:
+
+```csharp
+private readonly IMongoClient _client;
+
+public ProductsController(IMongoClient client)
+{
+ _client = client;
+}
+```
+
+## Configuration
+
+The .NET Aspire MongoDB component provides multiple options to configure the database connection based on the requirements and conventions of your project.
+
+### Use a connection string
+
+When using a connection string from the `ConnectionStrings` configuration section, you can provide the name of the connection string when calling `builder.AddMongoDBClient()`:
+
+```csharp
+builder.AddMongoDBClient("myConnection");
+```
+
+And then the connection string will be retrieved from the `ConnectionStrings` configuration section:
+
+```json
+{
+ "ConnectionStrings": {
+ "myConnection": "mongodb://server:port/test",
+ }
+}
+```
+
+See the [ConnectionString documentation](https://www.mongodb.com/docs/v3.0/reference/connection-string/) for more information on how to format this connection string.
+
+### Use configuration providers
+
+The .NET Aspire MongoDB component supports [Microsoft.Extensions.Configuration](https://learn.microsoft.com/dotnet/api/microsoft.extensions.configuration). It loads the `MongoDBSettings` from configuration by using the `Aspire:MongoDB:Driver` key. Example `appsettings.json` that configures some of the options:
+
+```json
+{
+ "Aspire": {
+ "MongoDB": {
+ "Driver": {
+ "ConnectionString": "mongodb://server:port/test",
+ "HealthChecks": true,
+ "HealthCheckTimeout": 10000,
+ "Tracing": true
+ },
+ }
+ }
+}
+```
+
+### Use inline delegates
+
+Also you can pass the `Action configureSettings` delegate to set up some or all the options inline:
+
+```csharp
+ builder.AddMongoDBClient("mongodb", settings => settings.ConnectionString = "mongodb://server:port/test");
+```
+
+## AppHost extensions
+
+In your AppHost project, register a MongoDB container and consume the connection using the following methods:
+
+```csharp
+var mongodb = builder.AddMongoDBContainer("mongodb").AddDatabase("mydatabase");
+
+var myService = builder.AddProject()
+ .WithReference(mongodb);
+```
+
+The `WithReference` method configures a connection in the `MyService` project named `mongodb`. In the _Program.cs_ file of `MyService`, the database connection can be consumed using:
+
+```csharp
+builder.AddMongoDBClient("mongodb");
+```
+
+## Additional documentation
+
+* https://www.mongodb.com/docs/drivers/csharp/current/quick-start/
+* https://github.com/dotnet/aspire/tree/main/src/Components/README.md
+
+## Feedback & contributing
+
+https://github.com/dotnet/aspire
diff --git a/src/Components/Aspire_Components_Progress.md b/src/Components/Aspire_Components_Progress.md
index 427a1ac1c66..6bfd399c7ac 100644
--- a/src/Components/Aspire_Components_Progress.md
+++ b/src/Components/Aspire_Components_Progress.md
@@ -10,6 +10,7 @@ As part of the .NET Aspire November preview, we want to include a set of .NET As
| Microsoft.Data.SqlClient | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ |
| Microsoft.EntityFramework.Cosmos | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| Microsoft.EntityFrameworkCore.SqlServer | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
+| MongoDB.Driver | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ |
| Azure.Data.Tables | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ |
| Azure.Messaging.ServiceBus | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ |
| Azure.Security.KeyVault | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ |
diff --git a/src/Components/Telemetry.md b/src/Components/Telemetry.md
index d55e0b7543d..f5b76e3e90d 100644
--- a/src/Components/Telemetry.md
+++ b/src/Components/Telemetry.md
@@ -78,6 +78,19 @@ Aspire.Microsoft.Data.SqlClient:
- "number-of-stasis-connections"
- "number-of-reclaimed-connections"
+Aspire.MongoDB.Driver:
+- Log categories:
+ - "MongoDB"
+ - "MongoDB.Command"
+ - "MongoDB.SDAM"
+ - "MongoDB.ServerSelection"
+ - "MongoDB.Connection"
+ - "MongoDB.Internal"
+- Activity source names:
+ - "MongoDB.Driver.Core.Extensions.DiagnosticSources"
+- Metric names:
+ - none
+
Aspire.Microsoft.EntityFrameworkCore.Cosmos:
- Log categories:
- "Azure-Cosmos-Operation-Request-Diagnostics"
diff --git a/tests/Aspire.Hosting.Tests/Aspire.Hosting.Tests.csproj b/tests/Aspire.Hosting.Tests/Aspire.Hosting.Tests.csproj
index 0b25e781558..4f1e89098ce 100644
--- a/tests/Aspire.Hosting.Tests/Aspire.Hosting.Tests.csproj
+++ b/tests/Aspire.Hosting.Tests/Aspire.Hosting.Tests.csproj
@@ -3,6 +3,8 @@
$(NetCurrent)
true
+
+ $(NoWarn),CS8002
diff --git a/tests/Aspire.Hosting.Tests/MongoDB/AddMongoDBTests.cs b/tests/Aspire.Hosting.Tests/MongoDB/AddMongoDBTests.cs
new file mode 100644
index 00000000000..b33c6e1267f
--- /dev/null
+++ b/tests/Aspire.Hosting.Tests/MongoDB/AddMongoDBTests.cs
@@ -0,0 +1,99 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Net.Sockets;
+using Microsoft.Extensions.DependencyInjection;
+using Xunit;
+
+namespace Aspire.Hosting.Tests;
+
+public class AddMongoDBTests
+{
+ [Fact]
+ public void AddMongoDBContainerWithDefaultsAddsAnnotationMetadata()
+ {
+ var appBuilder = DistributedApplication.CreateBuilder();
+
+ appBuilder.AddMongoDBContainer("mongodb");
+
+ var app = appBuilder.Build();
+
+ var appModel = app.Services.GetRequiredService();
+
+ var containerResource = Assert.Single(appModel.Resources.OfType());
+ Assert.Equal("mongodb", containerResource.Name);
+
+ var manifestAnnotation = Assert.Single(containerResource.Annotations.OfType());
+ Assert.NotNull(manifestAnnotation.Callback);
+
+ var serviceBinding = Assert.Single(containerResource.Annotations.OfType());
+ Assert.Equal(27017, serviceBinding.ContainerPort);
+ Assert.False(serviceBinding.IsExternal);
+ Assert.Equal("tcp", serviceBinding.Name);
+ Assert.Null(serviceBinding.Port);
+ Assert.Equal(ProtocolType.Tcp, serviceBinding.Protocol);
+ Assert.Equal("tcp", serviceBinding.Transport);
+ Assert.Equal("tcp", serviceBinding.UriScheme);
+
+ var containerAnnotation = Assert.Single(containerResource.Annotations.OfType());
+ Assert.Equal("latest", containerAnnotation.Tag);
+ Assert.Equal("mongo", containerAnnotation.Image);
+ Assert.Null(containerAnnotation.Registry);
+ }
+
+ [Fact]
+ public void AddMongoDBContainerAddsAnnotationMetadata()
+ {
+ var appBuilder = DistributedApplication.CreateBuilder();
+ appBuilder.AddMongoDBContainer("mongodb", 9813);
+
+ var app = appBuilder.Build();
+
+ var appModel = app.Services.GetRequiredService();
+
+ var containerResource = Assert.Single(appModel.Resources.OfType());
+ Assert.Equal("mongodb", containerResource.Name);
+
+ var manifestAnnotation = Assert.Single(containerResource.Annotations.OfType());
+ Assert.NotNull(manifestAnnotation.Callback);
+
+ var serviceBinding = Assert.Single(containerResource.Annotations.OfType());
+ Assert.Equal(27017, serviceBinding.ContainerPort);
+ Assert.False(serviceBinding.IsExternal);
+ Assert.Equal("tcp", serviceBinding.Name);
+ Assert.Equal(9813, serviceBinding.Port);
+ Assert.Equal(ProtocolType.Tcp, serviceBinding.Protocol);
+ Assert.Equal("tcp", serviceBinding.Transport);
+ Assert.Equal("tcp", serviceBinding.UriScheme);
+
+ var containerAnnotation = Assert.Single(containerResource.Annotations.OfType());
+ Assert.Equal("latest", containerAnnotation.Tag);
+ Assert.Equal("mongo", containerAnnotation.Image);
+ Assert.Null(containerAnnotation.Registry);
+ }
+
+ [Fact]
+ public void MongoDBCreatesConnectionString()
+ {
+ var appBuilder = DistributedApplication.CreateBuilder();
+ appBuilder
+ .AddMongoDBContainer("mongodb")
+ .WithAnnotation(
+ new AllocatedEndpointAnnotation("mybinding",
+ ProtocolType.Tcp,
+ "localhost",
+ 27017,
+ "https"
+ ))
+ .AddDatabase("mydatabase");
+
+ var app = appBuilder.Build();
+
+ var appModel = app.Services.GetRequiredService();
+
+ var connectionStringResource = Assert.Single(appModel.Resources.OfType());
+ var connectionString = connectionStringResource.GetConnectionString();
+
+ Assert.Equal("mongodb://localhost:27017/mydatabase", connectionString);
+ }
+}
diff --git a/tests/Aspire.Hosting.Tests/MongoDB/MongoDBContainerResourceTests.cs b/tests/Aspire.Hosting.Tests/MongoDB/MongoDBContainerResourceTests.cs
new file mode 100644
index 00000000000..f34bcbf519c
--- /dev/null
+++ b/tests/Aspire.Hosting.Tests/MongoDB/MongoDBContainerResourceTests.cs
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Aspire.Hosting.MongoDB;
+using MongoDB.Driver;
+using Xunit;
+
+namespace Aspire.Hosting.Tests.MongoDB;
+
+public class MongoDBContainerResourceTests
+{
+ [Theory]
+ [InlineData("password", "mongodb://root:password@myserver:1000/")]
+ [InlineData("@abc!$", "mongodb://root:%40abc!$@myserver:1000/")]
+ [InlineData("mypasswordwitha\"inthemiddle", "mongodb://root:mypasswordwitha\"inthemiddle@myserver:1000/")]
+ [InlineData("mypasswordwitha\"attheend\"", "mongodb://root:mypasswordwitha\"attheend\"@myserver:1000/")]
+ [InlineData("\"mypasswordwitha\"atthestart", "mongodb://root:\"mypasswordwitha\"atthestart@myserver:1000/")]
+ [InlineData("mypasswordwitha'inthemiddle", "mongodb://root:mypasswordwitha'inthemiddle@myserver:1000/")]
+ [InlineData("mypasswordwitha'attheend'", "mongodb://root:mypasswordwitha'attheend'@myserver:1000/")]
+ [InlineData("'mypasswordwitha'atthestart", "mongodb://root:'mypasswordwitha'atthestart@myserver:1000/")]
+ public void TestSpecialCharactersAndEscapeForPassword(string password, string expectedConnectionString)
+ {
+ var connectionString = new MongoDBConnectionStringBuilder()
+ .WithServer("myserver")
+ .WithPort(1000)
+ .WithUserName("root")
+ .WithPassword(password)
+ .Build();
+
+ Assert.NotNull(connectionString);
+
+ var builder = MongoUrl.Create(connectionString);
+ Assert.Equal(password, builder.Password);
+ Assert.Equal(expectedConnectionString, connectionString);
+ }
+}
diff --git a/tests/Aspire.MongoDB.Driver.Tests/Aspire.MongoDB.Driver.Tests.csproj b/tests/Aspire.MongoDB.Driver.Tests/Aspire.MongoDB.Driver.Tests.csproj
new file mode 100644
index 00000000000..ffe79958817
--- /dev/null
+++ b/tests/Aspire.MongoDB.Driver.Tests/Aspire.MongoDB.Driver.Tests.csproj
@@ -0,0 +1,14 @@
+
+
+
+ $(NetCurrent)
+
+ $(NoWarn);CS8002
+
+
+
+
+
+
+
+
diff --git a/tests/Aspire.MongoDB.Driver.Tests/AspireMongoDBDriverExtensionsTests.cs b/tests/Aspire.MongoDB.Driver.Tests/AspireMongoDBDriverExtensionsTests.cs
new file mode 100644
index 00000000000..1b3b952a931
--- /dev/null
+++ b/tests/Aspire.MongoDB.Driver.Tests/AspireMongoDBDriverExtensionsTests.cs
@@ -0,0 +1,172 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Diagnostics.HealthChecks;
+using Microsoft.Extensions.Hosting;
+using MongoDB.Driver;
+using Xunit;
+
+namespace Aspire.MongoDB.Driver.Tests;
+
+public class AspireMongoDBDriverExtensionsTests
+{
+ private const string DefaultConnectionString = "mongodb://localhost:27017/mydatabase";
+ private const string DefaultConnectionName = "mongodb";
+
+ [Theory]
+ [InlineData("mongodb://localhost:27017/mydatabase", true)]
+ [InlineData("mongodb://localhost:27017", false)]
+ public void AddMongoDBDataSource_ReadsFromConnectionStringsCorrectly(string connectionString, bool shouldRegisterDatabase)
+ {
+ var builder = CreateBuilder(connectionString);
+
+ builder.AddMongoDBClient(DefaultConnectionName);
+
+ var host = builder.Build();
+
+ var mongoClient = host.Services.GetRequiredService();
+
+ var uri = MongoUrl.Create(connectionString);
+
+ Assert.Equal(uri.Server.Host, mongoClient.Settings.Server.Host);
+ Assert.Equal(uri.Server.Port, mongoClient.Settings.Server.Port);
+
+ var mongoDatabase = host.Services.GetService();
+
+ if (shouldRegisterDatabase)
+ {
+ Assert.NotNull(mongoDatabase);
+ Assert.Equal(uri.DatabaseName, mongoDatabase.DatabaseNamespace.DatabaseName);
+ }
+ else
+ {
+ Assert.Null(mongoDatabase);
+ }
+ }
+
+ [Theory]
+ [InlineData("mongodb://localhost:27017/mydatabase", true)]
+ [InlineData("mongodb://localhost:27017", false)]
+ public void AddKeyedMongoDBDataSource_ReadsFromConnectionStringsCorrectly(string connectionString, bool shouldRegisterDatabase)
+ {
+ var key = DefaultConnectionName;
+
+ var builder = CreateBuilder(connectionString);
+
+ builder.AddKeyedMongoDBClient(key);
+
+ var host = builder.Build();
+
+ var mongoClient = host.Services.GetRequiredKeyedService(key);
+
+ var uri = MongoUrl.Create(connectionString);
+
+ Assert.Equal(uri.Server.Host, mongoClient.Settings.Server.Host);
+ Assert.Equal(uri.Server.Port, mongoClient.Settings.Server.Port);
+
+ var mongoDatabase = host.Services.GetKeyedService(key);
+
+ if (shouldRegisterDatabase)
+ {
+ Assert.NotNull(mongoDatabase);
+ Assert.Equal(uri.DatabaseName, mongoDatabase.DatabaseNamespace.DatabaseName);
+ }
+ else
+ {
+ Assert.Null(mongoDatabase);
+ }
+ }
+
+ [Fact]
+ public async Task AddMongoDBDataSource_HealthCheckShouldBeRegisteredWhenEnabled()
+ {
+ var builder = CreateBuilder(DefaultConnectionString);
+
+ builder.AddMongoDBClient(DefaultConnectionName, settings =>
+ {
+ settings.HealthChecks = true;
+ settings.HealthCheckTimeout = 1;
+ });
+
+ var host = builder.Build();
+
+ var healthCheckService = host.Services.GetRequiredService();
+
+ var healthCheckReport = await healthCheckService.CheckHealthAsync();
+
+ var healthCheckName = "MongoDB.Driver";
+
+ Assert.Contains(healthCheckReport.Entries, x => x.Key == healthCheckName);
+ }
+
+ [Fact]
+ public void AddKeyedMongoDBDataSource_HealthCheckShouldNotBeRegisteredWhenDisabled()
+ {
+ var builder = CreateBuilder(DefaultConnectionString);
+
+ builder.AddKeyedMongoDBClient(DefaultConnectionName, settings =>
+ {
+ settings.HealthChecks = false;
+ });
+
+ var host = builder.Build();
+
+ var healthCheckService = host.Services.GetService();
+
+ Assert.Null(healthCheckService);
+
+ }
+
+ [Fact]
+ public async Task AddKeyedMongoDBDataSource_HealthCheckShouldBeRegisteredWhenEnabled()
+ {
+ var key = DefaultConnectionName;
+
+ var builder = CreateBuilder(DefaultConnectionString);
+
+ builder.AddKeyedMongoDBClient(key, settings =>
+ {
+ settings.HealthChecks = true;
+ settings.HealthCheckTimeout = 1;
+ });
+
+ var host = builder.Build();
+
+ var healthCheckService = host.Services.GetRequiredService();
+
+ var healthCheckReport = await healthCheckService.CheckHealthAsync();
+
+ var healthCheckName = $"MongoDB.Driver_{key}";
+
+ Assert.Contains(healthCheckReport.Entries, x => x.Key == healthCheckName);
+ }
+
+ [Fact]
+ public void AddMongoDBDataSource_HealthCheckShouldNotBeRegisteredWhenDisabled()
+ {
+ var builder = CreateBuilder(DefaultConnectionString);
+
+ builder.AddMongoDBClient(DefaultConnectionName, settings =>
+ {
+ settings.HealthChecks = false;
+ });
+
+ var host = builder.Build();
+
+ var healthCheckService = host.Services.GetService();
+
+ Assert.Null(healthCheckService);
+ }
+
+ private static HostApplicationBuilder CreateBuilder(string connectionString)
+ {
+ var builder = Host.CreateEmptyApplicationBuilder(null);
+
+ builder.Configuration.AddInMemoryCollection([
+ new KeyValuePair($"ConnectionStrings:{DefaultConnectionName}", connectionString)
+ ]);
+ return builder;
+ }
+}
diff --git a/tests/Aspire.MongoDB.Driver.Tests/ConformanceTests.cs b/tests/Aspire.MongoDB.Driver.Tests/ConformanceTests.cs
new file mode 100644
index 00000000000..b816f42936e
--- /dev/null
+++ b/tests/Aspire.MongoDB.Driver.Tests/ConformanceTests.cs
@@ -0,0 +1,127 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Aspire.Components.ConformanceTests;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using MongoDB.Driver;
+using Xunit;
+
+namespace Aspire.MongoDB.Driver.Tests;
+
+public class ConformanceTests : ConformanceTests
+{
+ private const string ConnectionSting = "mongodb://root:password@localhost:27017/test_db";
+
+ private static readonly Lazy s_canConnectToServer = new(GetCanConnect);
+
+ protected override ServiceLifetime ServiceLifetime => ServiceLifetime.Singleton;
+
+ protected override string ActivitySourceName => "MongoDB.Driver.Core.Extensions.DiagnosticSources";
+
+ protected override string JsonSchemaPath => "src/Components/Aspire.MongoDB.Driver/ConfigurationSchema.json";
+
+ protected override bool SupportsKeyedRegistrations => true;
+
+ protected override bool CanConnectToServer => s_canConnectToServer.Value;
+
+ protected override string ValidJsonConfig => """
+ {
+ "Aspire": {
+ "MongoDB": {
+ "Driver": {
+ "ConnectionString": "YOUR_CONNECTION_STRING",
+ "HealthChecks": true,
+ "HealthCheckTimeout": 100,
+ "Tracing": true
+ }
+ }
+ }
+ }
+ """;
+
+ protected override (string json, string error)[] InvalidJsonToErrorMessage => new[]
+ {
+ ("""{"Aspire": { "MongoDB":{ "Driver": { "HealthChecks": "true"}}}}""", "Value is \"string\" but should be \"boolean\""),
+ ("""{"Aspire": { "MongoDB":{ "Driver": { "HealthCheckTimeout": "10000"}}}}""", "Value is \"string\" but should be \"integer\""),
+ ("""{"Aspire": { "MongoDB":{ "Driver": { "Tracing": "true"}}}}""", "Value is \"string\" but should be \"boolean\""),
+ };
+
+ protected override string[] RequiredLogCategories => [
+ "MongoDB.SDAM",
+ "MongoDB.ServerSelection",
+ "MongoDB.Connection",
+ ];
+
+ protected override void PopulateConfiguration(ConfigurationManager configuration, string? key = null)
+ => configuration.AddInMemoryCollection(new KeyValuePair[1]
+ {
+ new KeyValuePair(
+ CreateConfigKey("Aspire:MongoDB:Driver", key, "ConnectionString"),
+ ConnectionSting)
+ });
+
+ protected override void RegisterComponent(HostApplicationBuilder builder, Action? configure = null, string? key = null)
+ {
+ if (key is null)
+ {
+ builder.AddMongoDBClient("mongodb", configure);
+ }
+ else
+ {
+ builder.AddKeyedMongoDBClient(key, configure);
+ }
+ }
+
+ protected override void SetHealthCheck(MongoDBSettings options, bool enabled)
+ {
+ options.HealthChecks = enabled;
+ options.HealthCheckTimeout = 10;
+ }
+
+ protected override void SetMetrics(MongoDBSettings options, bool enabled) => throw new NotImplementedException();
+
+ protected override void SetTracing(MongoDBSettings options, bool enabled)
+ {
+ options.Tracing = enabled;
+ }
+
+ protected override void TriggerActivity(IMongoClient service)
+ {
+ using var source = new CancellationTokenSource(10);
+
+ service.ListDatabases(source.Token);
+ }
+
+ [Theory]
+ [InlineData(null)]
+ [InlineData("key")]
+ public void ClientAndDatabaseInstancesShouldBeResolved(string? key)
+ {
+ using IHost host = CreateHostWithComponent(key: key);
+
+ IMongoClient? mongoClient = Resolve();
+ IMongoDatabase? mongoDatabase = Resolve();
+
+ Assert.NotNull(mongoClient);
+ Assert.NotNull(mongoDatabase);
+
+ T? Resolve() => key is null ? host.Services.GetService() : host.Services.GetKeyedService(key);
+ }
+
+ private static bool GetCanConnect()
+ {
+ var client = new MongoClient(ConnectionSting);
+
+ try
+ {
+ client.ListDatabaseNames();
+ return true;
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+ }
+}
diff --git a/tests/testproject/TestProject.AppHost/TestProgram.cs b/tests/testproject/TestProject.AppHost/TestProgram.cs
index 158a6cd8c5d..4f47ab34b84 100644
--- a/tests/testproject/TestProject.AppHost/TestProgram.cs
+++ b/tests/testproject/TestProject.AppHost/TestProgram.cs
@@ -37,13 +37,15 @@ private TestProgram(string[] args, Assembly assembly, bool includeIntegrationSer
var redis = AppBuilder.AddRedisContainer("redis");
var postgres = AppBuilder.AddPostgresContainer("postgres");
var rabbitmq = AppBuilder.AddRabbitMQContainer("rabbitmq");
+ var mongodb = AppBuilder.AddMongoDBContainer("mongodb");
IntegrationServiceABuilder = AppBuilder.AddProject("integrationservicea")
.WithReference(sqlserver)
.WithReference(mysql)
.WithReference(redis)
.WithReference(postgres)
- .WithReference(rabbitmq);
+ .WithReference(rabbitmq)
+ .WithReference(mongodb);
}
}
diff --git a/tests/testproject/TestProject.IntegrationServiceA/Program.cs b/tests/testproject/TestProject.IntegrationServiceA/Program.cs
index a8a243cedb9..0448552746b 100644
--- a/tests/testproject/TestProject.IntegrationServiceA/Program.cs
+++ b/tests/testproject/TestProject.IntegrationServiceA/Program.cs
@@ -7,6 +7,7 @@
builder.AddRedis("redis");
builder.AddNpgsqlDataSource("postgres");
builder.AddRabbitMQ("rabbitmq");
+builder.AddMongoDBClient("mongodb");
var app = builder.Build();
diff --git a/tests/testproject/TestProject.IntegrationServiceA/TestProject.IntegrationServiceA.csproj b/tests/testproject/TestProject.IntegrationServiceA/TestProject.IntegrationServiceA.csproj
index 79dc6d40c41..45a3272abcc 100644
--- a/tests/testproject/TestProject.IntegrationServiceA/TestProject.IntegrationServiceA.csproj
+++ b/tests/testproject/TestProject.IntegrationServiceA/TestProject.IntegrationServiceA.csproj
@@ -1,14 +1,17 @@
-
+
net8.0
enable
enable
+
+ $(NoWarn);CS8002
+