dotnet / aspire

An opinionated, cloud ready stack for building observable, production ready, distributed applications in .NET
https://learn.microsoft.com/dotnet/aspire
MIT License
3.6k stars 397 forks source link

Add AppHost and ServiceDefaults project templates to support adoption #833

Closed Kralizek closed 7 months ago

Kralizek commented 9 months ago

For those who are not working on Visual Studio, a project template for creating the AppHost and ServiceDefaults projects would be beneficial in order to instrument existing solutions with Aspire.

DamianEdwards commented 9 months ago

That already exists. You can use dotnet new aspire to create a new solution with just AppHost and ServiceDefaults projects. Are you asking for individual templates for each of those project types? Note we do intend to add support to C# DevKit to add Aspire to an existing solution.

Kralizek commented 9 months ago

Are you asking for individual templates for each of those project types?

yes :)

DamianEdwards commented 9 months ago

Fair enough. So something like dotnet new aspire-apphost and dotnet new aspire-servicedefaults.

Kralizek commented 9 months ago

Yes. I understand it would be up to the developer to add the project references, but few dotnet add reference isn't too hard :)

What I did today was scaffold an empty solution (dotnet new aspire-empty) and then copy csproj and the content of program and extensions cs files.

DamianEdwards commented 9 months ago

@phenning could we do this with some more logic in the existing aspire empty solution template? e.g. what if simply didn't write out the .sln file if there was one in the directory already?

Kralizek commented 9 months ago

If that was the case, maybe the name of the template should be changed to favor discoverability.

People might not be inclined to run a dotnet new on an item called .NET Aspire Application in an application already existing.

DamianEdwards commented 9 months ago

Hmm, what if it was called .NET Aspire Empty Application?

Kralizek commented 9 months ago

A template with the word Application in its name gives me the idea of something that I will pour stuff into after creation rather than something that I add to an existing application.

phenning commented 9 months ago

@phenning could we do this with some more logic in the existing aspire empty solution template? e.g. what if simply didn't write out the .sln file if there was one in the directory already?

As a built in template engine feature, no, I don't think we can condition outputs based on the existence or non existence of files, especially by wildcard. I'm also not sure how this would work to do it automatically. Some developers may have multiple sln files in the same folder already in the location where the project is being located.

I could see being able to do this with additional template options that would work for the CLI.

--skip-solution-file (this would be hidden from Visual Studio options page, as it makes no sense)

--skip-apphost

--skip-servicedefaults

The trick here is that I'm not sure how we can handle the options here to only allow one to be chosen in Visual Studio. We could always hide all of the options in Visual Studio.

DamianEdwards commented 9 months ago

@phenning this is where I landed overnight too, adding a --skip-sln-file option for folks who want to add ServiceDefaults and AppHost projects to existing solutions from the command line. I think I prefer that instead of adding more templates like aspire-apphost and aspire-servicedefaults.

DamianEdwards commented 9 months ago

Putting this in preview.3

Kralizek commented 9 months ago

Just adding some meat on the grill.

I have a solution with a classic layout

- src
  - API
  - Web
- tests
  - API.Tests
  - Web.Tests
TestSln.sln

I want to add support to Aspire to this solution:

Try 1: in solution root with no parameters:

$ dotnet new aspire

dotnet new aspire
Creating this template will make changes to existing files:
  Overwrite   ./TestSln.sln

To create the template anyway, run the command with '--force' option:
   dotnet new aspire --force

For details on the exit code, refer to https://aka.ms/templating-exit-codes#73

Try 2: in solution root with --force

 dotnet new aspire --force
The template ".NET Aspire Application" was created successfully.
This template contains technologies from parties other than Microsoft, see https://aka.ms/aspire/1.0-third-party-notices for details.

