dotnet new
Create projects, solutions and config files from templates, choose template options deliberately, and ship a team template of your own.
dotnet new <template> [-n|--name <name>] [-o|--output <dir>] [-f|--framework <tfm>] [--dry-run] [--force] [template options]- Added in .NET .NET Core 1.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$template | string | Short name of an installed template, for example webapi, web, worker, classlib, xunit, sln, gitignore, globaljson, tool-manifest, buildprops. |
$-n, --nameoptional | string= name of the current folder | Name of the output: becomes the project file name and root namespace. With no -o, project templates that set preferNameDirectory (webapi, classlib, console) also create a folder of this name; item templates such as sln and gitignore write into the current folder. |
$-o, --outputoptional | path= the current folder, or ./<name> when -n is given to a template with preferNameDirectory | Folder to write into. Created if missing. |
$-f, --frameworkoptional | TFM= the SDK's own version (net10.0 on the 10.0 SDK) | Target framework written into the project, for example net10.0. |
$--dry-runoptional | flag= false | Prints the files that would be created or changed and writes nothing. |
$--forceoptional | flag= false | Overwrites existing files. Without it, dotnet new refuses to touch files that already exist. |
$--formatoptional | sln | slnx= slnx on the .NET 10 SDK | dotnet new sln only: which solution file format to create. |
Return value
process exit code0 when the files were created. Non-zero when the template is unknown, an option is invalid, or files would be overwritten without --force.
Errors
Prints an error and returns non-zero for an unknown template or option, and refuses to overwrite existing files unless --force is passed.
Changelog
- PHP .NET 7Sub-commands became dotnet new install, uninstall, list, search and update; the old --install style switches were deprecated.
- PHP .NET 9The webapi template no longer references Swashbuckle; it uses Microsoft.AspNetCore.OpenApi and MapOpenApi.
- PHP .NET 10dotnet new sln creates a .slnx solution file by default.
dotnet new instantiates a template: a folder of files plus a .template.config/template.json that says which tokens to replace and which options exist. The SDK ships the common templates; others come from NuGet template packages installed with dotnet new install. Nothing is compiled or restored; it only writes files.
Names, folders and frameworks
-n Orders.Api sets the project file name and root namespace. For project templates (those with preferNameDirectory, such as webapi, classlib and console) -n without -o also creates a folder of that name; item templates such as sln and gitignore write into the current folder, so dotnet new sln -n Shop creates Shop.slnx right there. -o src/Orders.Api alone takes the name from the folder. Use -o in scripts so the folder layout is explicit. -f defaults to the SDK's own framework, so an SDK picked up from a newer machine can create net11.0 projects in a net10.0 solution; pin the SDK with global.json or pass -f net10.0.
Templates a back-end team uses
| Short name | Creates | Options worth knowing |
|---|---|---|
webapi | Minimal API with built-in OpenAPI and an .http file | --use-controllers, --auth, --no-https, --no-openapi |
webapiaot | Native AOT minimal API with source-generated JSON | Slim builder, no MVC |
web | Empty ASP.NET Core app | Smallest starting point |
worker | Generic host with a BackgroundService | No Kestrel |
sln | Solution file | .slnx on the .NET 10 SDK; --format sln for the old format |
gitignore, editorconfig, globaljson, buildprops, tool-manifest | Repository files | globaljson --sdk-version 10.0.402 |
dotnet new <template> --help lists that template's options, dotnet new list shows what is installed and dotnet new search queries NuGet.org.
Team templates
A company template is a normal project plus template.json. sourceName is the string that is replaced by -n everywhere: file names, namespaces and project references. symbols declare options such as --database, and conditional comments in files (//#if (database == "postgres")) keep or drop code. Pack it with PackageType=Template, publish it to the internal feed and install it with dotnet new install Contoso.Templates::2.3.0. Pin the version so every new service starts from the same baseline.
Failure modes
- Running
dotnet new webapiin the repository root scattersProgram.csandappsettings.jsonnext to the solution. Always pass-o. - Re-running a template over an existing project fails;
--forceoverwrites your edited files without a merge. Use--dry-runfirst. - Templates are a snapshot. Fixes in a newer template never reach services created earlier, so shared settings belong in
Directory.Build.props, not only in the template. - Older build agents and tools that do not read
.slnxfail on a new solution; keep them on a current SDK rather than creating.slnfiles forever.
Example
# A new Orders service in an existing repository, every choice explicit.
cd ~/src/shop
# Pin the SDK first so -f defaults to net10.0 for everyone.
dotnet new globaljson --sdk-version 10.0.402 --roll-forward latestFeature
dotnet new sln -n Shop # Shop.slnx on the .NET 10 SDK
dotnet new webapi -o src/Orders.Api --dry-run # see what would be written
dotnet new webapi -o src/Orders.Api # minimal API + OpenAPI + Orders.Api.http
dotnet new classlib -o src/Orders.Domain
dotnet new worker -o src/Orders.Worker # queue consumer, no HTTP
dotnet new buildprops # Directory.Build.props at the root
dotnet new tool-manifest # .config/dotnet-tools.json
dotnet sln add src/Orders.Api src/Orders.Domain src/Orders.Worker
# What else is available, and the options of one template
dotnet new list
dotnet new webapi --helpWhen to use it
- Scaffold a new Orders.Api and Orders.Worker into src/ of an existing Shop.slnx with explicit -o and a pinned SDK
- Publish a company template that wires logging, health checks and the internal NuGet feed into every new service
- Preview with --dry-run what a template would overwrite before re-applying it to an existing repository
Frequently asked questions
Why did dotnet new create a net11.0 project?
-f defaults to the SDK that runs the command, and without global.json that is the newest SDK installed, preview included. Pin the SDK with dotnet new globaljson or pass -f net10.0.
How do I get a classic .sln instead of .slnx?
Run dotnet new sln --format sln. Prefer .slnx with a current SDK and IDE; it is shorter, merges cleanly and is what the .NET 10 SDK creates by default.
Does the webapi template still include Swagger UI?
No. Since .NET 9 it uses Microsoft.AspNetCore.OpenApi and MapOpenApi to serve the document; add a UI such as Scalar yourself if you want one.
More examples
A team template: template.json
Saved as <code>.template.config/template.json</code> next to the project. <code>sourceName</code> is replaced by the value of <code>-n</code> in file names and contents, and <code>preferNameDirectory</code> makes <code>-n</code> create a folder. Users run <code>dotnet new contoso-api -n Orders.Api --database none</code>.
{
"$schema": "http://json.schemastore.org/template",
"author": "Platform Team",
"classifications": ["Web", "API"],
"identity": "Contoso.Templates.OrdersService",
"name": "Contoso HTTP service",
"shortName": "contoso-api",
"sourceName": "Contoso.Service",
"preferNameDirectory": true,
"tags": { "language": "C#", "type": "project" },
"symbols": {
"database": {
"type": "parameter",
"datatype": "choice",
"choices": [
{ "choice": "postgres", "description": "Npgsql + EF Core" },
{ "choice": "none", "description": "No database" }
],
"defaultValue": "postgres"
}
}
}What dotnet new webapi gives you (Program.cs)
The template's shape with the sample replaced by an orders endpoint. The OpenAPI document is mapped only in Development, and <code>UseHttpsRedirection</code> is on unless <code>--no-https</code> was passed; behind a TLS-terminating proxy it needs forwarded headers to behave.
var builder = WebApplication.CreateBuilder(args);
// Built-in OpenAPI document (Microsoft.AspNetCore.OpenApi), served at /openapi/v1.json.
builder.Services.AddOpenApi();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
app.UseHttpsRedirection();
app.MapGet("/orders/{id:int}", (int id) =>
TypedResults.Ok(new OrderSummary(id, "ORD-" + id.ToString("D6"), 129.90m)))
.WithName("GetOrder");
app.Run();
public sealed record OrderSummary(int Id, string Number, decimal Total);Packing and installing the template
Installing from a folder is the fast loop while authoring. The <code>::2.3.0</code> suffix pins the package version, so two engineers creating services on the same day get identical files rather than whatever is latest.
# The template pack project has <PackageType>Template</PackageType>
# and includes the template folders as content.
dotnet pack templates/Contoso.Templates.csproj -c Release -o artifacts
# Try it locally from the folder before publishing it.
dotnet new install ./templates/content/OrdersService
dotnet new contoso-api -n Orders.Api -o src/Orders.Api --database postgres
# Everyone else installs a pinned version from the internal feed.
dotnet new install Contoso.Templates::2.3.0
dotnet new uninstall Contoso.Templates
Discussion