Home > Net >  How to Make Entity like MobileNo,EmpOfficeCode etc. unique In EF core Razor Pages by validation Manu
How to Make Entity like MobileNo,EmpOfficeCode etc. unique In EF core Razor Pages by validation Manu

Time:06-16

Hi I am very new in Microsoft EF core and razor pages project and Microsoft Identity. While registering new user I am providing various field .I want to make Phone Number Unique by Validation which is present in Register.cshtml.cs class .in EF they have made Email Unique but I cant understand how. I tried to find the way but failed...so can you guys suggest How can I Do it . My Register.cshtml.cs file

 //[AllowAnonymous]
//[Authorize(Roles = StaticDetails.AdminEndUser)]
public class RegisterModel : PageModel
{
    private readonly SignInManager<IdentityUser> _signInManager;
    private readonly UserManager<IdentityUser> _userManager;
    private readonly ILogger<RegisterModel> _logger;

    ////comented the Iemailsender because its causing error.
    // private readonly IEmailSender _emailSender;

    //// added by me for dependency injection;
    private readonly RoleManager<IdentityRole> _roleManager;
    private readonly ApplicationDbContext _db;

    
    public RegisterModel(
        UserManager<IdentityUser> userManager,
        SignInManager<IdentityUser> signInManager,
        ILogger<RegisterModel> logger,
        // IEmailSender emailSender,
        ////added by me for constructor for the upper used dependency injection;
        RoleManager<IdentityRole> roleManager,
        ApplicationDbContext db)
        
        
    {
        _userManager = userManager;
        _signInManager = signInManager;
        _logger = logger;
        // _emailSender = emailSender;
        ////added by me for upper used constructor;
        _roleManager = roleManager;
        _db = db;

    }

    [BindProperty]
    public InputModel Input { get; set; }

    public string ReturnUrl { get; set; }

    public IList<AuthenticationScheme> ExternalLogins { get; set; }

    public class InputModel
    {
        [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; }

        //added by me

        //[BindProperty]
        //public string Gender { get; set; }
        //public string[] Genders = new[] { "Male", "Female", "Unspecified" };

        //[DataType(DataType.Date)]
        //[Column(TypeName = "Date")]
        //public DateTime DateOfBirth { get; set; }

        [Required]
       
        //public string FullName { get; set; }
        public string FirstName { get; set; }

        public string LastName { get; set; }
        public string EmployeCode { get; set; }
        public string Designation { get; set; }

        //[DataType(DataType.Date)]
        //[Column(TypeName = "Date")]
        [BindProperty]
        public DateTime DateOfBirth { get; set; }
        [BindProperty]
        public DateTime DateOfJoining { get; set; }
        public string EmergencyNo { get; set; }
        public string AdharNo { get; set; }
       
        public string Address { get; set; }
        public string City { get; set; }
        public string PostalCode { get; set; }

        [Required]
        [Display(Name = "Phone Number")]
        [MaxLength(10)]
        public string PhoneNumber { get; set; }
    }

    public async Task OnGetAsync(string returnUrl = null)
    {
        ReturnUrl = returnUrl;
        ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
    }

    public async Task<IActionResult> OnPostAsync(string returnUrl = null)
    {
        returnUrl = returnUrl ?? Url.Content("~/");
        ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
        if (ModelState.IsValid)
        {
            //// var user = new Identityuser { UserName = Input.Email, Email = Input.Email };...I edited it because in Applicationuser class i am putting the name,address,city,postal code.
            var user = new ApplicationUser
            { 
                UserName = Input.Email, 
                Email = Input.Email ,
                FirstName = Input.FirstName,
                LastName = Input.LastName,
                EmployeCode = Input.EmployeCode,
                Designation = Input.Designation,
                //DateOfBirth= Convert.ToDateTime("DateOfBirth"),
                DateOfBirth = Input.DateOfBirth,
                DateOfJoining = Input.DateOfJoining,
                EmergencyNo = Input.EmergencyNo,
                AdharNo = Input.AdharNo,
                Address = Input.Address,
                City = Input.City,
                PostalCode = Input.PostalCode,
                PhoneNumber = Input.PhoneNumber
                
            };

            
            ////after dependency injection we come to after post handler.and in below line they r creating the user.
            var result = await _userManager.CreateAsync(user, Input.Password);
            if (result.Succeeded)
            {
                ////added by me if this is successful we want chk if role exits in the detabase.
                ////if admin user doesnot exits we want to creat it.
                ////StaticDetails class SD created by me.
                if (!await _roleManager.RoleExistsAsync(StaticDetails.AdminEndUser))
                {
                    await _roleManager.CreateAsync(new IdentityRole(StaticDetails.AdminEndUser));
                }

                if (!await _roleManager.RoleExistsAsync(StaticDetails.HrEndUser))
                {
                    await _roleManager.CreateAsync(new IdentityRole(StaticDetails.HrEndUser));
                }

                if (!await _roleManager.RoleExistsAsync(StaticDetails.ItEndUser))
                {
                    await _roleManager.CreateAsync(new IdentityRole(StaticDetails.ItEndUser));
                }
                if (!await _roleManager.RoleExistsAsync(StaticDetails.EmployeeEndUser))
                {
                    await _roleManager.CreateAsync(new IdentityRole(StaticDetails.EmployeeEndUser));
                }

                ////roles are created now have to assign it to a user.
                ////adminuser for now.means when i will creat it will by default take adminuser.
                await _userManager.AddToRoleAsync(user, StaticDetails.EmployeeEndUser);


                _logger.LogInformation("User created a new account with password.");

                var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
                code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
                var callbackUrl = Url.Page(
                    "/Account/ConfirmEmail",
                    pageHandler: null,
                    values: new { area = "Identity", userId = user.Id, code = code, returnUrl = returnUrl },
                    protocol: Request.Scheme);

                // await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
                //   $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
                
                if (_userManager.Options.SignIn.RequireConfirmedAccount)
                {
                    return RedirectToPage("RegisterConfirmation", new { email = Input.Email, returnUrl = returnUrl });
                }
                else
                {
                    await _signInManager.SignInAsync(user, isPersistent: false);
                    return LocalRedirect(returnUrl);
                }
            }
            foreach (var error in result.Errors)
            {
                ModelState.AddModelError(string.Empty, error.Description);
            }
        }

        // If we got this far, something failed, redisplay form
        return Page();
    }
}

