Usando la vista motor de la maquinilla de afeitar de una manera diferente
-
25-09-2019 - |
Pregunta
pensé que sería interesante si podía usar el nuevo motor MVC Razor Ver como una tecnología de combinación de correspondencia. Todavía puede ser parte de una página web MVC y no tiene que ser aplicación de consola independiente.
Ejemplo:
string myTemplate = "Hello @Name, How are you today?";
ViewModel.Name = "Billy Boy";
string output = RazorViewEngineRender( myTemplate, ViewModel );
A continuación, el string output = "Hello Billy Boy, How are you today?"
Lo más importante es que quiero la plantilla para ser conducido de una cadena en lugar de una vista o PartialView.
¿Alguien sabe si esto es posible?
ACTUALIZACIÓN:
Ben y Matt hicieron un proyecto en CodePlex: http://razorengine.codeplex.com/
Solución
Advertencia
Esto es código fea fea que fue hackeado sin probarlo aparte de conseguir que funcione correctamente.
VirtualPathProvider
Debido a que no estamos tratando con verdaderos puntos de vista en el servidor tenemos que añadir nuestro propio proveedor de ruta para contar MVC donde conseguir nuestras plantillas generadas dinámicamente. No debe haber más pruebas como la comprobación de las cadenas del diccionario para ver si el punto de vista ha sido añadido.
public class StringPathProvider : VirtualPathProvider {
public StringPathProvider()
: base() {
}
public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart) {
return null;
}
public override bool FileExists(string virtualPath) {
if (virtualPath.StartsWith("/stringviews") || virtualPath.StartsWith("~/stringviews"))
return true;
return base.FileExists(virtualPath);
}
public override VirtualFile GetFile(string virtualPath) {
if (virtualPath.StartsWith("/stringviews") || virtualPath.StartsWith("~/stringviews"))
return new StringVirtualFile(virtualPath);
return base.GetFile(virtualPath);
}
public class StringVirtualFile : System.Web.Hosting.VirtualFile {
string path;
public StringVirtualFile(string path)
: base(path) {
//deal with this later
this.path = path;
}
public override System.IO.Stream Open() {
return new System.IO.MemoryStream(System.Text.ASCIIEncoding.ASCII.GetBytes(RazorViewEngineRender.strings[System.IO.Path.GetFileName(path)]));
}
}
}
Render Clase
Esta clase tiene su plantilla como un parámetro de constructor y lo añade a una estructura estática diccionario que luego es leído por el VirtualPathProvider
anteriormente. A continuación, llama a Render
y se puede pasar opcionalmente en un modelo. Esto añadirá el tipo de modelo completa al @inherits
y anteponer a que el contenido del archivo.
public class RazorViewEngineRender {
internal static Dictionary<string, string> strings { get; set; }
string guid;
static RazorViewEngineRender() {
strings = new Dictionary<string, string>();
}
public RazorViewEngineRender(string Template) {
guid = Guid.NewGuid().ToString() + ".cshtml";
strings.Add(guid, Template);
}
public string Render() {
return Render(null);
}
public string Render(object ViewModel) {
//Register model type
if (ViewModel == null) {
strings[guid] = "@inherits System.Web.Mvc.WebViewPage\r\n" + strings[guid];
} else {
strings[guid] = "@inherits System.Web.Mvc.WebViewPage<" + ViewModel.GetType().FullName + ">\r\n" + strings[guid];
}
CshtmlView view = new CshtmlView("/stringviews/" + guid);
System.Text.StringBuilder sb = new System.Text.StringBuilder();
System.IO.TextWriter tw = new System.IO.StringWriter(sb);
ControllerContext controller = new ControllerContext();
ViewDataDictionary ViewData = new ViewDataDictionary();
ViewData.Model = ViewModel;
view.Render(new ViewContext(controller, view, ViewData, new TempDataDictionary(), tw), tw);
//view.ExecutePageHierarchy();
strings.Remove(guid);
return sb.ToString();
}
}
Global.asax
En el archivo Global.asax que tendrá que añadir lo siguiente a la Application_Start
System.Web.Hosting.HostingEnvironment.RegisterVirtualPathProvider(new Controllers.StringPathProvider());
Llamando el código
string Template = "Hello, @Model.Name";
Models.User user = new Models.User() { Name = "Billy Boy" };
RazorViewEngineRender view = new RazorViewEngineRender(Template);
string Results = view.Render(user); //pass in your model
Notas
Este sólo los trabajos con modelos mecanografiadas. Me trató de pasar en una nueva {Name = "Billy Boy"} y se está lanzando errores. No estoy seguro de por qué y en realidad no mirar demasiado profundamente en ella.
Esto fue muy divertido, gracias por hacer esta pregunta.
Otros consejos
Razor fue diseñado con funcionamiento autónomo en mente. Todavía no existe mucha documentación acerca de ese modo (ya que todo todavía en desarrollo), pero echar un vistazo a esta entrada del blog de Andrew Enfermera: http://vibrantcode.com/blog/2010/7/22/using-the-razor-parser-outside-of -aspnet.html