Rendre une vue à la volée
-
03-07-2019 - |
Question
Je développe une application ASP.NET MVC qui enverra un courrier électronique de confirmation à l'utilisateur. Pour le courrier électronique lui-même, j'aimerais créer une vue, puis la rendre et l'envoyer à l'aide des objets de messagerie .NET.
Comment puis-je faire cela en utilisant le framework MVC?
La solution 2
Selon mon commentaire sur la réponse de Richard, ce code fonctionnait, mais il entraînait toujours l'erreur "Impossible de rediriger après l'envoi des en-têtes HTTP".
Après un lot de fouilles dans Google et de frustration, j'ai enfin trouvé du code qui semble faire l'affaire, sur cet article:
http: //mikehadlow.blogspot .com / 2008/06 / mvc-framework-capture-output-of-view_05.html
La méthode de ce type consiste à créer son propre HttpContext.
Plutôt que d'utiliser MVCContrib BlockRenderer, je remplace simplement le HttpContext actuel par un nouveau qui héberge une réponse qui écrit dans un StringWriter.
Cette méthode fonctionne parfaitement (une différence mineure est que j'ai dû créer une action distincte pour rendre ma vue partielle, mais aucun drame là-bas).
Autres conseils
Vous devez utiliser IView.Render
. Vous pouvez obtenir la vue en utilisant ViewEngineCollection.FindView
( ViewEngines.Engines.FindView
pour les valeurs par défaut). Rendez la sortie dans un TextWriter
et assurez-vous d'appeler ViewEngine.ReleaseView
par la suite. Exemple de code ci-dessous (non testé):
StringWriter output = new StringWriter();
string viewName = "Email";
string masterName = "";
ViewEngineResult result = ViewEngines.Engines.FindView(ControllerContext, viewName, masterName);
ViewContext viewContext = new ViewContext(ControllerContext, result.View, viewData, tempData);
result.View.Render(viewContext, output);
result.ViewEngine.ReleaseView(ControllerContext, result.View);
string viewOutput = output.ToString();
Je vous laisserai viewData / tempData.
Cela a fonctionné pour moi:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
namespace Profiteer.WebUI.Controllers
{
public class SampleController : Controller
{
public ActionResult Index()
{
RenderViewAsHtml(RouteData.Values["controller"].ToString(),
RouteData.Values["action"].ToString());
return View();
}
private void RenderViewAsHtml(string controllerName, string viewName)
{
var vEngine = (from ve in ViewEngineCollection
where ve.GetType() == typeof(RazorViewEngine)
select ve).FirstOrDefault();
if (vEngine != null)
{
var view =
vEngine.FindView(
ControllerContext,
viewName, "_Layout", false).View as RazorView;
if (view != null)
{
var outPath =
Server.MapPath(
string.Format("~/Views/{0}/{1}.html",
controllerName, viewName));
using (var sw = new StreamWriter(outPath, false))
{
var viewContext =
new ViewContext(ControllerContext,
view,
new ViewDataDictionary(),
new TempDataDictionary(),
sw);
view.Render(viewContext, sw);
}
}
}
}
}
}