闲话 Asp.Net Core 数据校验(三)EF Core 集成 FluentValidation 校验数据例子

发布于:2024-04-30 ⋅ 阅读:(28) ⋅ 点赞:(0)

image

前言

一个在实际应用中 EF Core 集成 FluentValidation 进行数据校验的例子。

Step By Step 步骤

  1. 创建一个 Asp.Net Core WebApi 项目

  2. 引用以下 Nuget 包

    FluentValidation.AspNetCore
    Microsoft.AspNetCore.Identity.EntityFrameworkCore
    Microsoft.EntityFrameworkCore.Relational
    Microsoft.EntityFrameworkCore.SqlServer
    Microsoft.EntityFrameworkCore.Tools

  3. 创建 Login 操作方法的请求参数模型类 LoginRequest

    // LoginRequest 类只是一个普通的C#类,
    // 没有标注任何的Attribute或者实现任何的接口,
    // 它的唯一责任就是传递数据
    public record LoginRequest(string Email, string Password, string PasswordConfirm);
    
  4. 修改 appsettings.json,添加数据库连接字符串

    {
      "Logging": {
    	"LogLevel": {
    	  "Default": "Information",
    	  "Microsoft.AspNetCore": "Warning"
    	}
      },
      "AllowedHosts": "*",
      "ConnectionStrings": {
    	"Default": "Server=(localdb)\\mssqllocaldb;Database=IdentityTestDB;Trusted_Connection=True;MultipleActiveResultSets=true"
      }
    }	
    
  5. 创建用户实体类User和Role

    using Microsoft.AspNetCore.Identity;
    
    public class User : IdentityUser<long>
    {
    	public DateTime CreationTime { get; set; }
    	public string? NickName { get; set; }
    }
    
    public class Role : IdentityRole<long>
    {
    
    }
    
  6. 创建继承自IdentityDbContext的上下文类

    using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
    using Microsoft.EntityFrameworkCore;
    
    public class TestDbContext : IdentityDbContext<User, Role, long>
    {
    	public TestDbContext(DbContextOptions<TestDbContext> options)
    		: base(options)
    	{
    
    	}
    	protected override void OnModelCreating(ModelBuilder modelBuilder)
    	{
    		base.OnModelCreating(modelBuilder);
    		modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
    	}
    }
    
  7. 打开 Program.cs,注册 Identity 和 FluentValidation

    using FluentValidation;
    using FluentValidation.AspNetCore;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.EntityFrameworkCore;
    using System.Reflection;
    
    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    
    builder.Services.AddControllers();
    // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerGen();
    
    // 注册标识框架相关的服务,并配置相关选项
    IServiceCollection services = builder.Services;
    services.AddDbContext<TestDbContext>(opt =>
    {
    	string connStr = builder.Configuration.GetConnectionString("Default")!;
    	opt.UseSqlServer(connStr);
    });
    services.AddDataProtection();
    services.AddIdentityCore<User>(options =>
    {
    	options.Password.RequireDigit = false;
    	options.Password.RequireLowercase = false;
    	options.Password.RequireNonAlphanumeric = false;
    	options.Password.RequireUppercase = false;
    	options.Password.RequiredLength = 6;
    	options.Tokens.PasswordResetTokenProvider = TokenOptions.DefaultEmailProvider;
    	options.Tokens.EmailConfirmationTokenProvider = TokenOptions.DefaultEmailProvider;
    });
    var idBuilder = new IdentityBuilder(typeof(User), typeof(Role), services);
    idBuilder.AddEntityFrameworkStores<TestDbContext>()
    	.AddDefaultTokenProviders()
    	.AddRoleManager<RoleManager<Role>>()
    	.AddUserManager<UserManager<User>>();
    
    // 注册 FluentValidation 服务
    Assembly assembly = Assembly.GetExecutingAssembly();
    builder.Services.AddFluentValidationAutoValidation()
    	.AddFluentValidationClientsideAdapters()
    	.AddValidatorsFromAssembly(assembly);
    
    var app = builder.Build();
    
    // Configure the HTTP request pipeline.
    if (app.Environment.IsDevelopment())
    {
    	app.UseSwagger();
    	app.UseSwaggerUI();
    }
    
    app.UseHttpsRedirection();
    
    app.UseAuthorization();
    
    app.MapControllers();
    
    app.Run();	
    
  8. 编写请求参数模型类 LoginRequest

    public record LoginRequest(string UserName, string Password);
    
  9. 编写继承自AbstractValidator的数据校验类,留意注释

    using FluentValidation;
    using Microsoft.EntityFrameworkCore;
    
    public class LoginRequestValidator : AbstractValidator<LoginRequest>
    {
    	// 通过构造方法注入了TestDbContext
    	public LoginRequestValidator(TestDbContext dbCtx)
    	{
    		RuleFor(x => x.UserName)
    			.NotNull()
    			// 使用TestDbContext服务检查用户名是否存在
    			// 同步方式
    			.Must(name => dbCtx.Users.Any(u => u.UserName == name))
    			// 异步方式,但使用异步后出错,暂时未能找到解决方案
    			//.MustAsync((name,_) => dbCtx.Users.AnyAsync(u => u.UserName == name))
    			// 用Lambda表达式的形式使用模型类中的属性对报错信息进行格式化
    			.WithMessage(c => $"用户名{c.UserName}不存在");
    	}
    }
    
  10. 打开登录请求控制器,编写 Login API

    using Microsoft.AspNetCore.Mvc;
    
    namespace FluentValidationSample2.Controllers
    {
    	[ApiController]
    	[Route("[controller]/[action]")]
    	public class TestController : ControllerBase
    	{
    		[HttpPost]
    		public ActionResult Login(LoginRequest req)
    		{
    			return Ok();
    		}
    	}
    }
    
  11. 在 Postman 或 Swagger 测试 Login API,如果请求的用户名不存在,即会返回代码中定义的错误信息


网站公告

今日签到

点亮在社区的每一天
去签到