ABPZero中的Name和SurName处理,以及EmailAddress解决方案(完美)。
使用ABPzero的朋友们都知道,User表中有Name和Surname两个字段,这两个字段对于国内的用户来说相当的不友好。
以及我们的一些系统中是不会涉及到EmailAddress字段。也就是说不会使用邮箱来进行注册的,那么我们怎么解决了。
首先感谢群友https://github.com/maliming 提供的思路。
- 在abpzero中的AbpUser实体中Name和Surname、EmailAddress都是为必填。
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Abp.Configuration;
using Abp.Domain.Entities;
using Abp.Domain.Entities.Auditing;
using Abp.Extensions;
namespace Abp.Authorization.Users
{
/// <summary>
/// Represents a user.
/// </summary>
public abstract class AbpUser<TUser> : AbpUserBase, IFullAudited<TUser>, IPassivable
where TUser : AbpUser<TUser>
{
/// <summary>
/// UserName of the admin.
/// admin can not be deleted and UserName of the admin can not be changed.
/// </summary>
public const string AdminUserName = "admin";
/// <summary>
/// Maximum length of the <see cref="Name"/> property.
/// </summary>
public const int MaxNameLength = 32;
/// <summary>
/// Maximum length of the <see cref="Surname"/> property.
/// </summary>
public const int MaxSurnameLength = 32;
/// <summary>
/// Maximum length of the <see cref="Password"/> property.
/// </summary>
public const int MaxPasswordLength = 128;
/// <summary>
/// Maximum length of the <see cref="Password"/> without hashed.
/// </summary>
public const int MaxPlainPasswordLength = 32;
/// <summary>
/// Maximum length of the <see cref="EmailConfirmationCode"/> property.
/// </summary>
public const int MaxEmailConfirmationCodeLength = 328;
/// <summary>
/// Maximum length of the <see cref="PasswordResetCode"/> property.
/// </summary>
public const int MaxPasswordResetCodeLength = 328;
/// <summary>
/// Maximum length of the <see cref="AuthenticationSource"/> property.
/// </summary>
public const int MaxAuthenticationSourceLength = 64;
/// <summary>
/// Authorization source name.
/// It's set to external authentication source name if created by an external source.
/// Default: null.
/// </summary>
[MaxLength(MaxAuthenticationSourceLength)]
public virtual string AuthenticationSource { get; set; }
/// <summary>
/// Name of the user.
/// </summary>
[Required]
[StringLength(MaxNameLength)]
public virtual string Name { get; set; }
/// <summary>
/// Surname of the user.
/// </summary>
[Required]
[StringLength(MaxSurnameLength)]
public virtual string Surname { get; set; }
/// <summary>
/// Return full name (Name Surname )
/// </summary>
[NotMapped]
public virtual string FullName { get { return this.Name + " " + this.Surname; } }
/// <summary>
/// Password of the user.
/// </summary>
[Required]
[StringLength(MaxPasswordLength)]
public virtual string Password { get; set; }
/// <summary>
/// Is the <see cref="AbpUserBase.EmailAddress"/> confirmed.
/// </summary>
public virtual bool IsEmailConfirmed { get; set; }
/// <summary>
/// Confirmation code for email.
/// </summary>
[StringLength(MaxEmailConfirmationCodeLength)]
public virtual string EmailConfirmationCode { get; set; }
/// <summary>
/// Reset code for password.
/// It's not valid if it's null.
/// It's for one usage and must be set to null after reset.
/// </summary>
[StringLength(MaxPasswordResetCodeLength)]
public virtual string PasswordResetCode { get; set; }
/// <summary>
/// Lockout end date.
/// </summary>
public virtual DateTime? LockoutEndDateUtc { get; set; }
/// <summary>
/// Gets or sets the access failed count.
/// </summary>
public virtual int AccessFailedCount { get; set; }
/// <summary>
/// Gets or sets the lockout enabled.
/// </summary>
public virtual bool IsLockoutEnabled { get; set; }
/// <summary>
/// Gets or sets the phone number.
/// </summary>
public virtual string PhoneNumber {get; set; }
/// <summary>
/// Is the <see cref="AbpUser{TUser}.PhoneNumber"/> confirmed.
/// </summary>
public virtual bool IsPhoneNumberConfirmed { get; set; }
/// <summary>
/// Gets or sets the security stamp.
/// </summary>
public virtual string SecurityStamp { get; set; }
/// <summary>
/// Is two factor auth enabled.
/// </summary>
public virtual bool IsTwoFactorEnabled { get; set; }
/// <summary>
/// Is this user active?
/// If as user is not active, he/she can not use the application.
/// </summary>
public virtual bool IsActive { get; set; }
/// <summary>
/// Login definitions for this user.
/// </summary>
[ForeignKey("UserId")]
public virtual ICollection<UserLogin> Logins { get; set; }
/// <summary>
/// Roles of this user.
/// </summary>
[ForeignKey("UserId")]
public virtual ICollection<UserRole> Roles { get; set; }
/// <summary>
/// Claims of this user.
/// </summary>
[ForeignKey("UserId")]
public virtual ICollection<UserClaim> Claims { get; set; }
/// <summary>
/// Permission definitions for this user.
/// </summary>
[ForeignKey("UserId")]
public virtual ICollection<UserPermissionSetting> Permissions { get; set; }
/// <summary>
/// Settings for this user.
/// </summary>
[ForeignKey("UserId")]
public virtual ICollection<Setting> Settings { get; set; }
public virtual TUser DeleterUser { get; set; }
public virtual TUser CreatorUser { get; set; }
public virtual TUser LastModifierUser { get; set; }
protected AbpUser()
{
IsActive = true;
IsLockoutEnabled = true;
SecurityStamp = SequentialGuidGenerator.Instance.Create().ToString();
}
public virtual void SetNewPasswordResetCode()
{
PasswordResetCode = Guid.NewGuid().ToString("N").Truncate(MaxPasswordResetCodeLength);
}
public virtual void SetNewEmailConfirmationCode()
{
EmailConfirmationCode = Guid.NewGuid().ToString("N").Truncate(MaxEmailConfirmationCodeLength);
}
public override string ToString()
{
return string.Format("[User {0}] {1}", Id, UserName);
}
}
}
以上为ABPZERO源代码中的字段,我们怎么修改呢。
- 修改User实体信息。
打开我们项目中的User.cs实体。
public class User : AbpUser<User>
{
public const string DefaultPassword = "123qwe";
public static string CreateRandomPassword()
{
return Guid.NewGuid().ToString("N").Truncate(16);
}
private new string Name { get; set; }
private new string Surname { get; set; }
[Required(AllowEmptyStrings = true)]
public override string EmailAddress { get; set; }
public static User CreateTenantAdminUser(int tenantId, string emailAddress, string password)
{
return new User
{
TenantId = tenantId,
UserName = AdminUserName,
Name = AdminUserName,
Surname = AdminUserName,
EmailAddress = emailAddress,
Password = new PasswordHasher().HashPassword(password)
};
}
}
可以看到我将Name和SurName字段设置为private,这样设置之后,就有了值对象的感觉,EF在做实体验证的时候就不会对private的属性字段进行验证。
而Emailaddress因为涉及了很多的业务情况,我们不能将它设置为私有访问。
- 修改DbContext
我们打开'CMSDbContext.cs',添加方法
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>().Ignore(a => a.Name);
modelBuilder.Entity<User>().Ignore(a => a.Surname);
modelBuilder.Entity<User>().Property(a => a.EmailAddress).IsOptional();
// modelBuilder.Entity<User>().a => a.Name);
}
覆盖方法‘OnModelCreating’,然后将Name和SurName设置为忽略。
然后将EmailAddress设置为可空。
- 执行迁移
然后执行迁移文件命令:"add-migration Remove_Name_SurName".
然后再执行"update-database",生成的数据库中就不会有“Name”和“Surname”。 - 到目前为止,Name和SurName就不影响功能使用和开发了。
EmailAddress实体字段修改
CheckErrors(await _userManager.CreateAsync(user));
在userManager领域服务中的CreateAsync提供的方法中,检查了EmailAddress 所以我们要重写方法。
修改后的'UserManager.cs'
public class UserManager : AbpUserManager<Role, User>
{
private readonly IUnitOfWorkManager _unitOfWorkManager;
public UserManager(
UserStore userStore,
RoleManager roleManager,
IPermissionManager permissionManager,
IUnitOfWorkManager unitOfWorkManager,
ICacheManager cacheManager,
IRepository<OrganizationUnit, long> organizationUnitRepository,
IRepository<UserOrganizationUnit, long> userOrganizationUnitRepository,
IOrganizationUnitSettings organizationUnitSettings,
ILocalizationManager localizationManager,
ISettingManager settingManager,
IdentityEmailMessageService emailService,
IUserTokenProviderAccessor userTokenProviderAccessor, IUnitOfWorkManager unitOfWorkManager1)
: base(
userStore,
roleManager,
permissionManager,
unitOfWorkManager,
cacheManager,
organizationUnitRepository,
userOrganizationUnitRepository,
organizationUnitSettings,
localizationManager,
emailService,
settingManager,
userTokenProviderAccessor)
{
_unitOfWorkManager = unitOfWorkManager1;
}
public override async Task<IdentityResult> CheckDuplicateUsernameOrEmailAddressAsync(long? expectedUserId, string userName, string emailAddress)
{
var user = (await FindByNameAsync(userName));
if (user != null && user.Id != expectedUserId)
{
return AbpIdentityResult.Failed(string.Format(L("Identity.DuplicateName"), userName));
}
return IdentityResult.Success;
}
private string L(string name)
{
return LocalizationManager.GetString(AbpZeroConsts.LocalizationSourceName, name);
}
public override async Task<IdentityResult> CreateAsync(User user)
{
var result = await CheckDuplicateUsernameOrEmailAddressAsync(user.Id, user.UserName, user.EmailAddress);
if (!result.Succeeded)
{
return result;
}
user.EmailAddress = string.Empty;
var tenantId = GetCurrentTenantId();
if (tenantId.HasValue && !user.TenantId.HasValue)
{
user.TenantId = tenantId.Value;
}
try
{
return await base.CreateAsync(user);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
private int? GetCurrentTenantId()
{
if (_unitOfWorkManager.Current != null)
{
return _unitOfWorkManager.Current.GetTenantId();
}
return AbpSession.TenantId;
}
}
截止以上我们的功能EmailAddress功能就算正常了。
以下为旧文,大家可以自己对比观察。
使用ABPzero的朋友们都知道,User表中有Name和Surname两个字段,这两个字段对于国内的用户来说相当的不友好。
我们在尝试了很多的方法之后,发现无法完美将他们干掉。
所以尝试使用了一个比较不友好加流氓的方式来使用它。
如果你在使用的过程有更加美好的解决方案,可以提供给我们。
以及到https://github.com/aspnetboilerplate/module-zero/issues/337 这里提出方法。
开始流程:
首先到 "CMSDbContext.cs"中添加覆盖方法,找不到的如图所示:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>().Ignore(a => a.Name);
modelBuilder.Entity<User>().Ignore(a => a.Surname);
}
然后执行迁移文件命令:"add-migration Remove_Name_SurName".
然后再执行"update-database",生成的数据库中就不会有“Name”和“Surname”。
但是坑爹的地方就在这,我们在执行Insert(User)方法的时候还是会报错。对于这种情况。我深深的感觉到了无力(感觉身体被Kid掏空)。
没有其他办法,只能暴力解决。在方法中,默认添加Name和Surname的值,只是为了绕过Eentityframework的实体验证。。
如下图所示。

这样绕过之后,发现可以正常的处理信息。

User表中的Name和Surname也不在了。唯一不友好的地方就是坑爹。。
以上算是一个坑爹解决方法。
如果你有更加友好的解决方法。联系我。
ABPZero中的Name和SurName处理,以及EmailAddress解决方案(完美)。的更多相关文章
- ABPZero中的Name和SurName处理
使用ABPzero的朋友们都知道,User表中有Name和Surname两个字段,这两个字段对于国内的用户来说相当的不友好. 我们在尝试了很多的方法之后,发现无法完美将他们干掉. 所以尝试使用了一个比 ...
- ueditor1.3.6jsp版在struts2应用中上传图片报"未找到上传文件"解决方案
摘要: ueditor1.3.6jsp版在struts2应用中上传图片报"未找到上传文件"解决方案 在struts2应用中使用ueditor富文本编辑器上传图片或者附件时,即使配置 ...
- JSP中pageEncoding和charset区别,中文乱码解决方案(转载)
转载自:JSP中pageEncoding和charset区别,中文乱码解决方案 JSP指令标签中<%@ page contentType="text/html;charset=GB23 ...
- iOS 开发中,关于xxx.xcodeproj 文件冲突的解决方案 (以后谁不会了,直接将连接给他)
iOS 开发中,关于xxx.xcodeproj 文件冲突的解决方案 (一有冲突要手把手教一遍,太麻烦了,现在总结下,以后谁不会了,连接直接发他). 关于xxx.xcodeproj 文件冲突的话,是比较 ...
- MySQL安装过程中对The error code is 2203的解决方案
MySQL安装过程中对The error code is 2203的解决方案 1.问题描述 Windows系统安装MySQL遇到The error code is 2203.,具体描述如下 The i ...
- vue 在有大数据量的 table 中使用弹窗 input 输入数据时卡顿解决方案
vue 在有大数据量的 table 中使用弹窗 input 输入数据时卡顿解决方案 原因:vue在进行输入时,进行了多次的render刷新渲染操作,导致了input框输入时发生的卡顿现象 解决方法:在 ...
- VS·调试过程中某个操作导致调试突然退出之解决方案
阅文时长 | 0.11分钟 字数统计 | 232字符 主要内容 | 1.引言&背景 2.声明与参考资料 『VS·调试过程中某个操作导致调试突然退出之解决方案』 编写人 | SCscHero 编 ...
- 在ABPZERO中,扩展实体的方法。
内容 介绍 扩展的抽象实体 将新属性添加给用户 添加迁移 在界面上显示地址 在用户编辑/添加功能中添加地址 扩展的非抽象类实体 获得版本的派生实体 添加迁移 在界面上添加价格 在创建/编辑版本功能中加 ...
- 在AbpZero中hangfire后台作业的使用——hangfire的调度
在abpzero框架中,hangfiire通过依赖注入来进行接口的调用 hangfire的事件处理分为以下几种: 1.基于队列的任务处理(Fire-and-forget jobs) var jobId ...
随机推荐
- Django之验证
1. 滑动验证码补充说一下 极验科技:https://docs.geetest.com/install/deploy/server/python#下载SDK按照人家的实例操作即可 1.pip inst ...
- HTTP的Referrer和Referrer Policy设置
Referrer referrer是HTTP请求header的报文头,用于指明当前流量的来源参考页面.通过这个信息,我们可以知道访客是怎么来到当前页面的.这对于Web Analytics非常重要,可以 ...
- scrapy之spider模块
scrapy中的spider的用法 : 1.scrapy命令行可以传参数给构造器 scrapy crawl myspider -a category=electronics 构造器接收传入的参数 im ...
- 在ASP.NET Core中使用多环境
原文地址:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments?view=aspnetcore-2.1#star ...
- MySQL 并行复制演进及 MySQL 8.0 中基于 WriteSet 的优化
MySQL 8.0 可以说是MySQL发展历史上里程碑式的一个版本,包括了多个重大更新,目前 Generally Available 版本已经已经发布,正式版本即将发布,在此将介绍8.0版本中引入的一 ...
- BOM 清除
[root@test3 11]# gcc 11.2.c11.2.c:1: 错误:程序中有游离的 ‘\357’ 8进制,相当于16进制 ef11.2.c:1: 错误:程序中有游离的 ‘\273’11.2 ...
- win7系统保护配置现错误“文件名、目录名或卷标语法不正确。(0x8007007B)
windows7下系统保护功能很是鸡肋,有事会出现一下两个问题: 1.出现错误“文件名.目录名或卷标语法不正确.(0x8007007B) 2.保护设置列表中出现“Windows7_os(c:)(找不到 ...
- 查看tomcat项目中,具体占用cpu高的线程。
1.查看主进程占用cpu高: 此处主进程:27823 ~]# top top - :0: up days, :, 3 users, load average: 13.12, 13.31, 13.23 ...
- Java用户名登录学生信息管理系统并对其进行增删改查操作
package zzzzzzzz; import java.io.*;//作者:凯鲁嘎吉 - 博客园//http://www.cnblogs.com/kailugaji/ public class T ...
- Pycharm 安装 idea VIM
直接在线安装 1.File->Settings->Plugins->Install JetBrains Plugins 2.点击install安装ideavim 3.也许需要的切换v ...