Invalid UserName in ASP.NET Core 6

mostafa ahmed 41 Reputation points
2024-07-22T09:02:47.1366667+00:00

I am working on an ASP.NET Core 6 MVC application that uses ASP.NET Core Identity. When I try to create a new user using the UserManager, I get this error:

User name ' ' is invalid, can only contain letters or digits

Username do not has any whitespaces.

When I try to create new user I get the error:

var user = new User
 {
     UserName = "SpecialName",
     Email = "******@domain.com"
 };

 var result = await _userManager.CreateAsync(user, "pAssR!43");

The Code in program file:

builder.Services.AddIdentity<User, Role>(options =>
{
     options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
     options.User.RequireUniqueEmail = false;
})
.AddEntityFrameworkStores<School.Database.SchoolContext>()
.AddUserManager<UserManager<User>>()
.AddClaimsPrincipalFactory<ApplicationUserClaimsPrincipalFactory>()
.AddDefaultTokenProviders();
Entity Framework Core
Entity Framework Core
A lightweight, extensible, open-source, and cross-platform version of the Entity Framework data access technology.
778 questions
ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,786 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
11,308 questions
{count} votes

Accepted answer
  1. Jalpa Panchal-MSFT 795 Reputation points Microsoft Vendor
    2024-07-23T06:53:35.7733333+00:00

    As the Asp.net Identity has its own username property so you could try to override by using the below code:

    Modelx.cs:

    using Microsoft.AspNetCore.Authentication;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.Extensions.Options;
    using System.Resources;
    namespace School.Web.Help
    {
        public class AppUser : IdentityUser<string>
        {
            public string Id { get; set; } = null!;
            public string? Email { get; set; }
            public bool EmailConfirmed { get; set; }
            public string? PasswordHash { get; set; }
            public string? SecurityStamp { get; set; }
            public string? PhoneNumber { get; set; }
            public bool PhoneNumberConfirmed { get; set; }
            public bool TwoFactorEnabled { get; set; }
            public DateTime? LockoutEndDateUtc { get; set; }
            public bool LockoutEnabled { get; set; }
            public int AccessFailedCount { get; set; }
            public override string UserName { get; set; } = null!;
            public string? Name { get; set; }
            public string? NormalizedUserName { get; set; }
            public string? NormalizedEmail { get; set; }
            public string? ConcurrencyStamp { get; set; }
            public DateTimeOffset? LockoutEnd { get; set; }
            public string? FirstName { get; set; }
            public string? LastName { get; set; }
        }
        
        public class AppRole : IdentityRole<string>
        {
            public string Id { get; set; }
            public string Name { get; set; }
        }
        public class AppRoleClaim : IdentityRoleClaim<string>
        {
            public int Id { get; set; }
            public string RoleId { get; set; } = null!;
            public string? ClaimType { get; set; }
            public string? ClaimValue { get; set; }
        }
        public class AppUserClaim : IdentityUserClaim<string>
        {
            public string Id { get; set; }
            public string UserId { get; set; } = null!;
            public string? ClaimType { get; set; }
            public string? ClaimValue { get; set; }
        }
        public class AppUserLogin : IdentityUserLogin<string>
        {
            public string LoginProvider { get; set; }
            public string ProviderKey { get; set; }
            public string UserId { get; set; }
        }
        public class AppUserRole : IdentityUserRole<string>
        {
            public string Id { get; set; }
            public string RoleId { get; set; }
        }
        public class AppUserToken : IdentityUserToken<string>
        {
            public string UserId { get; set; } = null!;
            public string LoginProvider { get; set; } = null!;
            public string Name { get; set; } = null!;
            public string? Value { get; set; }
        }
        public sealed class ApplicationUserClaimsPrincipalFactory : UserClaimsPrincipalFactory<AppUser, AppRole>
        {
            public ApplicationUserClaimsPrincipalFactory(UserManager<AppUser> userManager, RoleManager<AppRole> roleManager, IOptions<IdentityOptions> options) : base(userManager, roleManager, options)
            {
            }
        }
    }
    

    AccountController.cs:

    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
    using Microsoft.AspNetCore.Identity.UI.Services;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.WebUtilities;
    using School.ViewModel;
    using System.Text.Encodings.Web;
    using System.Text;
    using School.Web.Help;
    // /Account/Register
    namespace School.Web.Controllers
    {
        public class AccountController : Controller
        {
            private SignInManager<AppUser> _signInManager;
            private UserManager<AppUser> _userManager;
            private readonly IHttpContextAccessor _accessor;
            public AccountController(UserManager<AppUser> userManager, SignInManager<AppUser> signInManager, IHttpContextAccessor accessor)
            {
                _userManager = userManager;
                _signInManager = signInManager;
                _accessor = accessor;
            }
            [AllowAnonymous]
            public async Task<IActionResult> Register()
            {
                var user = new AppUser
                {
                    Id = "111",
                    UserName = "qwerty",
                    Email = "******@gmail.com",
                    EmailConfirmed = true
                };
                var result = await _userManager.CreateAsync(user, "123123-Aa");
                int sfd = 4;
                if (result.Succeeded)
                {
                    //await SignInManager.SignInAsync(user, isPersistent: false);
                    return RedirectToAction("Index", "Home");
                }
                return View();
            }
            [HttpPost]
            [AllowAnonymous]
            [ValidateAntiForgeryToken]
            public async Task<ActionResult> Register(RegisterVM model)
            {
                if (ModelState.IsValid)
                {
                    var user = new AppUser
                    {
                        
                        UserName = model.Email,
                        Email = model.Email,
                        EmailConfirmed = true
                    };
                    var result = await _userManager.CreateAsync(user, model.Password);
                    if (result.Succeeded)
                    {
                        await _signInManager.SignInAsync(user, isPersistent: false);
                        return RedirectToAction("Index", "Home");
                    }
                    foreach (var error in result.Errors)
                    {
                        ModelState.AddModelError(string.Empty, error.Description);
                    }
                }
                // If we got this far, something failed, redisplay form
                return View(model);
            }
            private IdentityUser CreateUser()
            {
                try
                {
                    return Activator.CreateInstance<IdentityUser>();
                }
                catch
                {
                    throw new InvalidOperationException($"Can't create an instance of '{nameof(IdentityUser)}'. " +
                        $"Ensure that '{nameof(IdentityUser)}' is not an abstract class and has a parameterless constructor, or alternatively " +
                        $"override the register page in /Areas/Identity/Pages/Account/Register.cshtml");
                }
            }
            [AllowAnonymous]
            public ActionResult Login(string returnUrl)
            {
                return View();
            }
            //
            // POST: /Account/Login
            [ValidateAntiForgeryToken]
            [HttpPost]
            [AllowAnonymous]
            public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
            {
                if (ModelState.IsValid)
                {
                    // This doesn't count login failures towards account lockout
                    // To enable password failures to trigger account lockout, set lockoutOnFailure: true
                    var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
                    if (result.Succeeded)
                    {
                        return RedirectToAction("Index", "Home");
                    }
                    else
                    {
                        ModelState.AddModelError(string.Empty, "Invalid login attempt.");
                        return View(model);
                    }
                }
                return View(model);
            }
            //
            // POST: /Account/LogOff
            //[HttpPost]
            //[ValidateAntiForgeryToken]
            public ActionResult LogOff()
            {
                //SignInManager.SignOutAsync();
                return RedirectToAction("Index", "Home");
            }
        }
    }
    
    
    

    User's image

    Best regards,

    Jalpa


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. lokisinary 3d 0 Reputation points
    2024-12-04T15:15:03.3933333+00:00

    when i use user name as: test user
    then it gives me the same error but when i use: testuser
    it works and i found out that you cannot have space in the user name.

    so how i fixed it:
    in the register.razor i have added:

                <div class="form-floating mb-3">
    
                    <InputText @bind-Value="Input.UserName" class="form-control" autocomplete="username" aria-required="true" placeholder="username" />
    
                    <label for="username">Username</label>
    
                    <ValidationMessage For="() => Input.UserName" class="text-danger" />
    
                </div>  
    
    
    public async Task RegisterUser(EditContext editContext)
    
    {
    
        var user = CreateUser();
    
        await UserStore.SetUserNameAsync(user, Input.UserName, CancellationToken.None);
    
        var emailStore = GetEmailStore();
    
        await emailStore.SetEmailAsync(user, Input.Email, CancellationToken.None);
    
        var result = await UserManager.CreateAsync(user, Input.Password);
    
        if (!result.Succeeded)
    
        {
    
            identityErrors = result.Errors;
    
            return;
    
        }
    
        Logger.LogInformation("User created a new account with password.");
    
        var userId = await UserManager.GetUserIdAsync(user);
    
        var code = await UserManager.GenerateEmailConfirmationTokenAsync(user);
    
        code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
    
        var callbackUrl = NavigationManager.GetUriWithQueryParameters(
    
            NavigationManager.ToAbsoluteUri("Account/ConfirmEmail").AbsoluteUri,
    
            new Dictionary<string, object?> { ["userId"] = userId, ["code"] = code, ["returnUrl"] = ReturnUrl });
    
        await EmailSender.SendConfirmationLinkAsync(user, Input.Email, HtmlEncoder.Default.Encode(callbackUrl));
    
        if (UserManager.Options.SignIn.RequireConfirmedAccount)
    
        {
    
            RedirectManager.RedirectTo(
    
                "Account/RegisterConfirmation",
    
                new() { ["email"] = Input.Email, ["returnUrl"] = ReturnUrl });
    
        }
    
        await SignInManager.SignInAsync(user, isPersistent: false);
    
        RedirectManager.RedirectTo(ReturnUrl);
    
    }  
    
    
    private sealed class InputModel
    
    {
    
        [Required]
    
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 3)]
    
        [RegularExpression(@"^[a-zA-Z0-9 ._@+-]+$", ErrorMessage = "The username contains invalid characters.")]
    
        [Display(Name = "User Name")]
    
        public string UserName { get; set; } = "";
    
        [Required]
    
        [EmailAddress]
    
        [Display(Name = "Email")]
    
        public string Email { get; set; } = "";
    
        [Required]
    
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
    
        [DataType(DataType.Password)]
    
        [Display(Name = "Password")]
    
        public string Password { get; set; } = "";
    
        [DataType(DataType.Password)]
    
        [Display(Name = "Confirm password")]
    
        [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    
        public string ConfirmPassword { get; set; } = "";
    
    }  
    and program.cs:  
    builder.Services.AddIdentityCore<ApplicationUser>(options =>
    
    {
    
    

    options.SignIn.RequireConfirmedAccount = true;

    // Allow spaces in usernames

    options.User.AllowedUserNameCharacters =

    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+ ";
    ``````})
    
    .AddRoles<IdentityRole>()
    
    .AddEntityFrameworkStores<ApplicationDbContext>()
    
    .AddSignInManager()
    
    .AddDefaultTokenProviders();  
      
    and it fixed this issue but make sure you also update your other files like login.razor and etc.
    
    OR best practice is create new input field for example: CustomUserName or DisplayUserName or any other this way you will not affect the existing UserName and this way you will able to use CustomUserName, UserName, Email without any issue and remember that UserName still use the email so if you want to display the CustomUserName then you have to update the rest of your file to display the CustomUserName instead of UserName (keep in mind you do not need to change the UserName to CustomUserName you can user existing logic for UserName and Email without affecting them you just have to add the new input field for the CustomUserName.)
    
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.