Error while submitting the registration form

Surya Chandra Mohan 20 Reputation points
2024-05-20T05:31:38.77+00:00
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

ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,254 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Ping Ni-MSFT 2,405 Reputation points Microsoft Vendor
    2024-05-20T08:40:32.34+00:00

    Hi @Surya Chandra Mohan,

    For ModelState invalid, it seems your LoginModel does not receive value. For you said you get it from Register.cshtml.cs, I never seen you send this data in this cs file. Any way, I will share detailed explanation for how to send data from one page to another page.

    In Razor Pages, it contains RedirectToPage method to pass data by route data, but you cannot pass complex objects as route data. The route data feature only supports simple objects like int and string. If you want to retain more complex objects across requests, you need to use Sessions or TempData.

    For TempData,it uses Session, which itself uses IDistributedCache. IDistributedCache doesn't have the capability to accept objects or to serialize objects. So you need manually serialize/deserialize.


    Here is a sample

    1.Set the TempData before redirection in Register.cshtml.cs:

    LoginModel = new OtpRegisterVm()
    {
        Username = "aa",
        CountryCode = "ddd"
    };      //for easy testing, i just hard-coding, you need be sure it contains value...
    
    TempData["model"] = System.Text.Json.JsonSerializer.Serialize(LoginModel);   
    return RedirectToPage("/Auth/RegistrationForm");
    

    2.Receive the TempData and set the value to OtpRegisterVm LoginModel in OnPostValidSubmit in RegistrationForm.cshtml.cs:

    Processing = true;
    var data = TempData["model"] as string;
    LoginModel = System.Text.Json.JsonSerializer.Deserialize<OtpRegisterVm>(data);
    if (!ModelState.IsValid)
    {
        return Page();
    }
    

    3.Remove the [BindProperty] on OtpRegisterVm LoginModel in RegistrationForm.cshtml.cs .

    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. AgaveJoe 26,256 Reputation points
    2024-05-20T12:10:46.3+00:00

    I am able to fetch the username from one page to another and when the controller method is called, there is a status code 500 internal server error

    If I understand, your original problem is solved. This is a new problem?

    According to the screenshot the API URL (localhost:5143/api/identity/register) returned a 500 error. There can be many reasons for the 500 error. Unfortunately, you did not share any relevant source code pertaining to this error. We need the controller and the custom _httpService.Post service to do a code review.

    It would be easier and quicker if you debugged your own code. Use a tool like PostMan to call the Web API directly. Or use Swagger to call Web API.