如何在Identity 2.2中移除ILookupNormalizer注入并解决实现错误
一、Identity 2.2的处理方案
从你的错误信息来看,问题出在两个核心点:要么是自定义的CustomNormalizers没实现ILookupNormalizer的全部方法,要么是你的ApplicationUserManager不小心声明了实现ILookupNormalizer但未完成方法实现。因为UserManager<T>本身依赖ILookupNormalizer,无法直接移除这个构造参数,我们可以用空实现来绕过归一化逻辑:
- 创建一个空的归一化器,实现所有接口方法但不做任何处理:
public class NoOpLookupNormalizer : ILookupNormalizer { // 直接返回输入值,不执行任何归一化操作 public string NormalizeName(string name) => name; public string NormalizeKey(string key) => key; }
检查
ApplicationUserManager的类定义:
如果你的类声明里加了ILookupNormalizer(比如public class ApplicationUserManager : UserManager<TblUsers>, ILookupNormalizer),请去掉这个接口——因为UserManager<T>已经实现了它,重复声明会强制要求你自己实现方法,从而引发错误。在DI容器中注册这个空实现:
替换原来的CustomNormalizers注册代码,改成:
services.AddScoped<ILookupNormalizer, NoOpLookupNormalizer>();
这样ApplicationUserManager构造函数注入的就是这个空实现,既满足基类的依赖要求,又不会执行任何归一化操作。
二、Identity Core 3 Preview4的处理方案
在Core版本中,Identity默认注册了UpperInvariantLookupNormalizer作为ILookupNormalizer的实现,我们需要替换它为空实现,同时按需调整验证逻辑:
复用上面创建的
NoOpLookupNormalizer空实现类。在配置Identity服务时,替换默认的归一化器:
services.AddDefaultIdentity<TblUsers>() .AddEntityFrameworkStores<AbfaContext>(); // 替换为空实现,覆盖默认的UpperInvariantLookupNormalizer services.AddScoped<ILookupNormalizer, NoOpLookupNormalizer>();
- (可选)完全禁用基于归一化的用户名唯一性验证
默认的UserValidator会使用归一化后的用户名检查重复,如果你希望用户名区分大小写(即不做归一化),可以自定义UserValidator:
public class NoNormalizationUserValidator<TUser> : UserValidator<TUser> where TUser : class { public NoNormalizationUserValidator(IdentityErrorDescriber errors) : base(errors) { } public override async Task<IdentityResult> ValidateAsync(UserManager<TUser> manager, TUser user) { var result = new IdentityResult(); // 自定义验证逻辑:直接用原始用户名检查是否重复 var userName = await manager.GetUserNameAsync(user); var existingUser = await manager.FindByNameAsync(userName); if (existingUser != null && !await manager.GetUserIdAsync(existingUser).Equals(await manager.GetUserIdAsync(user))) { result = result.Concat(IdentityResult.Failed(manager.ErrorDescriber.DuplicateUserName(userName))); } // 可添加其他默认验证逻辑(如用户名长度、合法字符检查) return result; } }
然后注册这个自定义验证器:
services.AddScoped<IUserValidator<TblUsers>, NoNormalizationUserValidator<TblUsers>>();
这样就能完全移除Identity中的归一化逻辑,满足你的需求。
内容的提问来源于stack exchange,提问作者LPLN

