簡體   English   中英

如何通過手動驗證使 MobileNo、EmpOfficeCode 等實體在 EF 核心 Razor 頁面中獨一無二

[英]How to Make Entity like MobileNo,EmpOfficeCode etc. unique In EF core Razor Pages by validation Manually

嗨,我是 Microsoft EF 核心和 razor pages 項目和 Microsoft Identity 的新手。 在注冊新用戶時,我提供了各種字段。我想通過 Register.cshtml.cs 類中存在的驗證使電話號碼唯一。在 EF 中,他們使電子郵件唯一,但我不明白如何。 我試圖找到方法但失敗了……你們能建議我怎么做嗎? 我的 Register.cshtml.cs 文件

 //[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();
    }
}

和我的 ApplicationDbContext.cs 類

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);
    }
}

而且我還想讓其他一些屬性也獨一無二,這些屬性存在於我的 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; }

提前致謝

為此,您可以進行自定義或個性化驗證。 並使用該自定義屬性裝飾您的財產。

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.";
        }
    }
}

輸入模型.cs

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

與 MobileUniqueAttribute.cs 一樣,您也可以為其他字段創建單獨的自定義驗證。

更新 Startup.cs 類的 ConfigureServices() 方法,在services.Configure<IdentityOptions>()方法中添加以下IdentityOptions類屬性。 例如UserOptions具有 RequireUniqueEmail 屬性,設置一個標志,指示應用程序是否需要為其用戶提供唯一的電子郵件。

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

但是如果你想要其他屬性唯一,自定義屬性是一種方式,另一種方式是使用UserValidator類,你可以參考下面的代碼

 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());
        }
    }

然后在 Startup 類的 ConfigureServices() 方法中注冊 CustomUsernameEmailPolicy 類。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM