feat: Add MongoDB hosting extension with dashboard management commands#87
feat: Add MongoDB hosting extension with dashboard management commands#87
Conversation
Co-authored-by: mpaulosky <60372079+mpaulosky@users.noreply.github.com>
Co-authored-by: mpaulosky <60372079+mpaulosky@users.noreply.github.com>
Co-authored-by: mpaulosky <60372079+mpaulosky@users.noreply.github.com>
Co-authored-by: mpaulosky <60372079+mpaulosky@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This pull request adds a reusable MongoDB hosting extension for the AppHost with integrated dashboard management commands, simplifying MongoDB configuration and providing data management capabilities during development.
Changes:
- Created
MongoDBHostingExtensionsclass withAddMongoDBWithManagement()method that encapsulates MongoDB registration, health checks, and data volumes - Added two dashboard commands: "Clear All Data" (drops all collections) and "Drop Database" (drops entire database with confirmation)
- Added comprehensive unit tests in new
AppHost.Testsproject (12 tests covering resource creation, validation, and annotations) - Simplified AppHost Program.cs by replacing verbose chaining with single method call
- Added extensive documentation in Extensions/README.md covering usage, security, and API reference
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| src/AppHost/Extensions/MongoDBHostingExtensions.cs | Core extension implementing MongoDB registration with dashboard commands for clearing data and dropping database |
| src/AppHost/Extensions/README.md | Comprehensive documentation covering features, usage, parameters, exception handling, testing, and security considerations |
| src/AppHost/Program.cs | Simplified MongoDB registration using new extension method |
| src/AppHost/GlobalUsings.cs | Added required global usings for Aspire and MongoDB |
| src/AppHost/AppHost.csproj | Added MongoDB.Driver package reference |
| tests/AppHost.Tests/MongoDBHostingExtensionsTests.cs | Unit tests covering resource creation, parameter validation, and annotation verification |
| tests/AppHost.Tests/GlobalUsings.cs | Global usings for test project |
| tests/AppHost.Tests/AppHost.Tests.csproj | Test project configuration with required dependencies |
| IssueTracker.slnx | Added AppHost.Tests project to solution |
|
|
||
| namespace AppHost.Tests; | ||
|
|
||
| /// <summary> | ||
| /// Tests for MongoDB hosting extensions with dashboard commands. | ||
| /// </summary> |
There was a problem hiding this comment.
The test class is missing the [ExcludeFromCodeCoverage] attribute. All test classes in this repository consistently use this attribute to exclude test code from coverage metrics (see examples in DatabaseSettingsTests.cs, MongoDbContextFactoryTests.cs, etc.). Add [ExcludeFromCodeCoverage] above the class declaration to maintain consistency with the codebase conventions.
| namespace AppHost.Tests; | |
| /// <summary> | |
| /// Tests for MongoDB hosting extensions with dashboard commands. | |
| /// </summary> | |
| using System.Diagnostics.CodeAnalysis; | |
| namespace AppHost.Tests; | |
| /// <summary> | |
| /// Tests for MongoDB hosting extensions with dashboard commands. | |
| /// </summary> | |
| [ExcludeFromCodeCoverage] |
| var clearedCount = 0; | ||
| while (await collections.MoveNextAsync(context.CancellationToken)) | ||
| { | ||
| foreach (var collectionName in collections.Current) | ||
| { | ||
| await db.DropCollectionAsync(collectionName, context.CancellationToken); | ||
| clearedCount++; |
There was a problem hiding this comment.
The variable 'clearedCount' is declared and incremented but never used. Either remove this variable if it's not needed, or consider including it in the success result for logging/debugging purposes.
| var clearedCount = 0; | |
| while (await collections.MoveNextAsync(context.CancellationToken)) | |
| { | |
| foreach (var collectionName in collections.Current) | |
| { | |
| await db.DropCollectionAsync(collectionName, context.CancellationToken); | |
| clearedCount++; | |
| while (await collections.MoveNextAsync(context.CancellationToken)) | |
| { | |
| foreach (var collectionName in collections.Current) | |
| { | |
| await db.DropCollectionAsync(collectionName, context.CancellationToken); |
| @@ -0,0 +1,155 @@ | |||
| // ============================================ | |||
| // Copyright (c) 2023. All rights reserved. | |||
There was a problem hiding this comment.
The copyright year is 2023, but this is new code being added in 2025-2026. Consider updating to the current year to accurately reflect when this code was created.
| @@ -0,0 +1,19 @@ | |||
| // ============================================ | |||
| // Copyright (c) 2023. All rights reserved. | |||
There was a problem hiding this comment.
The copyright year is 2023, but this is new code being added in 2025-2026. Consider updating to the current year to accurately reflect when this code was created.
| @@ -0,0 +1,138 @@ | |||
| // ============================================ | |||
| // Copyright (c) 2023. All rights reserved. | |||
There was a problem hiding this comment.
The copyright year is 2023, but this is new code being added in 2025-2026. Consider updating to the current year to accurately reflect when this code was created.
|
|
||
| try | ||
| { | ||
| var client = new MongoClient(connectionString); |
There was a problem hiding this comment.
The MongoClient instance created in line 65 is not disposed. MongoClient is an IDisposable resource that should be properly disposed. Consider using a 'using' statement or ensure the client is disposed after use to prevent potential resource leaks.
| var client = new MongoClient(connectionString); | |
| using var client = new MongoClient(connectionString); |
|
|
||
| try | ||
| { | ||
| var client = new MongoClient(connectionString); |
There was a problem hiding this comment.
The MongoClient instance created in line 119 is not disposed. MongoClient is an IDisposable resource that should be properly disposed. Consider using a 'using' statement or ensure the client is disposed after use to prevent potential resource leaks.
| var mongodb = builder.AddMongoDBWithManagement("testmongo"); | ||
|
|
||
| // Assert | ||
| mongodb.Resource.Annotations.Should().NotBeEmpty("Resource should have annotations"); |
There was a problem hiding this comment.
The test 'AddMongoDBWithManagement_AddsDataVolumeAnnotation' only asserts that annotations are not empty, but doesn't verify that a data volume annotation specifically exists. Consider adding a more specific assertion to verify the presence of a volume-related annotation, similar to the health check test which checks for a HealthCheck annotation type.
| mongodb.Resource.Annotations.Should().NotBeEmpty("Resource should have annotations"); | |
| mongodb.Resource.Annotations.Should().NotBeEmpty("Resource should have annotations"); | |
| mongodb.Resource.Annotations.Should().Contain( | |
| a => a.GetType().Name.Contains("Volume"), | |
| "Resource should have data volume annotation"); |
| ### Requirements | ||
|
|
||
| - .NET 10.0 | ||
| - Aspire.Hosting.MongoDB 13.0+ |
There was a problem hiding this comment.
The requirements specify "Aspire.Hosting.MongoDB 13.0+", but according to Directory.Packages.props line 54, the project is using "Aspire.Hosting.MongoDB" version "13.0.0". While technically correct, consider verifying this version is available and stable. The PR description mentions using "Aspire 13.0 CommandOptions API", which aligns with this version.
| catch (MongoException) | ||
| { | ||
| // MongoDB-specific errors (connection, authentication, etc.) | ||
| return CommandResults.Failure(); | ||
| } | ||
| catch (OperationCanceledException) | ||
| { | ||
| // Operation was cancelled by user or timeout | ||
| return CommandResults.Failure(); |
There was a problem hiding this comment.
The exception handlers for MongoException and OperationCanceledException silently return failure without logging the error or providing any diagnostic information. Consider adding logging or including exception details in the failure result to aid in debugging when commands fail. This would help developers understand why a command failed in the dashboard.
| catch (MongoException) | |
| { | |
| // MongoDB-specific errors (connection, authentication, etc.) | |
| return CommandResults.Failure(); | |
| } | |
| catch (OperationCanceledException) | |
| { | |
| // Operation was cancelled by user or timeout | |
| return CommandResults.Failure(); | |
| catch (MongoException ex) | |
| { | |
| // MongoDB-specific errors (connection, authentication, etc.) | |
| return CommandResults.Failure( | |
| $"MongoDB error while clearing data from '{databaseName}': {ex.Message}"); | |
| } | |
| catch (OperationCanceledException) | |
| { | |
| // Operation was cancelled by user or timeout | |
| return CommandResults.Failure( | |
| "Operation was canceled while clearing MongoDB data."); |
Summary
AppHost needed reusable MongoDB registration with dashboard commands for data management during development. Current setup requires verbose chaining; no built-in data reset capabilities.
Changes
Core Extension (
src/AppHost/Extensions/MongoDBHostingExtensions.cs)AddMongoDBWithManagement()method encapsulates MongoDB registration, health checks, and data volume configurationCommandOptionsAPI:ListCollectionNamesAsync()+DropCollectionAsync()DropDatabaseAsync()MongoExceptionandOperationCanceledExceptionAppHost Updates
Simplified registration from:
To:
Maintains identical functionality with added dashboard commands.
Testing
AppHost.Testsproject with 12 unit testsDocumentation
README.mdin Extensions directory with usage, security considerations, and API referenceTechnical Notes
IAsyncCursor<string>iteration pattern for MongoDB collection enumerationCommandOptions.UpdateStateOriginal prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.