3
votes

Asp.net Identity doesn't allow same username for two or more users even if the primary key in AspNetUsers table is the Id, so i tried to ovveride the UserValidator of the UserManager but it stills give me errors that i can't give two users the same username , here is the custom validator:

public class CustomUserValidator<TUser> : IIdentityValidator<TUser>
 where TUser : ApplicationUser, Microsoft.AspNet.Identity.IUser
{
    private readonly UserManager<TUser> _manager;

    public CustomUserValidator()
    {
    }

    public CustomUserValidator(UserManager<TUser> manager)
    {
        _manager = manager;
    }

    public async Task<IdentityResult> ValidateAsync(TUser item)
    {
        var errors = new List<string>();


        if (_manager != null)
        {
            var otherAccount = await _manager.FindByNameAsync(item.UserName);
            if (otherAccount != null && otherAccount.CodeClient == item.CodeClient)
                errors.Add("Utilisateur existant.");
        }

        return errors.Any()
            ? IdentityResult.Failed(errors.ToArray())
            : IdentityResult.Success;
    }
}

and in the constructor of my controller i change the uservalidator property like this :

public UsersRootController(UserManager<ApplicationUser> userManager, RoleManager<IdentityRole> roleManager)
    {
        UserManager = userManager;
        RoleManager = RoleManager;
        UserManager.UserValidator = new CustomUserValidator<ApplicationUser>(userManager);
    }

When i try to call the createasync method :

  var user = new ApplicationUser() { UserName = model.UserName, Email = model.Email, Nom = model.Nom, Prenom = model.Prenom, IsEnabled = model.IsEnabled, CodeClient = model.Client };
   resultUser = await UserManager.CreateAsync(user, model.Password);

It uses my custom validator but returns always false .

Is there any way to fix that ?

1

1 Answers

1
votes

I had a same problem but with Role.

The problem is Microsoft strategy against validation! He check uniqueness through IIdentityValidator and also inside of IdentityDbContext. why two times? I don't know! To solve this problem take a look into the source code (here : https://aspnetidentity.codeplex.com/SourceControl/latest#src/Microsoft.AspNet.Identity.EntityFramework/IdentityDbContext.cs) and simply override it like something I did for Role :

public class ApplicationIdentityDbContext : IdentityDbContext<...>
{
    protected override System.Data.Entity.Validation.DbEntityValidationResult ValidateEntity(System.Data.Entity.Infrastructure.DbEntityEntry entityEntry, IDictionary<object, object> items)
    {
        if (entityEntry != null && entityEntry.State == EntityState.Added)
        {
            //NOTE : change the following codes to support your needs!
            var role = entityEntry.Entity as ApplicationRole;
            if (role != null)
            {
                var errors = new List<DbValidationError>();
                return new DbEntityValidationResult(entityEntry, errors);
            }
        }

        return base.ValidateEntity(entityEntry, items);

    }
}

After that you should force your Store, to use this new context.