Hello I’m wondering how I can create an OTP for my code. so, I can be able to send that code for people who sign up as new in Asp.net core web Application
here’s how my front looks like to get email and phone number:
@page
@model RegisterModel
<div class="container mt-5">
<form id="registerForm" asp-route-returnUrl="@Model.ReturnUrl" method="post" enctype="multipart/form-data">
<div asp-validation-summary="ModelOnly" class="text-danger" role="alert"></div>
<div class="swiper-container">
<div class="swiper-wrapper">
<!-- Étape 1 : Informations personnelles -->
<div class="swiper-slide">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkpNXo1OBbM9xr2QzR_ey1sW42ZjNQhdPgnQ&s" alt="Image de Profil" class="profile-image">
<div class="mb-2">
<label class="form-label" for="email">Email <i class="bi bi-envelope-at-fill"></i></label>
<input asp-for="Input.Email" type="email" id="email" class="form-control" required class="form-control" />
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
<div class="mb-2 d-flex justify-content-center">
<!-- Sélection du pays -->
<div class="col-4">
<label for="country" class="form-label">Code :</label>
<select asp-for="Input.CountryCode" class="form-control" id="country">
<option value="+243">RD. Congo (+243)</option>
<option value="+241">Gabon (+241)</option>
</select>
</div>
<!-- Numéro de téléphone -->
<div class="col-4">
<label for="telephone" class="form-label">Numero <i class="bi bi-telephone-fill"></i></label>
<input asp-for="Input.PhoneNumber" type="tel" id="telephone" required class="form-control" placeholder="ex: 0893031784" />
</div>
</div>
<!-- Navigation buttons -->
<div class="button-container">
<a asp-page="./Login" asp-route-returnUrl="@Model.ReturnUrl" class="btn btn-secondary prev-btn">Page de connexion</a>
<button type='button' class='btn btn-primary next-btn'>Suivant</button>
</div>
</div>
<!-- Étape 4 : Mot de passe -->
<div class='swiper-slide'>
<img src='https://www.dopethemes.com/wp-content/uploads/2024/09/Migrating-Legacy-PHP-Code-to-password_hash-300x300.webp' alt='Image de Profil' class='profile-image'>
@if (User.IsInRole(DetailStatic.Role_Admin))
{
<!-- Only admins can add a user with a role -->
<div class='mb-3'>
<select asp-for="Input.Role" asp-items="@Model.Input.RoleList" class="form-select">
<option disabled selected>-selectionnez le Role-</option>
</select>
</div>
}
<div style="font-size: 10px;">
<ul>
Le mot de passe doit contenir:
<li>au moins 8 characteres</li>
<li>au moins une Lettre Majiscule, au moins une Lettre Miniscule</li>
<li>au moins un chiffre, au moins un symbole (ex : *#%$)</li>
</ul>
</div>
<!-- Password fields -->
<div class='mb-3'>
<label for='password' class='form-label'>Mot de passe</label>
<div class="input-group">
<input asp-for='Input.Password' type='password' id='password' autocomplete='new-password'
class='form-control' />
<button type="button" class="btn btn-outline-secondary" style='background-color: #13357B; color: white;' onclick="togglePasswordVisibility('password', this)">
<i class="bi bi-eye-fill" id="eye-icon-password"></i>
</button>
</div>
<span asp-validation-for='Input.Password' class='text-danger'></span>
</div>
<div class='mb-3'>
<label for='confirm-password' class='form-label'>Confirmer Mot de passe</label>
<div class="input-group">
<input asp-for='Input.ConfirmPassword' type='password' id='confirm-password'
class='form-control' />
<button type="button" class="btn btn-outline-secondary" style='background-color: #13357B; color: white;' onclick="togglePasswordVisibility('confirm-password', this)">
<i class="bi bi-eye-fill" id="eye-icon-confirm-password"></i>
</button>
</div>
<span asp-validation-for='Input.ConfirmPassword'
class='text-danger'></span>
</div>
<!-- Navigation buttons -->
<div class="button-container">
<button type='button' class='btn btn-secondary prev-btn'>Précédent</button>
<button id='registerSubmit'
type='submit'
data-mdb-button-init
data-mdb-ripple-init
class='btn btn-success'>
Enregistrer
</button>
</div>
</div><!-- End of swiper-slide -->
</div><!-- End of swiper-wrapper -->
</div><!-- End of swiper-container -->
</form><!-- End of registerForm -->
</div><!-- End of container -->
<!-- Scripts -->
<script src="//code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="//stackpath.bootstrapcdn.com/bootstrap/5.1.3/js/bootstrap.bundle.min.js"></script>
<script src="//unpkg.com/swiper/swiper-bundle.min.js"></script>
<!-- Swiper initialization and button handling -->
<script>
@* Js to handle some validation *@
</script>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
Here’s how my backend code looks like:
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
#nullable disable
using System.ComponentModel.DataAnnotations;
using System.Text;
using System.Text.Encodings.Web;
using Bilokos.DataAccess.Repository.IRepository;
using Bilokos.Models;
using Bilokos.Utility;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.WebUtilities;
namespace BilokosWeb.Areas.Identity.Pages.Account
{
public class RegisterModel : PageModel
{
private readonly SignInManager<IdentityUser> _signInManager;
private readonly RoleManager<IdentityRole> _roleManager;
private readonly UserManager<IdentityUser> _userManager;
private readonly IUserStore<IdentityUser> _userStore;
private readonly IUserEmailStore<IdentityUser> _emailStore;
private readonly ILogger<RegisterModel> _logger;
private readonly IEmailSender _emailSender;
private readonly IUnitOfWork unitOfWork;
public RegisterModel(
UserManager<IdentityUser> userManager,
RoleManager<IdentityRole> roleManager,
IUserStore<IdentityUser> userStore,
SignInManager<IdentityUser> signInManager,
ILogger<RegisterModel> logger,
IEmailSender emailSender, IUnitOfWork _unitOfWork)
{
_userManager = userManager;
_userStore = userStore;
_emailStore = GetEmailStore();
_signInManager = signInManager;
_logger = logger;
_emailSender = emailSender;
_roleManager = roleManager;
unitOfWork = _unitOfWork;
}
[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; }
public string CountryCode { 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; }
public string? Role { get; set; }
[Display(Name = "Photo de profil")]
public IFormFile ProfileImage { get; set; }
[ValidateNever]
public IEnumerable<SelectListItem> RoleList { get; set; }
[Required]
public string Nom { get; set; }
public string? Adresse { get; set; }
public string? Ville { get; set; }
public string? Province { get; set; }
public string? PhoneNumber { get; set; }
}
public async Task OnGetAsync(string returnUrl = null)
{
Input = new()
{
RoleList = _roleManager.Roles.Select(x => x.Name).Select(i => new SelectListItem
{
Text = i,
Value = i
})
};
ReturnUrl = returnUrl;
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
}
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl ??= Url.Content("~/");
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
if (ModelState.IsValid)
{
var user = CreateUser();
await _userStore.SetUserNameAsync(user, Input.Email, CancellationToken.None);
await _emailStore.SetEmailAsync(user, Input.Email, CancellationToken.None);
//inserer les autres champs rajouter dans notre bd
user.Adresse = Input.Adresse;
user.PhoneNumber = $"{Input.CountryCode}" +Input.PhoneNumber;
user.Nom = Input.Nom;
user.Province = Input.Province;
user.Ville = Input.Ville;
user.DateDeCreation = DateOnly.FromDateTime(DateTime.Now);
var result = await _userManager.CreateAsync(user, Input.Password);
var userId = await _userManager.GetUserIdAsync(user);
var uploadsFolder = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images", $"Utilisateur-{userId}");
Directory.CreateDirectory(uploadsFolder); // Create directory if it doesn't exist
// Handle profile image upload
if (Input.ProfileImage != null && Input.ProfileImage.Length > 0) // Check if file is not null and has content
{
var fileName = Path.GetFileName(Input.ProfileImage.FileName);
var filePath = Path.Combine(uploadsFolder, fileName);
using (var stream = new FileStream(filePath, FileMode.Create))
{
await Input.ProfileImage.CopyToAsync(stream);
}
user.ProfileImagePath = $"/images/Utilisateur-{userId}/{fileName}"; // Store relative path
await _userManager.UpdateAsync(user); // Update the user with the new profile image path
}
if (result.Succeeded)
{
_logger.LogInformation("User created a new account with password.");
if (!String.IsNullOrEmpty(Input.Role))
{
await _userManager.AddToRoleAsync(user, Input.Role);
}
else
{
//si l'utilisateur n'a rien entrer on le donne le role d'utilisateur
await _userManager.AddToRoleAsync(user, DetailStatic.Role_Utilisateur);
}
var idUtlisateur = await _userManager.GetUserIdAsync(user);
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
DetailAbonnement detailAbonnement = new DetailAbonnement()
{
ApplicationUser = user,
AbonnementId=1,
DateDebut = DateTime.Now,
Statut=DetailStatic.StatusAbonnementActif
};
unitOfWork.DetailAbonnement.Add(detailAbonnement);
unitOfWork.Save();
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { area = "Identity", userId = idUtlisateur, code = code, returnUrl = returnUrl },
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(Input.Email, "Confirmer votre email",
$"Merci de bien vouloir confirmer votre adresse e-mail <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>en cliquant ici.</a>.");
if (_userManager.Options.SignIn.RequireConfirmedAccount)
{
return RedirectToPage("RegisterConfirmation", new { email = Input.Email, returnUrl = returnUrl });
}
else
{
if (User.IsInRole(DetailStatic.Role_Admin))
{
TempData["success"] = "Enregistrement reussi";
}
else
{
await _signInManager.SignInAsync(user, isPersistent: false);
}
TempData["welcomeBilokos"] = "Mbote! Boyei malamu na Bilokos, esika ya solo mpo na koteka mpe kosomba biloko na facilite....";
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();
}
private ApplicationUser CreateUser()
{
try
{
return Activator.CreateInstance<ApplicationUser>();
}
catch
{
throw new InvalidOperationException($"Can't create an instance of '{nameof(IdentityUser)}'. " +
$"Ensure that '{nameof(IdentityUser)}' is not an abstract class and has a parameterless constructor, or alternatively " +
$"override the register page in /Areas/Identity/Pages/Account/Register.cshtml");
}
}
private IUserEmailStore<IdentityUser> GetEmailStore()
{
if (!_userManager.SupportsUserEmail)
{
throw new NotSupportedException("The default UI requires a user store with email support.");
}
return (IUserEmailStore<IdentityUser>)_userStore;
}
}
}
Can you help me to create un OTP code to so I will be able to send it to people via email or phone number.