Asp.Net Identity save user without email
Asked Answered
B

7

40

I want to save user without email, like this:

var user = new ApplicationUser { UserName = model.Name };
var result = await UserManager.CreateAsync(user);

But I got error "Email cannot be null or empty". Is there any solution for this? Or it is impossible?

Blackball answered 12/1, 2015 at 15:19 Comment(1)
I have the exact same problem, though Email is provided result always returns null but successful. Is there a solution to this?Outshout
L
9

Identity depends on email as a way to reset user password.

However, ignoring email is not simple, but possible. You'll need to implement Microsoft.AspNet.Identity.IIdentityValidator interface that ignores the lack of email:

namespace Microsoft.AspNet.Identity
{
  /// <summary>
  /// Used to validate an item
  /// 
  /// </summary>
  /// <typeparam name="T"/>
  public interface IIdentityValidator<in T>
  {
    /// <summary>
    /// Validate the item
    /// 
    /// </summary>
    /// <param name="item"/>
    /// <returns/>
    Task<IdentityResult> ValidateAsync(T item);
  }
}

And then in ApplicationUserManager assign your own implementation to property UserValidator.

If you really need this, you can get the original source code for UserValidator by decompiling Microsoft.AspNet.Identity.UserValidator class and peeking into the existing source code and removing cheecking for email.

However, I'm not sure how the rest of the framework will react on lack of email on user. Probably you'll get exceptions in other operations.

Locksmith answered 12/1, 2015 at 19:53 Comment(0)
W
91

I know this is old, but I disagree with the accepted answer, since the question is tagged as asp.net-identity-2. For the benefit of future readers, ASP.NET Identity 2.0 has a very simple solution to this problem:

public class ApplicationUserManager : UserManager<ApplicationUser>
{
    ...snip...
    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) 
    {
        var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
        manager.UserValidator = new UserValidator<ApplicationUser>(manager)
        {
            // This disables the validation check on email addresses
            RequireUniqueEmail = false
        };
        ...snip...
    }
}

In UserValidator<TUser>, the Task<IdentityResult> ValidateAsync(T item) implementation checks this flag and determines if it should run email validation:

if (this.RequireUniqueEmail)
{
    await this.ValidateEmail(item, list);
}

Since you want to save users without an email address, this is how you should do it.

CAUTION: This should only be used when email addresses are not collected. If you want to collect and validate email addresses, but make them optional during registration, you should use a custom IIdentityValidator.

Whitethroat answered 26/2, 2015 at 16:40 Comment(1)
Plus one for your avatar. ...and the correct answer to the question, of course! : )Gamin
B
34

ASP Identity 2.2 can be set in App_Start\IdentityConfig.cs

    manager.UserValidator = new UserValidator<ApplicationUser>(manager)
    {
        AllowOnlyAlphanumericUserNames = false,
        RequireUniqueEmail = false
    };
Bahuvrihi answered 8/6, 2015 at 10:33 Comment(0)
D
11

In startup file you can disable RequireUniqueEmail by access IdentityOptions configuration Also here you can change complexity of password , Lockout,...

  services.Configure<IdentityOptions>(x =>
        {
            x.User.RequireUniqueEmail = false;

            //x.Password.RequireUppercase = false; => other condition for identity

        });

you should use Microsoft.AspnetCore.Identity, address of doc here

Thank you @PBO and you can also change identity options like below

 services.AddDefaultIdentity<IdentityUser>(
            options=> { 
                options.SignIn.RequireConfirmedAccount = false;
                options.User.RequireUniqueEmail = false;
                options.Password.RequireUppercase = false;
            })
            .AddEntityFrameworkStores<BookShopDbContext>();
Destruction answered 21/7, 2019 at 12:30 Comment(1)
you can access the same functionality in services.AddDefaultIdentityLindemann
L
9

Identity depends on email as a way to reset user password.

However, ignoring email is not simple, but possible. You'll need to implement Microsoft.AspNet.Identity.IIdentityValidator interface that ignores the lack of email:

