c# - Diseños de RazorEngine
(3)
Estoy usando el motor de Razor https://github.com/Antaris/RazorEngine para analizar el cuerpo de mis plantillas de correo electrónico. ¿Es posible definir un diseño e incluir otros archivos .cshtml? por ejemplo, un encabezado común y un pie de página.
Conseguí plantillas comunes y un diseño funcional, con la ayuda de estas dos publicaciones:
RazorEngine cadenas de diseños y secciones?
Esta es mi solución:
Solución 1: Diseño
Se utiliza para establecer _Layout
@{
_Layout = "Layout.cshtml";
ViewBag.Title = Model.Title;
}
Pie de página
@section Footer
{
@RenderPart("Footer.cshtml")
}
Layout.cshtml
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html>
<head>
</head>
<body>
<div id="content">
@RenderBody()
</div>
@if (IsSectionDefined("Footer"))
{
<div id="footer">
@RenderSection("Footer")
</div>
}
</body>
</html>
TemplateBaseExtensions
Extienda TemplateBase con un método RenderPart
public abstract class TemplateBaseExtensions<T> : TemplateBase<T>
{
public string RenderPart(string templateName, object model = null)
{
string path = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "Templates", templateName);
return Razor.Parse(File.ReadAllText(path), model);
}
}
Maquinilla de afeitar
Establezca BaseTemplateType en su clase TemplateBaseExtensions
TemplateServiceConfiguration templateConfig = new TemplateServiceConfiguration
{
BaseTemplateType = typeof(TemplateBaseExtensions<>)
};
Razor.SetTemplateService(new TemplateService(templateConfig));
Editar Solución 2:
Si está utilizando un TemplateResolver. RenderPart no es necesario usar el @Include en su lugar
Pie de página
@section Footer
{
@Include("Footer.cshtml")
}
Resolución
public class TemplateResolver : ITemplateResolver
{
public string Resolve(string name)
{
if (name == null)
{
throw new ArgumentNullException("name");
}
string path = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "Templates", name);
return File.ReadAllText(path, System.Text.Encoding.Default);
}
}
Config
TemplateServiceConfiguration templateConfig = new TemplateServiceConfiguration
{
Resolver = new TemplateResolver()
};
Razor.SetTemplateService(new TemplateService(templateConfig));
Actualización de The Muffin Man Especifique una plantilla y renderice una cadena
var templateResolver = Razor.Resolve("Registration.cshtml");
return templateResolver.Run(new ExecuteContext());
También yo, junto con otros en este enlace https://github.com/Antaris/RazorEngine/issues/61 tuve problemas con el uso de _Layout
mientras que Layout
funcionó.
''_Layout'' es la sintaxis antigua. Se actualizó a ''Diseño'' en una versión futura.
La forma más fácil de implementar un diseño con RazorEngine es reemplazando lo que devuelve su plantilla en @RenderBody () del diseño:
var finalHtml = layout.Replace(@"@RenderBody()", templateHtml);
P.ej:
Tu _Layout.cshtml con el típico @RenderBody ()
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html>
<head>
</head>
<body>
<div>
@RenderBody()
</div>
</body>
</html>
Tu plantilla RazorEngine MyTemplate.cshtml
@using RazorEngine.Templating
@inherits TemplateBase<myviewmodel>
<h1>Hello People</h1>
<p>@Model</p>
Y donde sea que llames la plantilla RazorEngine:
var TemplateFolderPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "EmailTemplates");
var template = File.ReadAllText(Path.Combine(TemplateFolderPath,"MyTemplate.cshtml"));
var layout = File.ReadAllText(Path.Combine(TemplateFolderPath, "_Layout.cshtml"));
var templateService = new TemplateService();
var templateHtml = templateService.Parse(template, myModel, null, null);
var finalHtml = layout.Replace(@"@RenderBody()", templateHtml);
Puedes hacer muchas cosas fácilmente con Razor; Sin embargo, ese proyecto en particular parece abstraer un montón de cosas del motor de Razor que podrías hacer (lo que es bueno y malo). En su situación, parece que estaría mucho mejor implementando su propia solución Razor (en realidad no es tan malo) y luego puede hacer que sus plantillas lancen excepciones o atraigan otro contenido con bastante facilidad.
Por ejemplo; Rodar su propia solución le permite crear una clase base para sus plantillas de maquinilla de afeitar que puede exponer la capacidad de obtener "vistas parciales" invocando otras plantillas. Además, puede realizar verificaciones de modelos y lanzar excepciones si ciertas propiedades son nulas.