ABPZero中的Name和SurName处理
使用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处理的更多相关文章
- ABPZero中的Name和SurName处理,以及EmailAddress解决方案(完美)。
使用ABPzero的朋友们都知道,User表中有Name和Surname两个字段,这两个字段对于国内的用户来说相当的不友好. 以及我们的一些系统中是不会涉及到EmailAddress字段.也就是说不会 ...
- 在ABPZERO中,扩展实体的方法。
内容 介绍 扩展的抽象实体 将新属性添加给用户 添加迁移 在界面上显示地址 在用户编辑/添加功能中添加地址 扩展的非抽象类实体 获得版本的派生实体 添加迁移 在界面上添加价格 在创建/编辑版本功能中加 ...
- 在AbpZero中hangfire后台作业的使用——hangfire的调度
在abpzero框架中,hangfiire通过依赖注入来进行接口的调用 hangfire的事件处理分为以下几种: 1.基于队列的任务处理(Fire-and-forget jobs) var jobId ...
- 在AbpZero中hangfire后台作业的使用——开启hangfire
AbpZero框架已经集成了hangfire,但它默认是关闭的,我们可以在运行站点下的Startup.cs文件中把这行代码注释取消就行了,代码如下: //Hangfire (Enable to ...
- abp去掉AbpUser中的Name,Surname,去掉姓和名分离
abp是国外的框架,默认的框架中的AbpUser表中的Name和Surname是分开的,这不符合国情:可以先去掉 1. 在User类中重写Name和Surname,并设置为私有 2. 在DbConte ...
- AbpZero双重认证之短信的坑
一.什么是双重认证 所谓双重认证简单来说就是除了用户名密码方式外,还额外增加了一道登录屏障.登录时先输入用户名和密码,正确后会向邮箱或手机号发送一个验证码(取决于您采用何种方式,甚至可以采用银行的电子 ...
- map对象建立家族姓氏查询
题目:定义一个map对象,其元素的键是家族姓氏,而值是存储该家族孩子名字的vector对象.为这个map容器输入至少六个条目.通过基于家族姓氏的查询检测你的程序,查询应输出该家族所有孩子的名字. // ...
- ABP module-zero +AdminLTE+Bootstrap Table+jQuery权限管理系统第十三节--RBAC模式及ABP权限管理(附送福利)
ABP+AdminLTE+Bootstrap Table权限管理系统一期 Github:https://github.com/Jimmey-Jiang/ABP-ASP.NET-Boilerplate- ...
- ABP入门系列(9)——权限管理
ABP入门系列目录--学习Abp框架之实操演练 源码路径:Github-LearningMpaAbp 完成了简单的增删改查和分页功能,是不是觉得少了点什么? 是的,少了权限管理.既然涉及到了权限,那我 ...
随机推荐
- 基于fiddler的APP抓包及服务端模拟
在HTTP接口的测试过程中,一般我们会按照如下的步骤进行: 1)测试环境的准备 2)HTTP消息体的构造 3)HTTP消息的发送及断言 如果我们可以拿到项目组的接口文档,并且HTTP后台服务是可以工作 ...
- 更改Debian Linux里面的EDT时区为CST时区
Debian按默认安装,设置的是EDT时区.这样跟我们的系统就都对不上,因此得 改回CST. 只需要两步即可: 使用vi编辑/etc/timezone,把timezone文件的内容更改为:Asia/S ...
- jQuery的动态绑定事件的应用
注意:bind()的事件绑定是只对当前页面选中的元素有效.如果你想对动态创建的元素bind()事件,是没有办法达到效果的 <script src="jquery-1.11.2.min. ...
- 查找第K小数
题目描述 查找一个数组的第K小的数,注意同样大小算一样大. 如 2 1 3 4 5 2 第三小数为3. 输入描述: 输入有多组数据.每组输入n,然后输入n个整数(1<=n<=1000), ...
- 从零开始部署小型企业级虚拟桌面 -- Vmware Horizon View 6 For Linux VDI -- 概念简介
什么是桌面虚拟化? 桌面虚拟化有很多概念,此处谈论的,是指的一般企业使用的“服务器 + 虚拟机 + 云终端”的方式来实现的. 桌面虚拟化的原理是什么? 桌面虚拟化看上去高大上,实际上原理非常的简单.拿 ...
- 1029: [JSOI2007]建筑抢修
1029: [JSOI2007]建筑抢修 Time Limit: 4 Sec Memory Limit: 162 MBSubmit: 2382 Solved: 1033[Submit][Statu ...
- HTML超文本标记语言-基础标签整理
第一章 <META>标签: <meta http-equiv="Content-Type" Content="text/html;charset=gb2 ...
- 自学 iOS - 三十天三十个 Swift 项目 第一天
最近公司项目不是很忙,偶然间看到编程语言排行榜,看到swift 已经排到前10了,然OC排名也越来越后了,感觉要上车了,虽然现在项目都是用OC写的,但是swift是一种趋势.在网上看到"自学 ...
- HttpServletResponse对象介绍
一.HttpServletResponse对象介绍
- DevOps的几个场景
名词: 服务发现: 用来确保服务的位置无关性,通过服务名来查询获得服务的实际地址. 名字解析: 用来确保服务器位置无关性,通过机器名查询获得机器的实际IP地址. 场景一: 特点: 应用少,流量轻,数台 ...