
Project Setup
- 20 installs
- 466 repo stars
- Updated July 25, 2026
- managedcode/dotnet-skills
Helps with ai & agent building tasks.
About
project-setup is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- project-setup
- AI & Agent Building
- AI-coding skill
Project Setup by the numbers
- 20 all-time installs (skills.sh)
- +1 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #10,442 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/managedcode/dotnet-skills --skill project-setupAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 20 |
|---|---|
| repo stars | ★ 466 |
| Last updated | July 25, 2026 |
| Repository | managedcode/dotnet-skills ↗ |
What it does
Helps with ai & agent building tasks.
Files
.NET Project Setup
Trigger On
- creating a new .NET solution or restructuring an existing one
- setting up
Directory.Build.props, shared package management, or repo-wide defaults - defining project layout for apps, libraries, and test projects
Workflow
1. Start from the app model and deployment target, then choose the smallest correct SDK and target framework set. 2. Use solution folders and project names that reflect bounded contexts or product areas, not temporary implementation details. 3. Centralize shared build settings, analyzer rules, nullable context, and package versions where it reduces duplication without hiding important differences. 4. Create test projects and CI hooks early so new projects do not drift into unverified templates. 5. Prefer project references and composition over circular dependencies or utility dumping grounds. 6. Document the local build, test, and run path in repo docs or AGENTS.md when the workflow is not obvious.
Current Upstream Notes
- The current "Build apps with .NET" Learn page reinforces app-model-first setup: console, web, worker, desktop, mobile, cloud, and AI entry points should drive SDK/template choice.
.NET SDK 8.0.422is servicing for the 8.0 line. Keepglobal.jsonand CI images explicit when a repo needs that line instead of relying on a newer local SDK.
Deliver
- a coherent solution structure
- shared build defaults that are easy to reason about
- starter quality and testing hooks for future work
Validate
- projects have explicit responsibility boundaries
- shared MSBuild settings do not accidentally override platform-specific needs
- a new contributor can build and test the repo without guessing
References
- patterns.md: solution layout conventions,
Directory.Build.props,Directory.Build.targets, Central Package Management,global.json,nuget.config, analyzers, multi-targeting, and source link - templates.md:
dotnet newtemplates for console apps, class libraries, ASP.NET Core APIs, worker services, Blazor, test projects, .NET Aspire, and gRPC services
{
"version": "1.0.1",
"category": "Core"
}
Project Structure Patterns
Solution Layout
Recommended Directory Structure
<repo-root>/
├── .config/
│ └── dotnet-tools.json
├── src/
│ ├── <ProductName>.Core/
│ ├── <ProductName>.Api/
│ └── <ProductName>.Web/
├── tests/
│ ├── <ProductName>.Core.Tests/
│ └── <ProductName>.Api.Tests/
├── samples/
│ └── <ProductName>.Sample/
├── docs/
├── Directory.Build.props
├── Directory.Build.targets
├── Directory.Packages.props
├── global.json
├── nuget.config
├── <SolutionName>.sln
└── README.mdProject Naming Conventions
| Project Type | Pattern | Example |
|---|---|---|
| Core library | <ProductName>.Core | Contoso.Orders.Core |
| Domain layer | <ProductName>.Domain | Contoso.Orders.Domain |
| Application layer | <ProductName>.Application | Contoso.Orders.Application |
| Infrastructure | <ProductName>.Infrastructure | Contoso.Orders.Infrastructure |
| Web API | <ProductName>.Api | Contoso.Orders.Api |
| Web frontend | <ProductName>.Web | Contoso.Orders.Web |
| Worker service | <ProductName>.Worker | Contoso.Orders.Worker |
| Unit tests | <ProjectName>.Tests | Contoso.Orders.Core.Tests |
| Integration tests | <ProjectName>.IntegrationTests | Contoso.Orders.Api.IntegrationTests |
---
Directory.Build.props
Directory.Build.props is automatically imported by MSBuild for all projects in its directory and subdirectories.
Basic Template
<Project>
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsAsErrors />
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<AnalysisLevel>latest-recommended</AnalysisLevel>
</PropertyGroup>
<!-- Package metadata for libraries -->
<PropertyGroup>
<Authors>Your Name or Organization</Authors>
<Company>Your Company</Company>
<Copyright>Copyright (c) $(Company) $([System.DateTime]::Now.Year)</Copyright>
<RepositoryUrl>https://github.com/your-org/your-repo</RepositoryUrl>
<RepositoryType>git</RepositoryType>
</PropertyGroup>
<!-- Deterministic builds for CI -->
<PropertyGroup Condition="'$(CI)' == 'true'">
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
<Deterministic>true</Deterministic>
</PropertyGroup>
</Project>Conditional Properties by Project Type
<Project>
<!-- Shared defaults -->
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<!-- Test project defaults -->
<PropertyGroup Condition="$(MSBuildProjectName.EndsWith('.Tests'))">
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<!-- Library defaults -->
<PropertyGroup Condition="!$(MSBuildProjectName.EndsWith('.Tests')) AND !$(MSBuildProjectName.EndsWith('.Api')) AND !$(MSBuildProjectName.EndsWith('.Web'))">
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
</Project>Nested Directory.Build.props
Child directories can extend the parent by importing it explicitly:
<!-- tests/Directory.Build.props -->
<Project>
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />
<PropertyGroup>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio" />
<PackageReference Include="coverlet.collector" />
</ItemGroup>
</Project>---
Directory.Build.targets
Use Directory.Build.targets for logic that runs after the project file is fully evaluated.
<Project>
<!-- Run after project evaluation -->
<Target Name="PrintBuildInfo" BeforeTargets="Build">
<Message Importance="High" Text="Building $(MSBuildProjectName) for $(TargetFramework)" />
</Target>
<!-- Enforce test naming convention -->
<Target Name="ValidateTestProjectNaming" BeforeTargets="Build" Condition="'$(IsTestProject)' == 'true'">
<Error Condition="!$(MSBuildProjectName.EndsWith('.Tests')) AND !$(MSBuildProjectName.EndsWith('.IntegrationTests'))"
Text="Test projects must end with .Tests or .IntegrationTests" />
</Target>
</Project>---
Central Package Management (CPM)
Central Package Management consolidates package versions into a single Directory.Packages.props file.
Enabling CPM
Add to Directory.Packages.props at the repository root:
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
</PropertyGroup>
<ItemGroup>
<!-- Runtime packages -->
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.0" />
<PackageVersion Include="System.Text.Json" Version="9.0.0" />
<!-- Entity Framework Core -->
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.0" />
<!-- ASP.NET Core extras -->
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.6.2" />
<!-- Testing -->
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageVersion Include="xunit" Version="2.9.2" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
<PackageVersion Include="Moq" Version="4.20.72" />
<PackageVersion Include="FluentAssertions" Version="6.12.1" />
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
<!-- Analyzers -->
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
<PackageVersion Include="Roslynator.Analyzers" Version="4.12.6" />
</ItemGroup>
</Project>Project File References with CPM
When CPM is enabled, project files reference packages without versions:
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" />
<PackageReference Include="Microsoft.Extensions.Logging" />
</ItemGroup>Version Overrides
Use VersionOverride sparingly when a project requires a different version:
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" VersionOverride="13.0.3" />
</ItemGroup>---
global.json
Pin the SDK version for reproducible builds:
{
"sdk": {
"version": "9.0.100",
"rollForward": "latestFeature",
"allowPrerelease": false
}
}Roll-Forward Policies
| Value | Behavior |
|---|---|
patch | Use specified or highest installed patch |
feature | Use specified or highest installed feature band |
minor | Use specified or highest installed minor |
major | Use highest installed SDK |
latestPatch | Use highest installed patch |
latestFeature | Use highest installed feature band |
latestMinor | Use highest installed minor |
latestMajor | Use highest installed SDK |
disable | Exact match only |
---
nuget.config
Configure package sources and credentials:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
<!-- Private feeds -->
<add key="github" value="https://nuget.pkg.github.com/your-org/index.json" />
</packageSources>
<packageSourceMapping>
<packageSource key="nuget.org">
<package pattern="*" />
</packageSource>
<packageSource key="github">
<package pattern="YourOrg.*" />
</packageSource>
</packageSourceMapping>
<!-- CI credentials via environment variables -->
<packageSourceCredentials>
<github>
<add key="Username" value="%NUGET_USERNAME%" />
<add key="ClearTextPassword" value="%NUGET_TOKEN%" />
</github>
</packageSourceCredentials>
</configuration>---
Analyzers and Code Style
.editorconfig Basics
root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true
[*.{cs,vb}]
dotnet_sort_system_directives_first = true
dotnet_separate_import_directive_groups = false
[*.cs]
csharp_style_namespace_declarations = file_scoped:warning
csharp_style_var_for_built_in_types = true:suggestion
csharp_style_var_when_type_is_apparent = true:suggestion
csharp_style_var_elsewhere = true:suggestion
csharp_prefer_braces = true:warning
csharp_style_expression_bodied_methods = when_on_single_line:suggestion
csharp_style_expression_bodied_constructors = false:suggestion
# IDE diagnostics
dotnet_diagnostic.IDE0005.severity = warning
dotnet_diagnostic.IDE0055.severity = warning
[*.{json,yml,yaml}]
indent_size = 2Analyzer Packages in Directory.Build.props
<ItemGroup>
<PackageReference Include="StyleCop.Analyzers" PrivateAssets="all" />
<PackageReference Include="Roslynator.Analyzers" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" PrivateAssets="all" />
</ItemGroup>---
Multi-Targeting
Single Project Multi-Targeting
<PropertyGroup>
<TargetFrameworks>net9.0;net8.0;netstandard2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="System.Text.Json" />
</ItemGroup>Conditional Compilation
#if NET9_0_OR_GREATER
// .NET 9+ specific code
ArgumentNullException.ThrowIfNull(value);
#else
// Fallback for older frameworks
if (value is null)
throw new ArgumentNullException(nameof(value));
#endif---
Source Link and Deterministic Builds
Enable source link for debugger integration:
<PropertyGroup>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="all" />
</ItemGroup>---
Solution Filters
Create .slnf files for partial solution loading:
{
"solution": {
"path": "MyProduct.sln",
"projects": [
"src\\MyProduct.Core\\MyProduct.Core.csproj",
"src\\MyProduct.Api\\MyProduct.Api.csproj",
"tests\\MyProduct.Core.Tests\\MyProduct.Core.Tests.csproj"
]
}
}Open with: dotnet sln open MyProduct.Api.slnf
Common Project Templates
Overview
.NET provides project templates via dotnet new. This reference covers common templates and their typical use cases.
---
Listing Available Templates
# List all installed templates
dotnet new list
# Search for templates
dotnet new search webapi
# Install a template pack
dotnet new install Microsoft.AspNetCore.SpaTemplates---
Console Applications
Basic Console App
dotnet new console -n MyApp -o src/MyAppGenerated structure:
src/MyApp/
├── MyApp.csproj
└── Program.csTypical `Program.cs`:
// Minimal hosting for console apps with DI
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddSingleton<MyService>();
using var host = builder.Build();
await host.RunAsync();---
Class Libraries
Standard Library
dotnet new classlib -n MyProduct.Core -o src/MyProduct.CoreLibrary with Multi-Targeting
Modify the generated `.csproj`:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net9.0;net8.0;netstandard2.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageId>MyCompany.MyProduct.Core</PackageId>
<Description>Core library for MyProduct</Description>
</PropertyGroup>
</Project>---
ASP.NET Core Web API
Minimal API
dotnet new webapi -n MyProduct.Api -o src/MyProduct.Api --use-minimal-apisTypical structure:
src/MyProduct.Api/
├── MyProduct.Api.csproj
├── Program.cs
├── Properties/
│ └── launchSettings.json
├── appsettings.json
└── appsettings.Development.jsonMinimal API `Program.cs` example:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.MapGet("/api/health", () => Results.Ok(new { Status = "Healthy" }))
.WithName("HealthCheck")
.WithOpenApi();
app.Run();Controller-Based API
dotnet new webapi -n MyProduct.Api -o src/MyProduct.Api --use-controllersController template:
using Microsoft.AspNetCore.Mvc;
namespace MyProduct.Api.Controllers;
[ApiController]
[Route("api/[controller]")]
public class ItemsController : ControllerBase
{
private readonly IItemService _itemService;
public ItemsController(IItemService itemService)
{
_itemService = itemService;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<ItemDto>>> GetAll(CancellationToken ct)
{
var items = await _itemService.GetAllAsync(ct);
return Ok(items);
}
[HttpGet("{id:guid}")]
public async Task<ActionResult<ItemDto>> GetById(Guid id, CancellationToken ct)
{
var item = await _itemService.GetByIdAsync(id, ct);
return item is null ? NotFound() : Ok(item);
}
[HttpPost]
public async Task<ActionResult<ItemDto>> Create(CreateItemRequest request, CancellationToken ct)
{
var item = await _itemService.CreateAsync(request, ct);
return CreatedAtAction(nameof(GetById), new { id = item.Id }, item);
}
}---
Worker Services
Background Service
dotnet new worker -n MyProduct.Worker -o src/MyProduct.WorkerWorker template:
namespace MyProduct.Worker;
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
private readonly IServiceScopeFactory _scopeFactory;
public Worker(ILogger<Worker> logger, IServiceScopeFactory scopeFactory)
{
_logger = logger;
_scopeFactory = scopeFactory;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("Worker running at: {Time}", DateTimeOffset.Now);
using var scope = _scopeFactory.CreateScope();
var service = scope.ServiceProvider.GetRequiredService<IMyService>();
await service.ProcessAsync(stoppingToken);
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
}
}
}---
Web Applications
Blazor Server
dotnet new blazor -n MyProduct.Web -o src/MyProduct.Web --interactivity ServerBlazor WebAssembly
dotnet new blazor -n MyProduct.Web -o src/MyProduct.Web --interactivity WebAssemblyRazor Pages
dotnet new webapp -n MyProduct.Web -o src/MyProduct.Web---
Test Projects
xUnit Test Project
dotnet new xunit -n MyProduct.Core.Tests -o tests/MyProduct.Core.TestsTest project `.csproj`:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio" />
<PackageReference Include="coverlet.collector" />
<PackageReference Include="FluentAssertions" />
<PackageReference Include="Moq" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\MyProduct.Core\MyProduct.Core.csproj" />
</ItemGroup>
</Project>Test class template:
using FluentAssertions;
using Moq;
using Xunit;
namespace MyProduct.Core.Tests;
public class ItemServiceTests
{
private readonly Mock<IItemRepository> _repositoryMock;
private readonly ItemService _sut;
public ItemServiceTests()
{
_repositoryMock = new Mock<IItemRepository>();
_sut = new ItemService(_repositoryMock.Object);
}
[Fact]
public async Task GetByIdAsync_WhenItemExists_ReturnsItem()
{
// Arrange
var itemId = Guid.NewGuid();
var expected = new Item { Id = itemId, Name = "Test" };
_repositoryMock
.Setup(r => r.GetByIdAsync(itemId, It.IsAny<CancellationToken>()))
.ReturnsAsync(expected);
// Act
var result = await _sut.GetByIdAsync(itemId, CancellationToken.None);
// Assert
result.Should().BeEquivalentTo(expected);
}
[Theory]
[InlineData("")]
[InlineData(" ")]
[InlineData(null)]
public async Task CreateAsync_WhenNameInvalid_ThrowsArgumentException(string? name)
{
// Arrange
var request = new CreateItemRequest { Name = name! };
// Act
var act = () => _sut.CreateAsync(request, CancellationToken.None);
// Assert
await act.Should().ThrowAsync<ArgumentException>();
}
}NUnit Test Project
dotnet new nunit -n MyProduct.Core.Tests -o tests/MyProduct.Core.TestsMSTest Test Project
dotnet new mstest -n MyProduct.Core.Tests -o tests/MyProduct.Core.TestsIntegration Test Project
// WebApplicationFactory-based integration tests
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
namespace MyProduct.Api.IntegrationTests;
public class ItemsEndpointTests : IClassFixture<WebApplicationFactory<Program>>
{
private readonly HttpClient _client;
public ItemsEndpointTests(WebApplicationFactory<Program> factory)
{
_client = factory
.WithWebHostBuilder(builder =>
{
builder.ConfigureServices(services =>
{
// Replace services for testing
services.AddSingleton<IItemRepository, InMemoryItemRepository>();
});
})
.CreateClient();
}
[Fact]
public async Task GetAll_ReturnsOkStatus()
{
// Act
var response = await _client.GetAsync("/api/items");
// Assert
response.EnsureSuccessStatusCode();
}
}---
Solution Setup Commands
Create Solution and Projects
# Create solution
dotnet new sln -n MyProduct
# Create projects
dotnet new classlib -n MyProduct.Core -o src/MyProduct.Core
dotnet new classlib -n MyProduct.Infrastructure -o src/MyProduct.Infrastructure
dotnet new webapi -n MyProduct.Api -o src/MyProduct.Api --use-minimal-apis
dotnet new xunit -n MyProduct.Core.Tests -o tests/MyProduct.Core.Tests
dotnet new xunit -n MyProduct.Api.IntegrationTests -o tests/MyProduct.Api.IntegrationTests
# Add projects to solution
dotnet sln add src/MyProduct.Core/MyProduct.Core.csproj
dotnet sln add src/MyProduct.Infrastructure/MyProduct.Infrastructure.csproj
dotnet sln add src/MyProduct.Api/MyProduct.Api.csproj
dotnet sln add tests/MyProduct.Core.Tests/MyProduct.Core.Tests.csproj
dotnet sln add tests/MyProduct.Api.IntegrationTests/MyProduct.Api.IntegrationTests.csproj
# Add project references
dotnet add src/MyProduct.Infrastructure/MyProduct.Infrastructure.csproj reference src/MyProduct.Core/MyProduct.Core.csproj
dotnet add src/MyProduct.Api/MyProduct.Api.csproj reference src/MyProduct.Core/MyProduct.Core.csproj
dotnet add src/MyProduct.Api/MyProduct.Api.csproj reference src/MyProduct.Infrastructure/MyProduct.Infrastructure.csproj
dotnet add tests/MyProduct.Core.Tests/MyProduct.Core.Tests.csproj reference src/MyProduct.Core/MyProduct.Core.csproj
dotnet add tests/MyProduct.Api.IntegrationTests/MyProduct.Api.IntegrationTests.csproj reference src/MyProduct.Api/MyProduct.Api.csproj---
.NET Aspire Application
Aspire App Host
dotnet new aspire -n MyProductCreates:
MyProduct/
├── MyProduct.AppHost/
│ ├── MyProduct.AppHost.csproj
│ └── Program.cs
├── MyProduct.ServiceDefaults/
│ ├── MyProduct.ServiceDefaults.csproj
│ └── Extensions.cs
└── MyProduct.slnAppHost `Program.cs`:
var builder = DistributedApplication.CreateBuilder(args);
var cache = builder.AddRedis("cache");
var postgres = builder.AddPostgres("postgres")
.AddDatabase("ordersdb");
var api = builder.AddProject<Projects.MyProduct_Api>("api")
.WithReference(cache)
.WithReference(postgres);
builder.AddProject<Projects.MyProduct_Web>("web")
.WithReference(api);
builder.Build().Run();Add Service to Existing Aspire Solution
# Add a new API project
dotnet new webapi -n MyProduct.OrdersApi -o src/MyProduct.OrdersApi
dotnet sln add src/MyProduct.OrdersApi/MyProduct.OrdersApi.csproj
# Reference ServiceDefaults
dotnet add src/MyProduct.OrdersApi/MyProduct.OrdersApi.csproj reference src/MyProduct.ServiceDefaults/MyProduct.ServiceDefaults.csproj---
gRPC Services
dotnet new grpc -n MyProduct.GrpcService -o src/MyProduct.GrpcServiceProto file template:
syntax = "proto3";
option csharp_namespace = "MyProduct.GrpcService";
package orders;
service OrderService {
rpc GetOrder (GetOrderRequest) returns (OrderResponse);
rpc CreateOrder (CreateOrderRequest) returns (OrderResponse);
rpc ListOrders (ListOrdersRequest) returns (stream OrderResponse);
}
message GetOrderRequest {
string order_id = 1;
}
message CreateOrderRequest {
string customer_id = 1;
repeated OrderItem items = 2;
}
message OrderItem {
string product_id = 1;
int32 quantity = 2;
}
message OrderResponse {
string order_id = 1;
string customer_id = 2;
repeated OrderItem items = 3;
string status = 4;
}
message ListOrdersRequest {
string customer_id = 1;
}---
Tool Manifest
Create Tool Manifest
dotnet new tool-manifestCreates `.config/dotnet-tools.json`:
{
"version": 1,
"isRoot": true,
"tools": {}
}Install Local Tools
dotnet tool install dotnet-ef
dotnet tool install format
dotnet tool install dotnet-reportgenerator-globaltoolUpdated manifest:
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "9.0.0",
"commands": ["dotnet-ef"]
},
"format": {
"version": "5.1.250801",
"commands": ["format"]
},
"dotnet-reportgenerator-globaltool": {
"version": "5.3.10",
"commands": ["reportgenerator"]
}
}
}Restore Tools
dotnet tool restore---
Quick Reference: Common Template Options
| Template | Command | Key Options |
|---|---|---|
| Console | dotnet new console | --use-program-main |
| Class Library | dotnet new classlib | --framework |
| Web API | dotnet new webapi | --use-controllers, --use-minimal-apis, --auth |
| Blazor | dotnet new blazor | --interactivity, --empty |
| Worker | dotnet new worker | --framework |
| xUnit | dotnet new xunit | --framework |
| Solution | dotnet new sln | - |
| gitignore | dotnet new gitignore | - |
| editorconfig | dotnet new editorconfig | - |
| global.json | dotnet new globaljson | --sdk-version, --roll-forward |