and my ApplicationDbContext.cs class

public class ApplicationDbContext : IdentityDbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }
   
    public DbSet<ApplicationUser> ApplicationUser { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<ApplicationUser>()
            .HasIndex(a => new { a.PhoneNumber, a.EmergencyNo })
            .IsUnique(true);
    }
}

And i also Want to make some other properties also unique which is present in my ApplicationUserClass:-

     public string FirstName { get; set; }
    
     public string LastName { get; set; }

     public string EmployeCode { get; set; }

     public string Designation { get; set; }

     public DateTime DateOfBirth { get; set; }

     public DateTime  DateOfJoining { get; set; }

     public string EmergencyNo { get; set; }

     public string AdharNo { get; set; }

    /*
   //Department dropdown and city and country thing
   //public string Gender { get; set; }
   //public string[] Genders = new[] { "Male", "Female", "Unspecified" };
    */  //public string FullName { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string PostalCode { get; set; }

thanks in advance

CodePudding user response:

For this, you can make a custom or personalized validation. and decorate your property with that custom attribute.

MobileUniqueAttribute.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using Base.Models;

namespace Core.Models
{
    public class MobileUniqueAttribute : ValidationAttribute
    {
        protected override ValidationResult IsValid(
            object value, ValidationContext validationContext)
        {
            var _context = (ApplicationDbContext)validationContext.GetService(typeof(ApplicationDbContext));
            var entity = _context.RegistationTable.SingleOrDefault(e => e.PhoneNumber == value.ToString());

            if (entity != null)
            {
                return new ValidationResult(GetErrorMessage(value.ToString()));
            }
            return ValidationResult.Success;
        }

        public string GetErrorMessage(string mobile)
        {
            return $"Mobile {mobile} is already in use.";
        }
    }
}

InputModel.cs

public class InputModel
{
    [Required]
    [MobileUnique]
    public string PhoneNumber { get; set; }
}

Like MobileUniqueAttribute.cs, you can create separate custom validation for other fields too.

CodePudding user response:

Update the ConfigureServices() method of the Startup.cs class to add the below IdentityOptions class properties inside the services.Configure<IdentityOptions>() method . Such as UserOptions has RequireUniqueEmail Property, sets a flag indicating whether the application requires unique emails for its users.

    services.Configure<IdentityOptions>(opts => {
            opts.User.RequireUniqueEmail = true; 
                   ...
               });

But if you want other property unique ,custom attribute is a way, another way is using the UserValidator class, you can refer to the below code

 public class CustomUsernameEmailPolicy : UserValidator<AppUser>
    {
        public override async Task<IdentityResult> ValidateAsync(UserManager<AppUser> manager, AppUser user)
        {
            IdentityResult result = await base.ValidateAsync(manager, user);
            List<IdentityError> errors = result.Succeeded ? new List<IdentityError>() : result.Errors.ToList();
 
            if (user.UserName == "google")
            {
                errors.Add(new IdentityError
                {
                    Description = "Google cannot be used as a user name"
                });
            }
 
            if (!user.Email.ToLower().EndsWith("@yahoo.com"))
            {
                errors.Add(new IdentityError
                {
                    Description = "Only yahoo.com email addresses are allowed"
                });
            }
            return errors.Count == 0 ? IdentityResult.Success : IdentityResult.Failed(errors.ToArray());
        }
    }

then register the CustomUsernameEmailPolicy class in the ConfigureServices() method of the Startup class.

 services.AddTransient<IUserValidator<AppUser>, CustomUsernameEmailPolicy>();
  • Related