Add template for email, already defined in .cshtml

0

I am sending an email to the user who forgot their password, the email can now be sent, but I would like to add a personalized template. I do not know if it would be possible to pass the view .cshtml as a body parameter to the email.

I already have a defined .cshtml template, and I think that if I included the html code in the controller it would not look good, because it would be many lines of code.

 // POST: /Account/ForgotPassword
    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> ForgotPassword(ForgotPasswordViewModel model)
    {
        //Verify Email
        //Generate Reset Password link
        //Send Email
        if (ModelState.IsValid)
        {
            var user = await UserManager.FindByNameAsync(model.Email);
            // if (user == null || !(await UserManager.IsEmailConfirmedAsync(user.Id)))
            if (user == null)
            {
                ModelState.AddModelError("", "El correo es invalido");
                // Don't reveal that the user does not exist or is not confirmed
                return View("ForgotPasswordConfirmation");
            }


            var emailService = new EmailService();


            string code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
            var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);

            string Body = "Please reset your password by clicking <a href=\"" + callbackUrl + "\">here</a>";
            await UserManager.SendEmailAsync(user.Id, "Reset Password", Body );

            return RedirectToAction("ForgotPasswordConfirmation", "Account");
        }

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


    }

in this line we send as parameter the body of the email

  

string Body="Please reset your password by clicking here";
              await UserManager.SendEmailAsync (user.Id, "Reset Password", Body);

I hope your help. Thank you very much :)

    
asked by ViA Alondra 16.07.2018 в 16:33
source

2 answers

1

I found the solution in the following way

  // POST: /Account/ForgotPassword
    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> ForgotPassword(ForgotPasswordViewModel model)
    {
        if (ModelState.IsValid)
        {
            var user = await UserManager.FindByNameAsync(model.Email);
            if (user == null)
            {
                ModelState.AddModelError("", "El correo es invalido");
                return View("ForgotPasswordConfirmation");
            }

            string code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
            var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);

            //En esta parte mando a llamar el método CreateBody que servira para pasar la plantilla personalizada, ya creada en .cshtml al email que se le enviara al usuario
            await UserManager.SendEmailAsync(user.Id, "Restablecer Contraseña", CreateBody(model.Email,callbackUrl) );

            return RedirectToAction("ForgotPasswordConfirmation", "Account");
        }

        return View(model);


    }

This is the method that is sent to call

    //Pasar archivo Email/Index.cshtml para enviar plantilla por email.
    //Recibe el parametro del email del usuario y el link para restablecer contraseña.
    private string CreateBody(string email, string link)
   {
        string body = string.Empty;
          //Esta es la ubicación de la plantilla personalizada ("~/Views/Email/Index.cshtml")
        using (StreamReader reader = new StreamReader(Server.MapPath("~/Views/Email/Index.cshtml") ))
        {
            body = reader.ReadToEnd();
        }
        //en la plantilla .cshtml en el lugar que agregaria el email le 
       // agrege {fname} y el lugar del link para restablecer contraseña{flink}
       //remplaza {fname} con el email y {flink} con el link, que son los parámetros que le asigne al metodo
        body = body.Replace("{femail}",email);
        body = body.Replace("{flink}", link);
        return body;
   }

This is a part of the template that you send by mail. I removed the styles to not enter so much information.

<tbody>
     <tr>
         <td >
              <div>
                    // aqui va el correo 
                   <h2 >¡Hola {femail}! </h2>
                    <br />
                    <h4 >
                           Haga click en el siguiente enlace para restablecer tu contraseña. 
                    </h4>
                     <h4>
                       //aqui va el link
                         <a href="{flink}"> Click para restablecer la contraseña </a>
                    </h4>
               </div>
            </td>
        </tr>
 </tbody>
    
answered by 19.07.2018 / 21:20
source
1

in theory you can send it an html string, with this I mean you should render the view in the first instance, some time ago I used a nugget for this, I do not know if there are modern alternatives enter the description of the link here

There is an example of how to use it in the asp net forum

link

Basically in the view controller you want to send, you put the code for the render (or you can create a generic email controller and inherit the ones you want to implement)

public static string RenderViewToString(this Controller controller, string viewName, object model)
{
    controller.ViewData.Model = model;
    try
    {
        using (StringWriter sw = new StringWriter())
        {
            ViewEngineResult viewResult = ViewEngines.Engines.FindView(controller.ControllerContext, viewName, null);
            ViewContext viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
            viewResult.View.Render(viewContext, sw);
            viewResult.ViewEngine.ReleaseView(controller.ControllerContext, viewResult.View);

            return sw.ToString();
        }
    }
    catch(Exception ex)
    {
        return ex.ToString();
    }
}

and in the call of it

    public ActionResult SendMail()
{
    // Get your Model Object
    var model = new MyViewUser();

    var output = this.RenderViewToString("~/Views/Controller/SendEmail.cshtml", model)
}
    
answered by 16.07.2018 в 16:53