.NET 6 环境搭建与实战开发教程
从零开始,手把手教你搭建 .NET 6 开发环境并完成第一个 Web API 项目
目录
1. 环境准备
1.1 安装 .NET 6 SDK
步骤 1: 下载 SDK
访问官网: https://dotnet.microsoft.com/download/dotnet/6.0
选择 SDK 6.0.xxx (不是 Runtime),下载 Windows x64 版本。
步骤 2: 安装
双击下载的安装包,一路 Next 完成安装。
步骤 3: 验证安装
打开命令行 (Win + R,输入 cmd),执行:
dotnet --version
输出类似 6.0.xxx 表示安装成功。
dotnet --list-sdks
查看已安装的所有 SDK 版本。
1.2 安装 Visual Studio 2022
步骤 1: 下载
访问: https://visualstudio.microsoft.com/zh-hans/vs/
选择 Community 2022 (免费版)。
步骤 2: 安装工作负载
安装时勾选以下工作负载:
- ✅ ASP.NET 和 Web 开发
- ✅ .NET 桌面开发 (可选)

步骤 3: 等待安装完成 (约 10-20 分钟)
1.3 安装 JetBrains Rider (推荐)
Rider 是 JetBrains 出品的跨平台 .NET IDE,如果你习惯使用 WebStorm/IDEA,Rider 会让你更快上手。
步骤 1: 下载
访问: https://www.jetbrains.com/rider/download/
选择 Windows 版本下载。
步骤 2: 安装
双击安装包,按提示完成安装。
步骤 3: 激活
- 可以申请 30 天试用
- 学生可以申请免费教育许可证
- 或者购买订阅
步骤 4: 首次配置
- 打开 Rider,选择 UI 主题 (推荐 Darcula 暗色主题)
- 安装 .NET SDK (如果未检测到会提示安装)
- 配置快捷键方案 (可选择 VS/IDEA/VS Code 风格)
Rider 优势:
- ✅ 启动速度快,比 VS 轻量
- ✅ 智能代码补全和重构功能强大
- ✅ 内置数据库工具
- ✅ 与 WebStorm/IDEA 快捷键一致
- ✅ 跨平台 (Windows/Mac/Linux)
1.4 安装 VS Code (可选)
如果你更习惯 VS Code:
- 安装 VS Code
- 安装扩展: C# (由 Microsoft 提供)
- 安装扩展: C# Dev Kit
1.5 安装数据库
本项目使用 MySQL,你也可以选择 SQL Server。
MySQL 安装:
- 下载: https://dev.mysql.com/downloads/mysql/
- 安装时记住设置的 root 密码
- 安装 MySQL Workbench (可视化工具)
验证:
mysql -u root -p
# 输入密码后进入 MySQL 命令行
1.6 安装 Postman (API 测试工具)
下载: https://www.postman.com/downloads/
用于测试我们开发的 API 接口。
2. 创建第一个项目
2.1 使用命令行创建 (推荐学习)
打开命令行,进入你想创建项目的目录:
# 进入工作目录
cd D:\Projects
# 创建解决方案文件夹
mkdir MyFirstApi
cd MyFirstApi
# 创建 Web API 项目
dotnet new webapi -n MyFirstApi -f net6.0
# 进入项目目录
cd MyFirstApi
# 运行项目
dotnet run
看到类似输出表示成功:
info: Microsoft.Hosting.Lifetime[14]
Now listening on: https://localhost:7xxx
Now listening on: http://localhost:5xxx
打开浏览器访问: https://localhost:7xxx/swagger
2.2 使用 Visual Studio 创建
步骤 1: 打开 Visual Studio 2022
步骤 2: 选择 "创建新项目"
步骤 3: 搜索 "ASP.NET Core Web API",选择它
步骤 4: 配置项目
- 项目名称:
MyFirstApi - 位置:
D:\Projects - 解决方案名称:
MyFirstApi
步骤 5: 其他信息
- 框架: .NET 6.0
- 身份验证类型: 无
- ✅ 配置 HTTPS
- ✅ 使用控制器
- ✅ 启用 OpenAPI 支持
步骤 6: 点击 "创建"
步骤 7: 按 F5 运行项目
2.3 使用 Rider 创建 (推荐)
步骤 1: 打开 Rider
步骤 2: 点击 "New Solution"
步骤 3: 选择模板
左侧选择 .NET / ASP.NET Core Web Application
右侧配置:
- Solution name:
MyFirstApi - Project name:
MyFirstApi - Directory:
D:\Projects - Type: Web API
- Framework: .NET 6.0
- ✅ Enable OpenAPI support
步骤 4: 点击 "Create"
步骤 5: 运行项目
- 点击右上角绿色运行按钮 ▶️
- 或按
Shift + F10 - 或按
Ctrl + F5(不调试运行)
Rider 常用快捷键 (IDEA 风格):
| 功能 | 快捷键 |
|---|---|
| 运行 | Shift + F10 |
| 调试 | Shift + F9 |
| 停止 | Ctrl + F2 |
| 重构/重命名 | Shift + F6 |
| 查找文件 | Ctrl + Shift + N |
| 查找类 | Ctrl + N |
| 全局搜索 | Ctrl + Shift + F |
| 格式化代码 | Ctrl + Alt + L |
| 生成代码 | Alt + Insert |
| 快速修复 | Alt + Enter |
| 跳转到定义 | Ctrl + B 或 Ctrl + 点击 |
| 查看实现 | Ctrl + Alt + B |
| 返回上一位置 | Ctrl + Alt + ← |
| 注释/取消注释 | Ctrl + / |
| 折叠/展开 | Ctrl + - / Ctrl + + |
Rider 实用功能:
- 数据库工具: 右侧 Database 面板,可直接连接 MySQL 查看数据
- HTTP Client: 内置 HTTP 请求工具,可替代 Postman
- Git 集成: 底部 Git 面板,可视化操作
- 终端: 底部 Terminal 面板,无需切换窗口
2.4 项目创建成功验证
浏览器自动打开 Swagger 页面,你会看到一个 WeatherForecast 示例 API。
点击 GET /WeatherForecast → Try it out → Execute
看到返回的 JSON 数据,恭喜你,第一个 API 项目创建成功!
3. 项目结构详解
3.1 文件结构
MyFirstApi/
├── Controllers/ # 控制器目录
│ └── WeatherForecastController.cs
├── Properties/
│ └── launchSettings.json # 启动配置
├── appsettings.json # 应用配置
├── appsettings.Development.json # 开发环境配置
├── Program.cs # 程序入口 ⭐
├── MyFirstApi.csproj # 项目文件
└── WeatherForecast.cs # 示例模型
3.2 Program.cs 详解
// 创建 Web 应用构建器
var builder = WebApplication.CreateBuilder(args);
// ========== 服务配置区域 ==========
// 添加控制器服务
builder.Services.AddControllers();
// 添加 Swagger 服务 (API 文档)
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// 构建应用
var app = builder.Build();
// ========== 中间件配置区域 ==========
// 开发环境启用 Swagger
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
// 启用 HTTPS 重定向
app.UseHttpsRedirection();
// 启用授权
app.UseAuthorization();
// 映射控制器路由
app.MapControllers();
// 运行应用
app.Run();
3.3 appsettings.json 详解
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
// 添加自定义配置
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=mydb;Uid=root;Pwd=123456;"
},
"AppSettings": {
"ApiName": "My First API",
"Version": "1.0.0"
}
}
3.4 .csproj 项目文件详解
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<!-- 目标框架 -->
<TargetFramework>net6.0</TargetFramework>
<!-- 启用可空引用类型 -->
<Nullable>enable</Nullable>
<!-- 启用隐式 using -->
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<!-- NuGet 包引用 -->
<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
</ItemGroup>
</Project>
4. 编写第一个 API
4.1 创建模型 (Model)
在项目根目录创建 Models 文件夹,新建 Product.cs:
namespace MyFirstApi.Models
{
/// <summary>
/// 产品模型
/// </summary>
public class Product
{
/// <summary>
/// 产品ID
/// </summary>
public int Id { get; set; }
/// <summary>
/// 产品名称
/// </summary>
public string Name { get; set; } = string.Empty;
/// <summary>
/// 产品价格
/// </summary>
public decimal Price { get; set; }
/// <summary>
/// 库存数量
/// </summary>
public int Stock { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreatedAt { get; set; } = DateTime.Now;
}
}
4.2 创建控制器 (Controller)
在 Controllers 文件夹新建 ProductController.cs:
using Microsoft.AspNetCore.Mvc;
using MyFirstApi.Models;
namespace MyFirstApi.Controllers
{
/// <summary>
/// 产品管理控制器
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class ProductController : ControllerBase
{
// 模拟数据库 (内存存储)
private static List<Product> _products = new()
{
new Product { Id = 1, Name = "iPhone 15", Price = 6999, Stock = 100 },
new Product { Id = 2, Name = "MacBook Pro", Price = 14999, Stock = 50 },
new Product { Id = 3, Name = "AirPods Pro", Price = 1899, Stock = 200 }
};
/// <summary>
/// 获取所有产品
/// </summary>
[HttpGet]
public ActionResult<List<Product>> GetAll()
{
return Ok(_products);
}
/// <summary>
/// 根据ID获取产品
/// </summary>
/// <param name="id">产品ID</param>
[HttpGet("{id}")]
public ActionResult<Product> GetById(int id)
{
var product = _products.FirstOrDefault(p => p.Id == id);
if (product == null)
{
return NotFound(new { message = "产品不存在" });
}
return Ok(product);
}
/// <summary>
/// 创建产品
/// </summary>
/// <param name="product">产品信息</param>
[HttpPost]
public ActionResult<Product> Create([FromBody] Product product)
{
product.Id = _products.Max(p => p.Id) + 1;
product.CreatedAt = DateTime.Now;
_products.Add(product);
return CreatedAtAction(nameof(GetById), new { id = product.Id }, product);
}
/// <summary>
/// 更新产品
/// </summary>
/// <param name="id">产品ID</param>
/// <param name="product">产品信息</param>
[HttpPut("{id}")]
public ActionResult Update(int id, [FromBody] Product product)
{
var existing = _products.FirstOrDefault(p => p.Id == id);
if (existing == null)
{
return NotFound(new { message = "产品不存在" });
}
existing.Name = product.Name;
existing.Price = product.Price;
existing.Stock = product.Stock;
return Ok(existing);
}
/// <summary>
/// 删除产品
/// </summary>
/// <param name="id">产品ID</param>
[HttpDelete("{id}")]
public ActionResult Delete(int id)
{
var product = _products.FirstOrDefault(p => p.Id == id);
if (product == null)
{
return NotFound(new { message = "产品不存在" });
}
_products.Remove(product);
return Ok(new { message = "删除成功" });
}
/// <summary>
/// 搜索产品
/// </summary>
/// <param name="keyword">关键字</param>
/// <param name="minPrice">最低价格</param>
/// <param name="maxPrice">最高价格</param>
[HttpGet("search")]
public ActionResult<List<Product>> Search(
string? keyword = null,
decimal? minPrice = null,
decimal? maxPrice = null)
{
var query = _products.AsQueryable();
if (!string.IsNullOrEmpty(keyword))
{
query = query.Where(p => p.Name.Contains(keyword));
}
if (minPrice.HasValue)
{
query = query.Where(p => p.Price >= minPrice.Value);
}
if (maxPrice.HasValue)
{
query = query.Where(p => p.Price <= maxPrice.Value);
}
return Ok(query.ToList());
}
}
}
4.3 运行并测试
- 按 F5 运行项目
- 打开 Swagger:
https://localhost:7xxx/swagger - 测试各个接口:
GET /api/Product- 获取所有产品GET /api/Product/1- 获取ID为1的产品POST /api/Product- 创建新产品PUT /api/Product/1- 更新产品DELETE /api/Product/1- 删除产品
4.4 使用 Postman 测试
GET 请求:
GET https://localhost:7xxx/api/Product
POST 请求:
POST https://localhost:7xxx/api/Product
Content-Type: application/json
{
"name": "iPad Pro",
"price": 8999,
"stock": 30
}
5. 连接数据库
5.1 安装 SqlSugar
在项目目录执行:
dotnet add package SqlSugarCore
或者在 Visual Studio 中:
- 右键项目 → 管理 NuGet 程序包
- 搜索
SqlSugarCore - 点击安装
5.2 配置数据库连接
修改 appsettings.json:
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Port=3306;Database=my_first_db;Uid=root;Pwd=你的密码;Charset=utf8mb4;"
},
"Logging": {
"LogLevel": {
"Default": "Information"
}
}
}
5.3 创建数据库服务
新建 Services/DbService.cs:
using SqlSugar;
namespace MyFirstApi.Services
{
/// <summary>
/// 数据库服务
/// </summary>
public class DbService
{
private readonly string _connectionString;
public DbService(IConfiguration configuration)
{
_connectionString = configuration.GetConnectionString("DefaultConnection")!;
}
/// <summary>
/// 获取数据库连接
/// </summary>
public SqlSugarClient GetDb()
{
return new SqlSugarClient(new ConnectionConfig
{
ConnectionString = _connectionString,
DbType = DbType.MySql,
IsAutoCloseConnection = true,
InitKeyType = InitKeyType.Attribute
});
}
/// <summary>
/// 初始化数据库和表
/// </summary>
public void InitDatabase()
{
var db = GetDb();
// 创建数据库 (如果不存在)
db.DbMaintenance.CreateDatabase();
// 创建表 (根据实体类)
db.CodeFirst.InitTables<Models.Product>();
Console.WriteLine("数据库初始化完成!");
}
}
}
5.4 修改 Product 模型
using SqlSugar;
namespace MyFirstApi.Models
{
/// <summary>
/// 产品模型
/// </summary>
[SugarTable("products")]
public class Product
{
/// <summary>
/// 产品ID
/// </summary>
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
public int Id { get; set; }
/// <summary>
/// 产品名称
/// </summary>
[SugarColumn(Length = 100)]
public string Name { get; set; } = string.Empty;
/// <summary>
/// 产品价格
/// </summary>
[SugarColumn(DecimalDigits = 2)]
public decimal Price { get; set; }
/// <summary>
/// 库存数量
/// </summary>
public int Stock { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreatedAt { get; set; } = DateTime.Now;
/// <summary>
/// 是否删除
/// </summary>
public bool IsDeleted { get; set; } = false;
}
}
5.5 注册服务
修改 Program.cs:
using MyFirstApi.Services;
var builder = WebApplication.CreateBuilder(args);
// 添加控制器
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// 注册数据库服务 (单例模式)
builder.Services.AddSingleton<DbService>();
var app = builder.Build();
// 初始化数据库
var dbService = app.Services.GetRequiredService<DbService>();
dbService.InitDatabase();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
6. 完整 CRUD 实战
6.1 创建产品服务
新建 Services/ProductService.cs:
using MyFirstApi.Models;
using SqlSugar;
namespace MyFirstApi.Services
{
/// <summary>
/// 产品服务
/// </summary>
public class ProductService
{
private readonly DbService _dbService;
public ProductService(DbService dbService)
{
_dbService = dbService;
}
/// <summary>
/// 获取所有产品
/// </summary>
public List<Product> GetAll()
{
var db = _dbService.GetDb();
return db.Queryable<Product>()
.Where(p => !p.IsDeleted)
.OrderByDescending(p => p.CreatedAt)
.ToList();
}
/// <summary>
/// 根据ID获取产品
/// </summary>
public Product? GetById(int id)
{
var db = _dbService.GetDb();
return db.Queryable<Product>()
.Where(p => p.Id == id && !p.IsDeleted)
.First();
}
/// <summary>
/// 分页查询
/// </summary>
public (List<Product> Items, int Total) GetPage(
int pageIndex,
int pageSize,
string? keyword = null)
{
var db = _dbService.GetDb();
int total = 0;
var query = db.Queryable<Product>()
.Where(p => !p.IsDeleted);
if (!string.IsNullOrEmpty(keyword))
{
query = query.Where(p => p.Name.Contains(keyword));
}
var items = query
.OrderByDescending(p => p.CreatedAt)
.ToPageList(pageIndex, pageSize, ref total);
return (items, total);
}
/// <summary>
/// 创建产品
/// </summary>
public int Create(Product product)
{
var db = _dbService.GetDb();
product.CreatedAt = DateTime.Now;
return db.Insertable(product).ExecuteReturnIdentity();
}
/// <summary>
/// 更新产品
/// </summary>
public bool Update(Product product)
{
var db = _dbService.GetDb();
return db.Updateable(product)
.IgnoreColumns(p => new { p.CreatedAt, p.IsDeleted })
.ExecuteCommand() > 0;
}
/// <summary>
/// 删除产品 (软删除)
/// </summary>
public bool Delete(int id)
{
var db = _dbService.GetDb();
return db.Updateable<Product>()
.SetColumns(p => p.IsDeleted == true)
.Where(p => p.Id == id)
.ExecuteCommand() > 0;
}
}
}
6.2 创建 DTO
新建 Dtos/ProductDtos.cs:
namespace MyFirstApi.Dtos
{
/// <summary>
/// 统一响应格式
/// </summary>
public class ApiResponse<T>
{
public int Code { get; set; }
public string Message { get; set; } = string.Empty;
public T? Data { get; set; }
public static ApiResponse<T> Success(T data, string message = "操作成功")
{
return new ApiResponse<T> { Code = 200, Message = message, Data = data };
}
public static ApiResponse<T> Fail(string message, int code = 400)
{
return new ApiResponse<T> { Code = code, Message = message };
}
}
/// <summary>
/// 分页响应
/// </summary>
public class PageResponse<T>
{
public List<T> Items { get; set; } = new();
public int Total { get; set; }
public int PageIndex { get; set; }
public int PageSize { get; set; }
public int TotalPages => (int)Math.Ceiling((double)Total / PageSize);
}
/// <summary>
/// 创建产品请求
/// </summary>
public class CreateProductDto
{
public string Name { get; set; } = string.Empty;
public decimal Price { get; set; }
public int Stock { get; set; }
}
/// <summary>
/// 更新产品请求
/// </summary>
public class UpdateProductDto
{
public string Name { get; set; } = string.Empty;
public decimal Price { get; set; }
public int Stock { get; set; }
}
}
6.3 重构控制器
修改 Controllers/ProductController.cs:
using Microsoft.AspNetCore.Mvc;
using MyFirstApi.Dtos;
using MyFirstApi.Models;
using MyFirstApi.Services;
namespace MyFirstApi.Controllers
{
/// <summary>
/// 产品管理控制器
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class ProductController : ControllerBase
{
private readonly ProductService _productService;
public ProductController(ProductService productService)
{
_productService = productService;
}
/// <summary>
/// 获取所有产品
/// </summary>
[HttpGet]
public ActionResult<ApiResponse<List<Product>>> GetAll()
{
var products = _productService.GetAll();
return Ok(ApiResponse<List<Product>>.Success(products));
}
/// <summary>
/// 分页查询产品
/// </summary>
/// <param name="pageIndex">页码 (从1开始)</param>
/// <param name="pageSize">每页数量</param>
/// <param name="keyword">搜索关键字</param>
[HttpGet("page")]
public ActionResult<ApiResponse<PageResponse<Product>>> GetPage(
int pageIndex = 1,
int pageSize = 10,
string? keyword = null)
{
var (items, total) = _productService.GetPage(pageIndex, pageSize, keyword);
var pageData = new PageResponse<Product>
{
Items = items,
Total = total,
PageIndex = pageIndex,
PageSize = pageSize
};
return Ok(ApiResponse<PageResponse<Product>>.Success(pageData));
}
/// <summary>
/// 根据ID获取产品
/// </summary>
[HttpGet("{id}")]
public ActionResult<ApiResponse<Product>> GetById(int id)
{
var product = _productService.GetById(id);
if (product == null)
{
return NotFound(ApiResponse<Product>.Fail("产品不存在", 404));
}
return Ok(ApiResponse<Product>.Success(product));
}
/// <summary>
/// 创建产品
/// </summary>
[HttpPost]
public ActionResult<ApiResponse<int>> Create([FromBody] CreateProductDto dto)
{
var product = new Product
{
Name = dto.Name,
Price = dto.Price,
Stock = dto.Stock
};
var id = _productService.Create(product);
return Ok(ApiResponse<int>.Success(id, "创建成功"));
}
/// <summary>
/// 更新产品
/// </summary>
[HttpPut("{id}")]
public ActionResult<ApiResponse<bool>> Update(int id, [FromBody] UpdateProductDto dto)
{
var existing = _productService.GetById(id);
if (existing == null)
{
return NotFound(ApiResponse<bool>.Fail("产品不存在", 404));
}
existing.Name = dto.Name;
existing.Price = dto.Price;
existing.Stock = dto.Stock;
var success = _productService.Update(existing);
return Ok(ApiResponse<bool>.Success(success, "更新成功"));
}
/// <summary>
/// 删除产品
/// </summary>
[HttpDelete("{id}")]
public ActionResult<ApiResponse<bool>> Delete(int id)
{
var success = _productService.Delete(id);
if (!success)
{
return NotFound(ApiResponse<bool>.Fail("产品不存在", 404));
}
return Ok(ApiResponse<bool>.Success(true, "删除成功"));
}
}
}
6.4 注册服务
修改 Program.cs:
using MyFirstApi.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// 注册服务
builder.Services.AddSingleton<DbService>();
builder.Services.AddScoped<ProductService>(); // 添加这行
var app = builder.Build();
// 初始化数据库
var dbService = app.Services.GetRequiredService<DbService>();
dbService.InitDatabase();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
7. 常用开发技巧
7.1 全局异常处理
新建 Filters/GlobalExceptionFilter.cs:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using MyFirstApi.Dtos;
namespace MyFirstApi.Filters
{
/// <summary>
/// 全局异常过滤器
/// </summary>
public class GlobalExceptionFilter : IExceptionFilter
{
private readonly ILogger<GlobalExceptionFilter> _logger;
public GlobalExceptionFilter(ILogger<GlobalExceptionFilter> logger)
{
_logger = logger;
}
public void OnException(ExceptionContext context)
{
// 记录日志
_logger.LogError(context.Exception, "发生未处理异常");
// 返回统一格式
var response = ApiResponse<object>.Fail(
context.Exception.Message,
500
);
context.Result = new JsonResult(response)
{
StatusCode = 500
};
context.ExceptionHandled = true;
}
}
}
注册过滤器:
builder.Services.AddControllers(options =>
{
options.Filters.Add<GlobalExceptionFilter>();
});
7.2 跨域配置 (CORS)
// Program.cs
var builder = WebApplication.CreateBuilder(args);
// 添加 CORS 服务
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAll", policy =>
{
policy.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
var app = builder.Build();
// 使用 CORS (放在 UseAuthorization 之前)
app.UseCors("AllowAll");
7.3 日志配置
// 使用内置日志
public class ProductController : ControllerBase
{
private readonly ILogger<ProductController> _logger;
public ProductController(ILogger<ProductController> logger)
{
_logger = logger;
}
[HttpGet]
public IActionResult GetAll()
{
_logger.LogInformation("获取所有产品");
// ...
}
}
7.4 配置读取
// appsettings.json
{
"AppSettings": {
"ApiName": "My API",
"MaxPageSize": 100
}
}
// 读取配置
public class MyService
{
private readonly IConfiguration _config;
public MyService(IConfiguration config)
{
_config = config;
}
public void DoSomething()
{
var apiName = _config["AppSettings:ApiName"];
var maxSize = _config.GetValue<int>("AppSettings:MaxPageSize");
}
}
7.5 文件上传
[HttpPost("upload")]
public async Task<ActionResult<ApiResponse<string>>> Upload(IFormFile file)
{
if (file == null || file.Length == 0)
{
return BadRequest(ApiResponse<string>.Fail("请选择文件"));
}
// 生成文件名
var fileName = $"{Guid.NewGuid()}{Path.GetExtension(file.FileName)}";
var filePath = Path.Combine("uploads", fileName);
// 确保目录存在
Directory.CreateDirectory("uploads");
// 保存文件
using var stream = new FileStream(filePath, FileMode.Create);
await file.CopyToAsync(stream);
return Ok(ApiResponse<string>.Success(fileName, "上传成功"));
}
8. 调试与测试
8.1 Visual Studio 调试
设置断点:
- 点击代码行号左侧,出现红点
启动调试:
- 按 F5 启动调试
- 按 Ctrl + F5 不调试运行
调试快捷键:
- F10: 单步跳过
- F11: 单步进入
- Shift + F11: 单步跳出
- F5: 继续运行
查看变量:
- 鼠标悬停在变量上
- 使用"监视"窗口
- 使用"即时窗口"执行代码
8.2 Rider 调试 (推荐)
设置断点:
- 点击代码行号左侧,出现红点
- 或者光标在行上按
Ctrl + F8
启动调试:
- 按
Shift + F9启动调试 - 按
Shift + F10不调试运行 - 或点击右上角绿色虫子图标 🐛
调试快捷键 (IDEA 风格):
| 功能 | 快捷键 |
|---|---|
| 单步跳过 (Step Over) | F8 |
| 单步进入 (Step Into) | F7 |
| 单步跳出 (Step Out) | Shift + F8 |
| 继续运行 (Resume) | F9 |
| 运行到光标处 | Alt + F9 |
| 停止调试 | Ctrl + F2 |
| 计算表达式 | Alt + F8 |
| 切换断点 | Ctrl + F8 |
查看变量:
- 鼠标悬停在变量上查看值
- 使用左下角 Variables 面板查看所有变量
- 使用 Watches 面板添加监视表达式
- 使用 Evaluate Expression (
Alt + F8) 执行代码
条件断点:
- 右键点击断点红点
- 选择 "Edit Breakpoint"
- 输入条件表达式,如:
id == 5
Rider 调试技巧:
- 异常断点: Run → View Breakpoints → 勾选 "Any exception"
- 日志断点: 右键断点 → 勾选 "Log message to console",不暂停只打印
- 内联值显示: 调试时变量值直接显示在代码行末尾
- 热重载: 调试时修改代码,按
Alt + F10应用更改
8.3 使用 Rider 内置 HTTP Client
Rider 内置了 HTTP 请求工具,可以替代 Postman。
创建请求文件:
- 右键项目 → New → HTTP Request
- 创建
api-test.http文件
编写请求:
### 获取所有产品
GET https://localhost:7xxx/api/Product
Accept: application/json
### 获取单个产品
GET https://localhost:7xxx/api/Product/1
Accept: application/json
### 创建产品
POST https://localhost:7xxx/api/Product
Content-Type: application/json
{
"name": "iPad Pro",
"price": 8999,
"stock": 30
}
### 更新产品
PUT https://localhost:7xxx/api/Product/1
Content-Type: application/json
{
"name": "iPad Pro 2024",
"price": 9999,
"stock": 25
}
### 删除产品
DELETE https://localhost:7xxx/api/Product/1
运行请求:
- 点击请求左侧的绿色运行按钮 ▶️
- 响应结果显示在右侧面板
使用环境变量:
创建 http-client.env.json:
{
"dev": {
"baseUrl": "https://localhost:7xxx"
},
"prod": {
"baseUrl": "https://api.example.com"
}
}
请求中使用变量:
GET {{baseUrl}}/api/Product
8.4 使用 Swagger 测试
- 运行项目后访问
/swagger - 展开接口,点击 "Try it out"
- 填写参数,点击 "Execute"
- 查看响应结果
8.5 使用 Postman 测试
创建请求集合:
- 新建 Collection: "MyFirstApi"
- 添加请求
环境变量:
baseUrl = https://localhost:7xxx
请求示例:
GET {{baseUrl}}/api/Product
GET {{baseUrl}}/api/Product/1
POST {{baseUrl}}/api/Product
8.6 单元测试 (进阶)
创建测试项目:
dotnet new xunit -n MyFirstApi.Tests
dotnet add MyFirstApi.Tests reference MyFirstApi
编写测试:
public class ProductServiceTests
{
[Fact]
public void GetAll_ShouldReturnProducts()
{
// Arrange
var service = new ProductService(/* mock */);
// Act
var result = service.GetAll();
// Assert
Assert.NotNull(result);
}
}
9. 部署发布
9.1 发布项目
命令行发布:
# 发布到 publish 文件夹
dotnet publish -c Release -o ./publish
Visual Studio 发布:
- 右键项目 → 发布
- 选择目标 (文件夹/IIS/Azure等)
- 配置发布选项
- 点击发布
9.2 IIS 部署
- 安装 .NET 6 Hosting Bundle
- 在 IIS 中创建网站
- 将发布文件复制到网站目录
- 配置应用程序池 (.NET CLR 版本选择"无托管代码")
9.3 Docker 部署
创建 Dockerfile:
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["MyFirstApi.csproj", "."]
RUN dotnet restore
COPY . .
RUN dotnet build -c Release -o /app/build
FROM build AS publish
RUN dotnet publish -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MyFirstApi.dll"]
构建和运行:
docker build -t myfirstapi .
docker run -d -p 8080:80 myfirstapi
附录: 常见问题
Q1: 端口被占用
# 查看端口占用
netstat -ano | findstr :5000
# 修改端口 (launchSettings.json)
"applicationUrl": "https://localhost:7001;http://localhost:5001"
Q2: 数据库连接失败
检查:
- MySQL 服务是否启动
- 连接字符串是否正确
- 用户名密码是否正确
- 数据库是否存在
Q3: Swagger 不显示注释
在 .csproj 中添加:
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
在 Program.cs 中配置:
builder.Services.AddSwaggerGen(c =>
{
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
});
Q4: 跨域问题
确保:
- 已添加 CORS 服务
UseCors放在UseAuthorization之前- 前端请求地址正确
下一步学习
完成本教程后,建议:
- ✅ 阅读
CSharp_DotNet6_学习指南.md深入学习 - ✅ 尝试给 DataAcquireAndControl 项目添加新功能
- ✅ 学习 Entity Framework Core (另一个流行的 ORM)
- ✅ 学习 JWT 身份认证
- ✅ 学习 SignalR 实时通信
祝你学习顺利!🎉