namespace Microsoft.AspNet.Identity
{
  /// <summary>
  /// Used to validate an item
  /// 
  /// </summary>
  /// <typeparam name="T"/>
  public interface IIdentityValidator<in T>
  {
    /// <summary>
    /// Validate the item
    /// 
    /// </summary>
    /// <param name="item"/>
    /// <returns/>
    Task<IdentityResult> ValidateAsync(T item);
  }
}

And then in ApplicationUserManager assign your own implementation to property UserValidator.

If you really need this, you can get the original source code for UserValidator by decompiling Microsoft.AspNet.Identity.UserValidator class and peeking into the existing source code and removing cheecking for email.

However, I'm not sure how the rest of the framework will react on lack of email on user. Probably you'll get exceptions in other operations.

Locksmith answered 12/1, 2015 at 19:53 Comment(0)
F
7

If anyone is still struggling with this...

Set options.User.RequireUniqueEmail=true, create a custom user validator and register it before registering Identity. This will make the email optional but still require it to be unique if entered.

in ConfigureServices(IServiceCollection services):

services.AddTransient<IUserValidator<ApplicationUser>, OptionalEmailUserValidator<MonotypeIdentityUser>>();
services.AddIdentity(...);

The custom user validator class:

public class OptionalEmailUserValidator<TUser> : UserValidator<TUser> where TUser : class
{
    public OptionalEmailUserValidator(IdentityErrorDescriber errors = null) : base(errors)
    {
    }

    public override async Task<IdentityResult> ValidateAsync(UserManager<TUser> manager, TUser user)
    {
        var result = await base.ValidateAsync(manager, user);
        
        if(!result.Succeeded && String.IsNullOrWhiteSpace(await manager.GetEmailAsync(user)))
        {
            var errors = result.Errors.Where(e => e.Code != "InvalidEmail");

            result = errors.Count() > 0 ? IdentityResult.Failed(errors.ToArray()) : IdentityResult.Success;
        }           

        return result;
    }
}
Frankel answered 12/10, 2021 at 20:7 Comment(1)
Great answer, you can also just do a services.AddIdentity().AddUserValidator<OptionalEmailUserValidator<ApplicationUser>>() to inject in a one linerRabah
E
3

You can create a user account without Email by editing the identity file in the App_Start folder and changing the RequireUniqueEmail value to False to avoid the Email validator`

  manager.UserValidator = new UserValidator<ApplicationUser>(manager)
        {
            AllowOnlyAlphanumericUserNames = false,
            RequireUniqueEmail = false,
        };

`

Esch answered 31/10, 2021 at 17:28 Comment(0)
W
0

Actually there is a better way. Alter the validation for just when you need to ignore it and then restore it back when done. (Don't use async in this case because another thread might be need to update(?))

// first create/update the identity!!! 
user.PasswordHash = UserManager.PasswordHasher.HashPassword(model.Password); //hash and update directly

// alter
UserManager.UserValidator = new UserValidator<StoreUser>(UserManager)
{
    AllowOnlyAlphanumericUserNames = false,
    RequireUniqueEmail = false
};

var result = UserManager.Update(user);

// restore... 
UserManager.UserValidator = new UserValidator<StoreUser>(UserManager)
{
    AllowOnlyAlphanumericUserNames = false,
    RequireUniqueEmail = true
};
Walling answered 2/6, 2016 at 21:47 Comment(3)
this is a really, really bad idea. What happens if two people update their user at the same time? Race condition that's what. Why wouldn't you just set this once on startup like everyone else suggests?Selfopinionated
What if I want to store e-mail and its associated fields now found in AspNetUsers in a separate table? Same with phone fields?Greyso
@muybn, I managed to seperate phone number, email address into a AccountContact table. Its a lot of work and unless you have specific reason for doing it, its a waste of time. I got a lot of errors that required a lot of time looking through the source code to understand what is going on. Initially I removed username too but restored it just to get my project going (I fill it with either phone number or email depending on what the customer provided).Lindemann

© 2022 - 2024 — McMap. All rights reserved.