Description
Background and Motivation
There are various scenarios where it's useful to be able to launch a project in the "normal way", outside of Aspire launching it, but still have that project be configured with the right Aspire settings in order to connect to Aspire services and the Aspire OpenTelemetry dashboard.
Scenarios include:
- MAUI and other .NET Mobile projects (e.g. Uno) where there may not be support initially for an integrated launch experience (Feature Request: .NET MAUI/mobile support 🌺 #4684)
- MAUI and other .NET Mobile projects (e.g. Uno) when there is support for an integrated launch experience, but users still want the ability to launch outside of Aspire to support the typical inner loop scenario here https://twitter.com/GFlisch4u/status/1811635668327539021, just restarting MAUI app via Shift-F5 / F5 in VS
- Test scenarios, where the .NET Android/iOS app is launched by Appium, xharness, or BrowserStack but still wants to talk the Aspire services for to run the UI tests - these technologies all expect to launch the app themselves, not have AppHost launch the app
- Other client apps that are launched by some other program, a service, with custom CLI args from the command line, etc.
- Web apps where the user wishes to set the web app as the startup project and still have that work
This API meets that need, by allowing the settings, normally passed via environment variables, to optionally be written to a settings file (e.g. a JSON file). Writing the settings file can happen in addition to building/launching the project normally, allowing both Aspire integrated and standalone startup to work, or it be the only option, with Aspire configured to not build/launch the project, just generate settings. The API here supports both use cases.
Proposed API
namespace Aspire.Hosting;
public static class ProjectResourceBuilderExtensions
{
+ /// <summary>
+ /// Adds a settings file to the project resource, to optionally persist settings that are normally set via environment variables.
+ /// The settings file can be generated with or without also launching the project.
+ /// </summary>
+ /// <param name="builder">The <see cref="IDistributedApplicationBuilder"/>.</param>
+ /// <param name="settingsFilePath">The path to settings file, absolute or relative to app host directory.</param>
+ /// <param name="settingsFileType">The settings file type, C# code (for use with IConfigurationBuilder.AddInMemoryCollection) or JSON (for use with IConfigurationBuilder.AddJsonFile).</param>
+ /// <param name="onlyGenerateSettings">Indicate whether to skip build/running this resource, only generating settings.</param>
+ public static IResourceBuilder<ProjectResource> WithSettingsFile(this IResourceBuilder<ProjectResource> builder, string settingsFilePath, SettingsFileType settingsFileType, bool onlyGenerateSettings)
+ /// <summary>
+ /// Adds a settings file to the project resource, to optionally persist settings that are normally set via environment variables.
+ /// The settings file can be generated with or without also launching the project.
+ /// </summary>
+ /// <param name="builder">The <see cref="IDistributedApplicationBuilder"/>.</param>
+ /// <param name="settingsFileOptions">The options to use for settings file generation.</param>
+ /// <returns></returns>
+ public static IResourceBuilder<ProjectResource> WithSettingsFile(this IResourceBuilder<ProjectResource> builder, SettingsFileOptions settingsFileOptions)
+ /// <summary>
+ /// Adds a .NET project to the application model, just generating a settings file for the project.
+ /// </summary>
+ /// <param name="builder">The <see cref="IDistributedApplicationBuilder"/>.</param>
+ /// <param name="name">The name of the resource. This name will be used for service discovery when referenced in a dependency.</param>
+ /// <returns>A reference to the <see cref="IResourceBuilder{T}"/>.</returns>
+ /// <remarks>
+ /// <para>
+ /// This overload of the <see cref="AddProject(IDistributedApplicationBuilder, string, string)"/> method adds a project to the application
+ /// model where Aspire only generates a settings file for the project, not otherwise trying to build or run it. This is useful for projects
+ /// that you wish to always launch manually, but have them connect to Aspire services and OTEL.
+ /// </para>
+ public static IResourceBuilder<ProjectResource> AddSettingsOnlyProject(this IDistributedApplicationBuilder builder, string name,
+ string settingsFilePath, SettingsFileType settingsFileType)
}
A draft PR implementing this API is here: #5016.
Usage Examples
builder.AddProject<Projects.MyFrontend>("mywebapp")
.WithSettingsFile("..\\MyWebApp\\obj\\appsettingsAspire.g.json", SettingsFileType.Json, onlyGenerateSettings: false)
.WithExternalHttpEndpoints()
.WithReference(basketService)
.WithReference(catalogService);
builder.AddSettingsOnlyProject("mymauiapp", "..\\MyMauiApp\\obj\\appsettingsAspire.g.cs", SettingsFileType.CSharp)
.WithExternalHttpEndpoints()
.WithReference(basketService)
.WithReference(catalogService);
Alternative Designs
Initially, I considered having a separate project type for projects that generate settings. But allowing settings to optionally be generated for any .NET project, via a settings file IResourceAnnotation
, allows more flexibility and emphasizes this is optional functionality in addition to integrated launch. Plus it required less changes to add. It seems like a nicer design all around.