ASP.NET Core Identity - Allow optional (yet unique) email address How to allow user registration without requiring an e-mail address (while preserving the dupe-check in case it's present) in ASP.NET Core Identity

ASP.NET Core C# - How to lock an async method according to custom IDs

One of the main reasons I like ASP.NET Core Identity is that it provides all the tools you need to handle user registration: customizable password strength, e-mail verification system, configurable lockout strategies, third-party auth providers support, and so on. All these things - and much more - are already available out of the box, the only thing we need to do is to configure the Identity service to suit our needs - possibly using a couple of (official) NuGet packages to bring some additional juice in.

That said, sometimes you need to do something that isn't natively supported - such as allowing your users to register without requiring them to enter a given e-mail address. Although this isn't a typical requirement, there are some edge-case scenarios where you would want to do that. In my personal experience, this usually happens when those users are added by back-end operators: in other words, non-interactive users that only need to be present in the database (for various reasons), without actually being able to perform the login; however, there could be a lot of other suitable scenarios where you would want to overcome the default ASP.NET Core behavior where the user e-mail address is a required field.

In this post, we'll see how we can do that using a custom (yet simple) OptionalEmailUserValidator class. Are we ready? Let's start!

The issue

Before starting to work on our assignment, let's briefly reproduce the issue we're talking about.

Suppose we try to create our user in the following way:

If we try to do that, we will get a result variable equal to "InvalidEmail", which will be translated into an "Email cannot be null or empty" readable error. This happens because the ASP.NET Identity system wants the user.Email property to be filled with a non-null, non-empty, valid, and unique e-mail address.

Now that we know what we need to overcome, let's see how we can do that.

The (wrong) way to do that

The first thing we might be tempted to do is to configure the identity options in the following way:

This would do something quite similar to what we want: we would be able to specify a null/empty e-mail address. However, the above settings will also disable the dupe-check of the existing e-mail addresses, which is something we might want to preserve for those users that will register (or "be registered") with a valid e-mail address.

The solution

Instead of disabling the dupe-check, we might think of creating a custom email validator and using that instead of the default one. That custom validator should behave in the following way:

  • If the Email property is null or empty, return a IdentityResult.Success (instead of InvalidEmail).
  • If the Email property is present, perform the dupe-check just like the default validator.

Here's the C# source code for a OptionalEmailUserValidator that does just that:

And here's how we can inject it into our web application's ASP.NET Identity service, replacing the default validator:

Be sure to put the above one-liner before the existing builder.Services.AddIdentity() or AddDefaultIdentity() line, otherwise it wouldn't work.


That's it: I sincerely hope that this simple, yet useful technique will help other ASP.NET Core developers looking for a neat and efficient way to allow the use of optional (yet unique) email addresses for their ASP.NET Core Identity users.


About Ryan

IT Project Manager, Web Interface Architect and Lead Developer for many high-traffic web sites & services hosted in Italy and Europe. Since 2010 it's also a lead designer for many App and games for Android, iOS and Windows Phone mobile devices for a number of italian companies. Microsoft MVP for Development Technologies since 2018.

View all posts by Ryan

Leave a Reply

Your email address will not be published. Required fields are marked *

The reCAPTCHA verification period has expired. Please reload the page.

This site uses Akismet to reduce spam. Learn how your comment data is processed.