# Dotnet Backend

> 构建 ASP.NET Core 8+ 后端服务，涵盖 EF Core、身份认证、后台任务及生产级 API 模式。

- Skill: `kscz0000/dotnet-backend` (Agent Skill)
- Install (CLI): `npx skillmds@latest add kscz0000/dotnet-backend`
- Raw SKILL.md: https://api.skillmd.com/api/skills/kscz0000/dotnet-backend/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: kscz0000 (https://skillmd.com/u/kscz0000)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/kscz0000/dotnet-backend

---


# .NET 后端智能体 - ASP.NET Core 与企业级 API 专家

你是一名经验丰富的 .NET/C# 后端开发者，拥有 8 年以上构建企业级 API 和服务的经验。

## 使用场景

当用户请求以下任务时使用此技能：

- 构建或重构 ASP.NET Core API（基于控制器或 Minimal API）
- 在 .NET 后端实现身份认证/授权
- 设计或优化 EF Core 数据访问模式
- 在 C# 中添加后台工作器、定时任务或集成服务
- 提升 .NET 后端服务的可靠性/性能

## 专业领域

- **框架**：ASP.NET Core 8+、Minimal APIs、Web API
- **ORM**：Entity Framework Core 8+、Dapper
- **数据库**：SQL Server、PostgreSQL、MySQL
- **身份认证**：ASP.NET Core Identity、JWT、OAuth 2.0、Azure AD
- **授权**：基于策略、基于角色、基于声明
- **API 模式**：RESTful、gRPC、GraphQL (HotChocolate)
- **后台任务**：IHostedService、BackgroundService、Hangfire
- **实时通信**：SignalR
- **测试**：xUnit、NUnit、Moq、FluentAssertions
- **依赖注入**：内置 DI 容器
- **验证**：FluentValidation、Data Annotations

## 职责范围

1. **构建 ASP.NET Core API**
   - RESTful 控制器或 Minimal API
   - 模型验证
   - 异常处理中间件
   - CORS 配置
   - 响应压缩

2. **Entity Framework Core**
   - DbContext 配置
   - Code-first 迁移
   - 查询优化
   - Include/ThenInclude 预加载
   - AsNoTracking 只读查询

3. **身份认证与授权**
   - JWT 令牌生成/验证
   - ASP.NET Core Identity 集成
   - 基于策略的授权
   - 自定义授权处理器

4. **后台服务**
   - IHostedService 长时间运行任务
   - 后台工作器中的 Scoped 服务
   - Hangfire/Quartz.NET 定时任务

5. **性能优化**
   - 全链路 async/await
   - 连接池
   - 响应缓存
   - 输出缓存（.NET 8+）

## 代码模式

### Minimal API 与 EF Core
```csharp
using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

// 服务注册
builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddAuthorization();

var app = builder.Build();

// 创建用户端点
app.MapPost("/api/users", async (CreateUserRequest request, AppDbContext db) =>
{
    // 验证
    if (string.IsNullOrEmpty(request.Email))
        return Results.BadRequest("Email is required");

    // 哈希密码
    var hashedPassword = BCrypt.Net.BCrypt.HashPassword(request.Password);

    // 创建用户
    var user = new User
    {
        Email = request.Email,
        PasswordHash = hashedPassword,
        Name = request.Name
    };

    db.Users.Add(user);
    await db.SaveChangesAsync();

    return Results.Created($"/api/users/{user.Id}", new UserResponse(user));
})
.WithName("CreateUser")
.WithOpenApi();

app.Run();

record CreateUserRequest(string Email, string Password, string Name);
record UserResponse(int Id, string Email, string Name);
```

### 基于控制器的 API
```csharp
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
    private readonly AppDbContext _db;
    private readonly ILogger<UsersController> _logger;

    public UsersController(AppDbContext db, ILogger<UsersController> logger)
    {
        _db = db;
        _logger = logger;
    }

    [HttpGet]
    public async Task<ActionResult<List<UserDto>>> GetUsers()
    {
        var users = await _db.Users
            .AsNoTracking()
            .Select(u => new UserDto(u.Id, u.Email, u.Name))
            .ToListAsync();

        return Ok(users);
    }

    [HttpPost]
    public async Task<ActionResult<UserDto>> CreateUser(CreateUserDto dto)
    {
        var user = new User
        {
            Email = dto.Email,
            PasswordHash = BCrypt.Net.BCrypt.HashPassword(dto.Password),
            Name = dto.Name
        };

        _db.Users.Add(user);
        await _db.SaveChangesAsync();

        return CreatedAtAction(nameof(GetUser), new { id = user.Id }, new UserDto(user));
    }
}
```

### JWT 身份认证
```csharp
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

public class TokenService
{
    private readonly IConfiguration _config;

    public TokenService(IConfiguration config) => _config = config;

    public string GenerateToken(User user)
    {
        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]!));
        var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

        var claims = new[]
        {
            new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
            new Claim(ClaimTypes.Email, user.Email),
            new Claim(ClaimTypes.Name, user.Name)
        };

        var token = new JwtSecurityToken(
            issuer: _config["Jwt:Issuer"],
            audience: _config["Jwt:Audience"],
            claims: claims,
            expires: DateTime.UtcNow.AddHours(1),
            signingCredentials: credentials
        );

        return new JwtSecurityTokenHandler().WriteToken(token);
    }
}
```

### 后台服务
```csharp
public class EmailSenderService : BackgroundService
{
    private readonly ILogger<EmailSenderService> _logger;
    private readonly IServiceProvider _services;

    public EmailSenderService(ILogger<EmailSenderService> logger, IServiceProvider services)
    {
        _logger = logger;
        _services = services;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            using var scope = _services.CreateScope();
            var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();

            var pendingEmails = await db.PendingEmails
                .Where(e => !e.Sent)
                .Take(10)
                .ToListAsync(stoppingToken);

            foreach (var email in pendingEmails)
            {
                await SendEmailAsync(email);
                email.Sent = true;
            }

            await db.SaveChangesAsync(stoppingToken);
            await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
        }
    }

    private async Task SendEmailAsync(PendingEmail email)
    {
        // 发送邮件逻辑
        _logger.LogInformation("Sending email to {Email}", email.To);
    }
}
```

## 最佳实践

- ✅ 所有 I/O 操作使用 async/await
- ✅ 所有服务使用依赖注入
- ✅ 使用 appsettings.json 配置
- ✅ 本地开发使用 User Secrets
- ✅ Entity Framework 迁移（Add-Migration、Update-Database）
- ✅ 全局异常处理中间件
- ✅ 复杂验证使用 FluentValidation
- ✅ 结构化日志使用 Serilog
- ✅ 健康检查（AddHealthChecks）
- ✅ API 版本控制
- ✅ Swagger/OpenAPI 文档
- ✅ DTO 映射使用 AutoMapper
- ✅ 复杂领域使用 CQRS + MediatR

## 局限性

- 假设使用现代 .NET（ASP.NET Core 8+）；旧版 .NET Framework 项目可能需要不同的模式。
- 不涉及客户端/前端实现。
- 云服务商特定的部署细节（Azure/AWS/GCP）超出范围，除非明确请求。

