Seleziona una pagina

Con l’avvento del nuovo ASP.NET Identity, le Nostre applicazioni sono sempre più legate all’integrazione con i social network.

A fronte di queste integrazioni, il nuovo membership fornito di default con ASP.NET MVC 4/5, è (volutamente) molto “scarno” e privo di molte funzionalità utilizzate per la gestione custom degli account presenti sulla propria applicazione.

Una delle funzionalità “mancanti” è la possibilità di inviare un’Email di conferma a fronte della registrazione di un utente, per verificare che l’indirizzo Email sia esistente.

Di seguito spiegherò passo passo come creare una semplice registrazione “custom” che abbia l’invio di una Mail di conferma per la registrazione del sito.

Model Utente:

Creando un’applicazione di tipo ASP.NET MVC per default nella cartella Models troviamo la classe ApplicationUser, questa classe contiene la definizione del modello del nostro Utente.

Aggiungiamo alla nostra classe le seguanti Proprietà:

  • Email: Indirizzo Email del Nostro utente
  • ConfirmedEmail: Valore booleano che indica l’avvenuta conferma dell’indirizzo Email da parte dell’utente.
public class ApplicationUser : IdentityUser
    {
        public string Email{ get; set; }
        public bool ConfirmedEmail { get; set; }
    }

ViewModel Registrazione:

Una volta aggiunto la proprietà Email al nostro modello, andiamo a modificare Il view model utilizzato nella registrazione dell’utente aggiungendo il campo Email:

 public class RegisterViewModel
    {
        [Required]
        [Display(Name = "User name")]
        public string UserName { get; set; }

        [Required]
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} 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; }

        [Required]
        [EmailAddress]
        [Display(Name = "E-mail")]
        public string Email { get; set; }
    }

Il Nostro campo, in fase di registrazione sarà obbligatorio ([Required])  e di tipo Email ([EmailAddress]), in questo modo lato front end saranno attivati gli script per il controllo sulla presenza del dato e sulla validità formale (Indirizzo Email) dello stesso.

Form Registrazione:

Una volta modificato il ViewModel della registrazione possiamo aggiornare la View di registrazione dell’Utente:

@using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()
    <h4>Create a new account.</h4>
    <hr />
    @Html.ValidationSummary()
    <div class="form-group">
        @Html.LabelFor(m => m.UserName, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" class="btn btn-default" value="Register" />
        </div>
    </div>
}
Action ConfirmEmail e Register:

Dopo la modifica dell’interfaccia (View), possiamo finalmente aggiungere uan nuova Action ConfirmEmail e modificare l’Action Register del nostro controller (AccountController) utilizzato per la registrazione, aggiungendo l’invio di una mail all’indirizzo fornito in fase di registrazione:

// GET: /Account/ConfirmEmail
[AllowAnonymous]
public async Task<ActionResult> ConfirmEmail(string Token, string Email)
{
  ApplicationUser user = this.UserManager.FindById(Token);
  if (user != null) { 
     if (user.Email == Email)
     {
        user.ConfirmedEmail = true;
        await UserManager.UpdateAsync(user);
        await SignInAsync(user, isPersistent: false);
        return RedirectToAction("Index", "Home", new { ConfirmedEmail = user.Email });
     }
     else
     {
        return RedirectToAction("Confirm", "Account", new { Email = user.Email });
     }
  }
  else
  {
     return RedirectToAction("Confirm", "Account", new { Email = "" });
  }
}

// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
  if (ModelState.IsValid)
  {
      var user = new ApplicationUser() { UserName = model.UserName };
      user.Email = model.Email;
      user.ConfirmedEmail = false;
      var result = await UserManager.CreateAsync(user, model.Password);
      if (result.Succeeded)
      {
         System.Net.Mail.MailMessage m = new System.Net.Mail.MailMessage(
                        new System.Net.Mail.MailAddress("sender@xxxxxx.com", "Web Registration"),
                        new System.Net.Mail.MailAddress(user.Email));
         m.Subject = "Email confirmation";
         m.Body = string.Format("Dear {0}<BR/>Thank you for your registration, please click on the below link to comlete your registration: <a href=\"{1}\" title=\"User Email Confirm\">{1}</a>", user.UserName, Url.Action("ConfirmEmail","Account", new { Token = user.Id, Email = user.Email },Request.Url.Scheme));
         m.IsBodyHtml = true;
         System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient("smtp.live.com");
         smtp.Credentials = new System.Net.NetworkCredential("sender@xxxxxx.com", "xxxxxx");
         smtp.EnableSsl = true;
         smtp.Send(m);
         return RedirectToAction("Confirm", "Account", new { Email = user.Email });
      }
      else
      {
         AddErrors(result);
      }
  }

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

Essendo codice di esempio lascio a voi la modifica per la gestione localizzata delle stringhe e per i parametri dell’invio della mail (nell’esempio viene utilizzato un account live ma si può usare un qualisasi indirizzo Email valido).

Action/View Confirm:

Come si può vedere dal codice, una volta inserito il nuovo Utente viene inviata una Mail e, a differenza della registrazione di default, viene richiamata l’action “Confirm” che serve per visualizzare a video la notifica dell’invio della Mail di conferma registrazione all’indirizzo indicato nel form di registrazione:

[AllowAnonymous]
public ActionResult Confirm(string Email)
{
    ViewBag.Email = Email;
     return View();
}      

Per ultimo aggiungiamo la View Confirm:

@{
    ViewBag.Title = "Confirm Email Address Sent";
}
<h2>@ViewBag.Title.</h2>

<div class="row">
    <div class="col-md-8">
        Please check your Email Inbox, a confirm Email is Sent to @ViewBag.Email
    </div>
</div>

Una volta applicate le modifiche riportate nei pragrafi precedenti, è possibile compilare la web application e provare una registrazione.

Se tutto è corretto arriverà un’Email, all’indirizzo indicato nella compilazione del form di registrazione, contenente un link utile per la conferma dell’Email, per semplicità all’interno del link verrà passato l’identificativo univoco dell’utente e l’indirizzo email di riferimento.

Cliccando sul link inserito nella Mail, verrà richiamata l’Action “ConfirmEmail” la quale, una volta controllati i dati, segnerà come confermato l’indirizzo Email dell’utente.

Login Utente

E’ possibile inoltre modificare il flusso della login per evitare l’accesso al sito di un utente non ancora “confermato” sempre modificando il nostro controller:

// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
 if (ModelState.IsValid)
 {
   var user = await UserManager.FindAsync(model.UserName, model.Password);
   if (user != null)
   {
     if (user.ConfirmedEmail == true) {
        await SignInAsync(user, model.RememberMe);
        return RedirectToLocal(returnUrl);
     }
     else
     {
       ModelState.AddModelError("", "Confirm Email Address.");
     }
   }
   else
   {
     ModelState.AddModelError("", "Invalid username or password.");
   }
 }
 // If we got this far, something failed, redisplay form
return View(model); }

In pratica basta controllare il valore della proprietà ConfirmedEmail dell’Uternte prima di eseguire l’accesso.

Spero la guida sia stata di vostro gradimento.

P.S. Ricordate di cambiare i parametri per l’invio della posta!

Happy Coding!

Altri Articoli

ASP.Net Core, testare applicazioni con XUnit
views 598
Come tutti sappiamo con l’avvento di .Net Core tutto l’ecosistema sta subendo evoluzioni, fin dalla prima versione del progetto ASP.NET MVC Core è sta...
ASP.NET Core, Dependency injection
views 656
In questo articolo parleremo della Dependency Injection, un pattern che consente di creare applicazioni flessibili e semplifica la fase di unit test. ...
ASP.NET Core custom Middleware
views 200
Nel precedente articolo intitolato ASP.NET Core Middleware abbiamo parlato di cosa sono i middleware ed abbiamo visto come usare i middleware buit-in ...
ASP.NET Core Middleware
views 355
"Middleware are software components that are assembled into an application pipeline to handle requests and responses. Each component chooses whether t...