RegistrationForm.cshtml
@page
@model FaceAdminApp.Pages.Auth.RegistrationFormModel
@{
ViewData["Title"] = "RegistrationForm";
}
<style>
.container {
max-width: 600px;
margin: 0 auto;
padding: 20px;
border: 1px solid #ccc;
border-radius: 5px;
background-color: #f9f9f9;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
font-weight: bold;
}
.form-control {
width: 100%;
padding: 8px;
border-radius: 3px;
border: 1px solid #ccc;
}
.btn-primary {
background-color: #007bff;
color: #fff;
border: none;
}
.btn-primary:hover {
background-color: #0056b3;
}
.btn-secondary {
background-color: #6c757d;
color: #fff;
border: none;
}
.btn-secondary:hover {
background-color: #545b62;
}
.mt-2 {
margin-top: 20px;
}
.adornment-icon {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
pointer-events: none;
}
.btn-outline-primary {
border-color: #007bff;
color: #007bff;
}
.btn-outline-primary:hover {
background-color: #007bff;
color: #fff;
}
</style>
<div class="container">
<form method="post" asp-page-handler="validSubmit" enctype="multipart/form-data">
<div class="form-group">
<label asp-for="RegisterVmModel.FirstName"></label>
<input asp-for="RegisterVmModel.FirstName" class="form-control" autocomplete="off" />
<span asp-validation-for="RegisterVmModel.FirstName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="RegisterVmModel.LastName"></label>
<input asp-for="RegisterVmModel.LastName" class="form-control" autocomplete="off" />
<span asp-validation-for="RegisterVmModel.LastName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="RegisterVmModel.EmployeeId"></label>
<input asp-for="RegisterVmModel.EmployeeId" class="form-control" autocomplete="off" />
<span asp-validation-for="RegisterVmModel.EmployeeId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="RegisterVmModel.Enterprise">Enterprise Name</label>
<input id="enterpriseInput" class="form-control" autocomplete="off" asp-for="RegisterVmModel.Enterprise" />
<span asp-validation-for="RegisterVmModel.Enterprise" class="text-danger"></span>
@foreach (var enterprise in Model.SearchEnterprise(Model.Enterprise).Result)
{
<div>@enterprise</div>
}
@* <span class="text-danger">@Model.ValidateEnterprise(Model.Enterprise)</span> *@
</div>
<div class="form-group">
<label asp-for="RegisterVmModel.Password"></label>
<input asp-for="RegisterVmModel.Password" class="form-control" autocomplete="off" type="password" />
<span asp-validation-for="RegisterVmModel.Password" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="RegisterVmModel.ConfirmPassword"></label>
<input asp-for="RegisterVmModel.ConfirmPassword" class="form-control" autocomplete="off" type="password" />
<span asp-validation-for="RegisterVmModel.ConfirmPassword" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Photo"></label>
<input type="file" id="photoInput" name="Photo" class="form-control" />
<span asp-validation-for="Photo" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-outline-primary btn-sm">Submit</button>
</form>
<div class="mt-6 d-flex justify-space-between align-center">
<a asp-page="/Auth/Login" class="btn btn-primary">Login</a>
</div>
RegistrationForm.cshtml.cs
using FaceAdminApp.Auth;
using FaceAdminApp.DTOs;
using FaceAdminApp.Services;
using FaceAdminApp.Utilities;
using FaceAdminApp.ViewModels;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Text;
namespace FaceAdminApp.Pages.Auth
{
public class RegistrationFormModel : PageModel
{
private readonly VacApiService _apiService;
private readonly ILoginService _loginService;
private readonly NavigationManager _navManager;
private readonly DialogService _dialogService;
public RegistrationFormModel(VacApiService apiService, ILoginService loginService, NavigationManager navManager, DialogService dialogService)
{
_apiService = apiService;
_loginService = loginService;
_navManager = navManager;
_dialogService = dialogService;
SelectListDto = new SelectListDto();
RegisterVmModel = new RegisterVm();
LoginModel = new OtpRegisterVm();
}
[BindProperty]
public RegisterVm RegisterVmModel { get; set; }
[BindProperty]
public OtpRegisterVm LoginModel { get; set; }
[BindProperty]
public int StepOffset { get; set; } = 0;
public string Enterprise { get; set; }
[BindProperty]
public string Username { get; set; }
//public SelectListDto SelectListDto = new();
public SelectListDto SelectListDto { get; set; }
public List<string> Enterprises = new List<string>();
public LoginResultDto response;
public bool Processing = false;
[BindProperty]
public bool OtpProcessing { get; set; } = false;
public bool EnterpriseError = false;
public bool IsPhoneNumberValidated = false;
[BindProperty]
public IFormFile Photo { get; set; }
public async Task<IActionResult> OnPostValidSubmit()
{
Processing = true;
if (!ModelState.IsValid)
{
return Page();
}
var dto = await MapVmToDto();
// Access mobile number as username
var username = LoginModel.CountryCode + LoginModel.Username;
dto.UserName = username;
if (Photo != null && Photo.Length > 0)
{
if (!IsImageFile(Photo.FileName))
{
Notify.Add(TempData, false, "Please upload a valid image file.", "");
Processing = false;
return Page();
}
// Save the file to a location or process it
var filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "uploads", Photo.FileName);
using (var stream = new FileStream(filePath, FileMode.Create))
{
await Photo.CopyToAsync(stream);
}
// Attach the file path to your DTO
dto.PhotoPath = filePath;
}
var response = await _apiService.RegisterUser(dto);
if (response.Succeeded)
{
Notify.Add(TempData, false, "Registration was successful.", "");
}
else
{
Notify.Add(TempData, false, response.Error, "");
Processing = false;
}
return Page();
}
public bool IsImageFile(string fileName)
{
var allowedExtensions = new[] { ".jpg", ".jpeg", ".png", ".gif" };
var extension = Path.GetExtension(fileName).ToLowerInvariant();
return allowedExtensions.Contains(extension);
}
public async Task<RegisterDto> MapVmToDto()
{
// Access mobile number as username
var username = LoginModel.CountryCode + LoginModel.Username;
var item = SelectListDto.SelectList.FirstOrDefault(e =>
e.Name.Equals(RegisterVmModel.Enterprise, StringComparison.OrdinalIgnoreCase));
var enterpriseId = item is null ? 0 : item.Id;
var dto = new RegisterDto
{
FirstName = RegisterVmModel.FirstName,
LastName = RegisterVmModel.LastName,
//UserName = LoginModel.CountryCode + LoginModel.Username,
UserName = username,
EnterpriseId = enterpriseId,
EmployeeId = RegisterVmModel.EmployeeId,
Password = RegisterVmModel.Password,
};
return dto;
}
public string ValidateEnterprise(string input)
{
if (!Enterprises.Contains(input))
{
return "Only registered enterprises allowed";
}
return null;
}
public async Task<IEnumerable<string>> SearchEnterprise(string value)
{
if (string.IsNullOrEmpty(value) || value.Length < 3)
return Enumerable.Empty<string>();
return await Task.FromResult(Enterprises.Where(x => x.StartsWith(value, StringComparison.InvariantCultureIgnoreCase)));
}
}
}
While submitting the form, the breakpoint hits while checking the model state and there are invalid details fetched from the OtpRegisterVm and I have used bind property but it is not working and when bind property is removed for the OtpRegisterVm model, the details are all valid for the RegisterVmModel. The OtpRegisterVm contains the username, country code and password and these are fetched from Register.cshtml.cs -
Register.cshtml.cs
using FaceAdminApp.Auth;
using FaceAdminApp.DTOs;
using FaceAdminApp.Models;
using FaceAdminApp.Services;
using FaceAdminApp.Utilities;
using FaceAdminApp.ViewModels;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace FaceAdminApp.Pages.Auth
{
public class RegisterModel : PageModel
{
private readonly ILoginService _loginService;
private readonly VacApiService _apiService;
public RegisterModel(ILoginService loginService, VacApiService apiService)
{
_loginService = loginService;
_apiService = apiService;
}
[BindProperty]
public string LoginPhoneNumber { get; set; }
[BindProperty]
public string CountryCode { get; set; }
[BindProperty]
public OtpRegisterVm LoginModel { get; set; }
public bool IsPhoneNumberPresent { get; set; } = false;
public bool IsPhoneNumberValidated { get; set; }
public bool OtpProcessing { get; set; }
public bool Processing { get; set; }
//public void OnGet()
//{
// if (!string.IsNullOrEmpty(LoginPhoneNumber))
// {
// IsPhoneNumberPresent = true;
// LoginModel = new OtpRegisterVm { Username = LoginPhoneNumber, CountryCode = CountryCode };
// }
// else
// {
// IsPhoneNumberPresent = false;
// }
//}
public void OnGet()
{
if (!string.IsNullOrEmpty(LoginPhoneNumber))
{
IsPhoneNumberPresent = true;
}
else
{
IsPhoneNumberPresent = false;
}
}
public async Task<IActionResult> OnPostGenerateOtpAsync()
{
OtpProcessing = true;
if (LoginModel == null || string.IsNullOrEmpty(LoginModel.Username))
{
Notify.Add(TempData, false, "", "Phone Number required");
OtpProcessing = false;
return Page();
}
else if (LoginModel.Username.Length < 10)
{
Notify.Add(TempData, false, "", "Enter valid Phone Number");
OtpProcessing = false;
return Page();
}
//Notify.Add(TempData, true, $"OTP Generated successfully: {generatedOtp}", "");
var dto = new PhoneNumberDto { PhoneNumber = LoginModel.CountryCode + LoginModel.Username };
var response = await _apiService.GenerateRegisterOtp(dto);
if (response.IsSuccess)
{
Notify.Add(TempData, true, "OTP Generated successfully", "");
}
else
{
Notify.Add(TempData, false, "", response.Message);
}
OtpProcessing = false;
return Page();
}
public async Task<IActionResult> OnPostAsync()
{
Processing = true;
if (string.IsNullOrEmpty(LoginModel.Username) || string.IsNullOrEmpty(LoginModel.Password))
{
Notify.Add(TempData, false, "", "Phone Number and OTP are required");
Processing = false;
return Page();
}
if (LoginModel.Username.Length < 10 || LoginModel.Password.Length != 6)
{
Notify.Add(TempData, false, "", "Invalid Phone Number or OTP");
Processing = false;
return Page();
}
var dto = new LoginDto { Username = LoginModel.CountryCode + LoginModel.Username, Password = LoginModel.Password };
var response = await _apiService.ValidateRegisterOtp(dto);
if (response.IsSuccess)
{
Notify.Add(TempData, true, "Phone number validated", "");
IsPhoneNumberValidated = true;
}
else
{
Notify.Add(TempData, false, "", response.Message);
}
Processing = false;
return RedirectToPage("/Auth/RegistrationForm");
}
}
}
pro-U5N9oLnw.jpeg