How my NormalizeEmail always null?

Nhựt Lại 65 Reputation points
2024-06-19T18:47:21.2133333+00:00

Hi, I'm new to this, so I'm not so good, your help is my pleasure.
I have a problem, when I sign up for an account, it is okay, but when I log in, as far as I know, the NormalizeEmail is always null, and I don't know why, I try to cover in the database, but its don't work either. But my UserName ( I set it as email, cause I want people to log in by their email ), is automatically Normalized, I don't know where the problem is. Can someone, help me, please? I would very very appreciate it. If you need to see any file, just comment. Thank you.

This my LoginViewModel

namespace ChatApp_BE.ViewModels { public class LoginViewModel { public string Email { get; set; } public string Password { get; set; } public bool RememberMe { get; set; } } }

Here my User Model

using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace ChatApp_BE.Models;
public class User : IdentityUser
{
    public string? Nickname { get; set; }
    public string Email { get; set; } = string.Empty;
    public bool EmailConfirmed { get; set; }
    public string? PasswordHash { get; set; }
    public string? SecurityStamp { get; set; }
    public string? FullName { get; set; }
    public string? Avatar { get; set; }
    public string? EmailConfirmationToken { get; set; }
    public string? ResetPasswordToken { get; set; }
    public string? RefreshToken { get; set; }
    public virtual ICollection<Message> Messages { get; set; } = new List<Message>();
    public virtual ICollection<RoomUser> RoomUsers { get; set; } = new List<RoomUser>();
    public virtual ICollection<Room> Rooms { get; set; } = new List<Room>();
}

Here is Register

[HttpPost("register")]
public async Task<IActionResult> Register(RegisterViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = await _userManager.FindByEmailAsync(model.Email);
        if (user != null && await _userManager.IsEmailConfirmedAsync(user))
        {
            return BadRequest("Email was already used.");
        }
        user = new User
        {
            UserName = model.Email,
            Email = model.Email,
            FullName = model.FullName,
        };
        var result = await _userManager.CreateAsync(user, model.Password);
        if (result.Succeeded)
        {
            var token = await _userManager.GenerateEmailConfirmationTokenAsync(user);
            var confirmationLink = Url.Action(
                nameof(ConfirmEmail),
                "User",
                new { userId = user.Id, token },
                Request.Scheme
                );
            await _emailSender.SendEmailAsync("Confirm your email",
                model.Email,
                $"Please confirm your email by clicking <a href=\"{confirmationLink}\">here</a>.");
            return Ok(new { Message = "Registration successful! Please check your email to confirm your account." });
        }
        foreach (var error in result.Errors)
        {
            ModelState.AddModelError(string.Empty, error.Description);
        }
    }
    return BadRequest(ModelState);
}

Here is Login.

[HttpPost("login")]
public async Task<IActionResult> Login(LoginViewModel model)
{
    try
    {
        if (ModelState.IsValid)
        {
            var normalizedEmail = _userManager.NormalizeEmail(model.Email);
            var user = await _userManager.FindByEmailAsync(model.Email);
            if (user == null || !await _userManager.CheckPasswordAsync(user, model.Password)) // tu lam sau nhe
            {
                return Unauthorized("Invalid login attempt.");
            }
            var tokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.UTF8.GetBytes(_config.GetSection("Jwt:SecretKey").Value!);
            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(new Claim[]
                {
                new Claim(ClaimTypes.Name, user.UserName),
                new Claim(ClaimTypes.NameIdentifier, user.Id.ToString())
                }),
                Expires = DateTime.UtcNow.AddDays(7),
                SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
            };
            var token = tokenHandler.CreateToken(tokenDescriptor);
            var tokenString = tokenHandler.WriteToken(token);
            return Ok(new { Token = tokenString });
        }
        return BadRequest(ModelState);
    }
    catch (Exception ex)
    {
        return BadRequest(ex.Message);
    }
}

Developer technologies | ASP.NET | ASP.NET Core
0 comments No comments
{count} votes

Answer accepted by question author
  1. Anonymous
    2024-06-20T09:21:02.66+00:00

    Hi @Nhựt Lại

    User.Email hides inherited member IdentityUser<string>.Email. To make the current member override that implementation, add the override keyword:

    public class User : IdentityUser
    {
        public string? Nickname { get; set; }
        public override string  Email { get; set; } = string.Empty;
        //other properties....
    }
    

    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.

    Best regards,
    Rena

    2 people found this answer helpful.

1 additional answer

Sort by: Most helpful
  1. AgaveJoe 30,491 Reputation points
    2024-06-19T20:06:14.6433333+00:00

    As far as I can tell this is an Identity customization question.

    The convention for modifying the user in Identity is naming the class "ApplicationUser". "User" is a property of the ControllerBase class. Naming a class "User" and instantiating the class in a controller is not the best idea. See the docs.

    https://learn.microsoft.com/en-us/aspnet/core/security/authentication/customize-identity-model?view=aspnetcore-8.0#custom-user-data

    I'm guessing the issue is "User" is not passed as an argument to the context, IdentityDbContext<User>, as illustrated in the link above.

    1 person found this answer helpful.

Your answer

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