使用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解决方案(完美)。的更多相关文章

  1. ABPZero中的Name和SurName处理

    使用ABPzero的朋友们都知道,User表中有Name和Surname两个字段,这两个字段对于国内的用户来说相当的不友好. 我们在尝试了很多的方法之后,发现无法完美将他们干掉. 所以尝试使用了一个比 ...

  2. ueditor1.3.6jsp版在struts2应用中上传图片报"未找到上传文件"解决方案

    摘要: ueditor1.3.6jsp版在struts2应用中上传图片报"未找到上传文件"解决方案 在struts2应用中使用ueditor富文本编辑器上传图片或者附件时,即使配置 ...

  3. JSP中pageEncoding和charset区别,中文乱码解决方案(转载)

    转载自:JSP中pageEncoding和charset区别,中文乱码解决方案 JSP指令标签中<%@ page contentType="text/html;charset=GB23 ...

  4. iOS 开发中,关于xxx.xcodeproj 文件冲突的解决方案 (以后谁不会了,直接将连接给他)

    iOS 开发中,关于xxx.xcodeproj 文件冲突的解决方案 (一有冲突要手把手教一遍,太麻烦了,现在总结下,以后谁不会了,连接直接发他). 关于xxx.xcodeproj 文件冲突的话,是比较 ...

  5. MySQL安装过程中对The error code is 2203的解决方案

    MySQL安装过程中对The error code is 2203的解决方案 1.问题描述 Windows系统安装MySQL遇到The error code is 2203.,具体描述如下 The i ...

  6. vue 在有大数据量的 table 中使用弹窗 input 输入数据时卡顿解决方案

    vue 在有大数据量的 table 中使用弹窗 input 输入数据时卡顿解决方案 原因:vue在进行输入时,进行了多次的render刷新渲染操作,导致了input框输入时发生的卡顿现象 解决方法:在 ...

  7. VS·调试过程中某个操作导致调试突然退出之解决方案

    阅文时长 | 0.11分钟 字数统计 | 232字符 主要内容 | 1.引言&背景 2.声明与参考资料 『VS·调试过程中某个操作导致调试突然退出之解决方案』 编写人 | SCscHero 编 ...

  8. 在ABPZERO中,扩展实体的方法。

    内容 介绍 扩展的抽象实体 将新属性添加给用户 添加迁移 在界面上显示地址 在用户编辑/添加功能中添加地址 扩展的非抽象类实体 获得版本的派生实体 添加迁移 在界面上添加价格 在创建/编辑版本功能中加 ...

  9. 在AbpZero中hangfire后台作业的使用——hangfire的调度

    在abpzero框架中,hangfiire通过依赖注入来进行接口的调用 hangfire的事件处理分为以下几种: 1.基于队列的任务处理(Fire-and-forget jobs) var jobId ...

随机推荐

  1. python爬虫之Beautifulsoup学习笔记

    相关内容: 什么是beautifulsoup bs4的使用 导入模块 选择使用解析器 使用标签名查找 使用find\find_all查找 使用select查找 首发时间:2018-03-02 00:1 ...

  2. javascript模块化编程-详解立即执行函数表达式IIFE

    一.IIFE解释 全拼Imdiately Invoked Function Expression,立即执行的函数表达式.  像如下的代码所示,就是一个匿名立即执行函数: (function(windo ...

  3. Python中DataFrame去重

    # 去除重复行数据 keep:'first':保留重复行的第一行,'last':保留重复行的最后一行,False:删除所有重复行df = df.drop_duplicates( subset=['YJ ...

  4. EntityFramework Code-First 简易教程(九)-------一对多

    一对多(One-to-Many)关系: 下面,我们来介绍Code-First的一对多关系,比如,在一个Standard(年级)类中包含多个Student类. 如果想了解更多关于one-to-one,o ...

  5. Linux下内存查看命令

    在Linux下面,我们常用top命令来查看系统进程,top也能显示系统内存.我们常用的Linux下查看内容的专用工具是free命令. Linux下内存查看命令free详解: 在Linux下查看内存我们 ...

  6. Web服务并发I/O模型

    I/O模型: 阻塞型.非阻塞型.复用型.信号驱动型.异步 同步/异步: 关注消息通知机制 消息通知: 同步:等待对方返回消息 异步:被调用者通过状态.通知或回调机制通知调用者被调用者的运行状态 阻塞/ ...

  7. Android 用webService产生java.lang.ClassCastException: org.ksoap2.serialization.SoapPrimitive错误的解决(转)

    在做android  Webservice开发的时候一般情况下大家接受webservice服务器返回值的时候都是使用 SoapObject soapObject = (SoapObject) enve ...

  8. django知识点回顾(上)

    Django---知识点: 1. 配置文件: media: avatar = models.FileField(upload_to='avatar')#数据库里的model MEDIA_ROOT=os ...

  9. PCB (2)创建新工程原理图

    1创建一个新项目 2创建一个新的原理图图纸 3将原理图图纸添加到项目 4设置原理图选项 修改单位 设置图纸大小 图纸附加说明 5绘制原理图 打开库 之后连续放置的器件会在此基础上+1 名字 描述 6 ...

  10. ethereum/EIPs-158 State clearing 被EIP-161取代

    eip title author type category status created superseded-by 158 State clearing Vitalik Buterin Stand ...