选对 dotnet new 模板是新建项目关键,需用 dotnet new --list 查看、-f 指定框架版本、避免中文路径;dotnet restore 应在 CI 中显式调用;dotnet run 需用 --project 指定目标;publish 须按需设 --self-contained 和 --runtime。

dotnet new 创建项目时如何选对模板
新建项目第一步不是写代码,而是选对 dotnet new 模板。模板不对,后续引用、SDK 版本、启动方式全可能出问题。
-
dotnet new --list查看本地已安装模板(注意:.NET SDK 更新后需手动运行dotnet new --install补充新模板) - 常用模板名必须带引号或转义:Web 项目用
dotnet new web(.NET 6+),不要用过时的webapi或mvc模板除非明确需要对应结构 - 指定框架版本要加
-f参数:dotnet new console -f net8.0,否则默认用 SDK 最高稳定版,CI 环境容易因 SDK 升级意外失败 - 避免在中文路径下执行
dotnet new,某些模板(如 Blazor WebAssembly)生成的.csproj文件可能含非法 XML 字符,导致dotnet build报错MSB4025: The project file could not be loaded
dotnet restore 和隐式还原的区别
dotnet restore 不是总需要手动运行——但你得知道它什么时候被跳过、什么时候必须显式调用。
-
dotnet build、dotnet run、dotnet test默认会触发隐式还原,但仅当项目文件(.csproj)自上次还原后有变更(比如新增了) - CI/CD 流水线中建议始终显式执行
dotnet restore,否则缓存机制可能导致依赖未更新,尤其使用Directory.Build.props全局控制包版本时 - 若遇到
NU1102: Unable to find package xxx,先确认NuGet.Config是否配置了私有源;再检查是否误用了--interactive参数(该参数在无 TTY 的 Docker 构建中会卡住) - 多项目解决方案中,
dotnet restore solution.sln比逐个还原更快,且能统一解析项目间项目引用(ProjectReference)
dotnet run 总是编译整个解决方案?怎么只跑一个项目
dotnet run 默认行为取决于当前目录和项目文件存在位置,不加参数很容易跑错目标。
- 在解决方案根目录执行
dotnet run会报错Couldn't find a project to run—— 它只认当前目录下的.csproj,不自动推导启动项目 - 指定项目必须用
--project(不能简写为-p在某些旧 SDK 中不可靠):dotnet run --project src/MyApp/MyApp.csproj - 传递命令行参数给应用本身时,双短横后的内容才属于应用:
dotnet run --project app.csproj -- --verbose --port 5001,中间的--是分隔符,漏掉会导致参数被 CLI 解析而非传入 Main - 若项目含
(如true web模板),dotnet run自动启用热重载(Hot Reload);但类库项目或console模板默认不启用,需加--hot-reload参数(.NET 6+)
dotnet publish 输出目录混乱?如何控制产物结构
dotnet publish 的输出不是简单复制文件,它的目录结构、依赖打包方式直接受参数控制,稍不注意就部署失败。
-
--self-contained false(默认)生成“框架依赖型”发布包,运行前需目标机器装对应 .NET 运行时;--self-contained true才打包容器化部署常用的独立包,但体积大、跨平台需额外指定--runtime(如linux-x64) -
-o指定输出路径时,路径不能是相对路径中的上级目录(如-o ../publish),部分 SDK 版本会静默失败或覆盖错误目录 - 发布 Web 项目时,默认启用
Trimming(.NET 6+),可能移除反射使用的类型,导致System.TypeLoadException;若用到Assembly.GetTypes()或 JSON 序列化动态类型,应加--no-trim - 想排除 XML 文档文件减少体积?加
/p:ExcludeXmlDocs=true;但别用/p:DocumentationFile=手动指定,它和dotnet publish的内部文档生成逻辑冲突
.NET CLI 的复杂性不在命令数量,而在每个命令背后隐含的 SDK 版本策略、项目系统解析逻辑和跨平台运行时绑定规则。最容易被忽略的是:同一句 dotnet build 在本地 Windows 和 CI 中的 Linux runner 上,可能因 global.json 缺失或 MSBuildSDKsPath 环境变量不同,加载完全不同的 SDK 目录。










