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 ...
随机推荐
- python爬虫之Beautifulsoup学习笔记
相关内容: 什么是beautifulsoup bs4的使用 导入模块 选择使用解析器 使用标签名查找 使用find\find_all查找 使用select查找 首发时间:2018-03-02 00:1 ...
- javascript模块化编程-详解立即执行函数表达式IIFE
一.IIFE解释 全拼Imdiately Invoked Function Expression,立即执行的函数表达式. 像如下的代码所示,就是一个匿名立即执行函数: (function(windo ...
- Python中DataFrame去重
# 去除重复行数据 keep:'first':保留重复行的第一行,'last':保留重复行的最后一行,False:删除所有重复行df = df.drop_duplicates( subset=['YJ ...
- EntityFramework Code-First 简易教程(九)-------一对多
一对多(One-to-Many)关系: 下面,我们来介绍Code-First的一对多关系,比如,在一个Standard(年级)类中包含多个Student类. 如果想了解更多关于one-to-one,o ...
- Linux下内存查看命令
在Linux下面,我们常用top命令来查看系统进程,top也能显示系统内存.我们常用的Linux下查看内容的专用工具是free命令. Linux下内存查看命令free详解: 在Linux下查看内存我们 ...
- Web服务并发I/O模型
I/O模型: 阻塞型.非阻塞型.复用型.信号驱动型.异步 同步/异步: 关注消息通知机制 消息通知: 同步:等待对方返回消息 异步:被调用者通过状态.通知或回调机制通知调用者被调用者的运行状态 阻塞/ ...
- Android 用webService产生java.lang.ClassCastException: org.ksoap2.serialization.SoapPrimitive错误的解决(转)
在做android Webservice开发的时候一般情况下大家接受webservice服务器返回值的时候都是使用 SoapObject soapObject = (SoapObject) enve ...
- django知识点回顾(上)
Django---知识点: 1. 配置文件: media: avatar = models.FileField(upload_to='avatar')#数据库里的model MEDIA_ROOT=os ...
- PCB (2)创建新工程原理图
1创建一个新项目 2创建一个新的原理图图纸 3将原理图图纸添加到项目 4设置原理图选项 修改单位 设置图纸大小 图纸附加说明 5绘制原理图 打开库 之后连续放置的器件会在此基础上+1 名字 描述 6 ...
- ethereum/EIPs-158 State clearing 被EIP-161取代
eip title author type category status created superseded-by 158 State clearing Vitalik Buterin Stand ...