Processing post-creation actions...
Restoring C:\Development\Tests\TestSln\TestSln.sln:
  Determining projects to restore...
  Restored C:\Development\Tests\TestSln\TestSln.AppHost\TestSln.AppHost.csproj (in 264 ms).
  Restored C:\Development\Tests\TestSln\TestSln.ServiceDefaults\TestSln.ServiceDefaults.csproj (in 260 ms).
Restore succeeded.
Restoring C:\Development\Tests\TestSln\TestSln.AppHost\TestSln.AppHost.csproj:
  Determining projects to restore...
  All projects are up-to-date for restore.
Restore succeeded.
Restoring C:\Development\Tests\TestSln\TestSln.ServiceDefaults\TestSln.ServiceDefaults.csproj:
  Determining projects to restore...
  All projects are up-to-date for restore.
Restore succeeded.

Outcome:

Try 3: in src directory with no parameters

$ dotnet new aspire
The template ".NET Aspire Application" was created successfully.
This template contains technologies from parties other than Microsoft, see https://aka.ms/aspire/1.0-third-party-notices for details.

Processing post-creation actions...
Restoring C:\Development\Tests\TestSln\src\src.sln:
  Determining projects to restore...
  Restored C:\Development\Tests\TestSln\src\src.AppHost\src.AppHost.csproj (in 260 ms).
  Restored C:\Development\Tests\TestSln\src\src.ServiceDefaults\src.ServiceDefaults.csproj (in 257 ms).
Restore succeeded.
Restoring C:\Development\Tests\TestSln\src\src.AppHost\src.AppHost.csproj:
  Determining projects to restore...
  All projects are up-to-date for restore.
Restore succeeded.
Restoring C:\Development\Tests\TestSln\src\src.ServiceDefaults\src.ServiceDefaults.csproj:
  Determining projects to restore...
  All projects are up-to-date for restore.
Restore succeeded.

Outcome:

Try 4: in solution root with -o parameter targeting "src"

$  dotnet new aspire -o .\src\ --dry-run
File actions would have been taken:
  Create: src\src.AppHost\Program.cs
  Create: src\src.AppHost\Properties\launchSettings.json
  Create: src\src.AppHost\appsettings.Development.json
  Create: src\src.AppHost\appsettings.json
  Create: src\src.AppHost\src.AppHost.csproj
  Create: src\src.ServiceDefaults\Extensions.cs
  Create: src\src.ServiceDefaults\src.ServiceDefaults.csproj
  Create: src\src.sln
This template contains technologies from parties other than Microsoft, see https://aka.ms/aspire/1.0-third-party-notices for details.

Processing post-creation actions...
Action would have been taken automatically:
   Restore NuGet packages required by this project.

Outcome: same as Try 3


Long story short:

The template as it is today cannot be used to instrument an existing application without doing a lot of manual work to either move projects in the correct directory and adjust the references/solution file or rename the projects and adjust the references.

Adding --skip-sln-file can improve the situation, but would still require some hand crafting.

$  dotnet new aspire -o src -n TestSln --dry-run --skin-sln-file
File actions would have been taken:
  Create: src\TestSln.AppHost\Program.cs
  Create: src\TestSln.AppHost\Properties\launchSettings.json
  Create: src\TestSln.AppHost\TestSln.AppHost.csproj
  Create: src\TestSln.AppHost\appsettings.Development.json
  Create: src\TestSln.AppHost\appsettings.json
  Create: src\TestSln.ServiceDefaults\Extensions.cs
  Create: src\TestSln.ServiceDefaults\TestSln.ServiceDefaults.csproj

This template contains technologies from parties other than Microsoft, see https://aka.ms/aspire/1.0-third-party-notices for details.

Processing post-creation actions...
Action would have been taken automatically:
   Restore NuGet packages required by this project.

$ dotnet sln add src\TestSln.AppHost
$ dotnet sln add src\TestSln.ServiceDefaults

Ideally, I'd love to have the possibility to avoid having a prefix to the projects, i.e. just AppHost and ServiceDefault.