Pregunta

Estoy buscando implementar algunas plantillas en una aplicación web y quería utilizar los controles basados en plantillas de ASP.NET.Sin embargo, no quiero depender de archivos físicos .ascx o VirtualPathProvider para cargar las plantillas.

Quiero poder cargar las plantillas desde una base de datos u otro almacén de datos (¿en memoria?). ¿Existe alguna implementación de un método LoadTemplate () que devuelva un ITemplate dada una representación de cadena de una plantilla .ascx?

Si no es así, ¿cómo podría escribir uno?

Para su información, Kentico tiene una característica similar, pero se basan en VirtualPathProvider para usar el LoadTemplate() en la clase TemplateControl.Con ese método, pueden cargar plantillas (las llaman transformaciones) almacenadas en la base de datos.

¿Fue útil?

Solución

Sí, VirtualPathProvider es probablemente el método que querrá usar, si una cadena o base de datos es la fuente que desea usar.(También hay generadores de código que pueden emitir código, pero por lo general se utilizan cuando se crea el código de forma dinámica, no se cargan desde una fuente externa como en su caso).

Sin embargo, no mencionas por qué no quieres usar VirtualPathProvider.¿Se debe a que no quiere o no puede debido a algunos requisitos especiales que tiene en una situación particular?

Por último, si "parece trivial" cargar y compilar código dinámicamente, entonces no sabe qué tiene que hacer todo el sistema .Net antes de que pueda ejecutar código dinámico: generación de ensamblado, compilación y JIT, aplicacióncontextos, resolución de nombre de clase / miembro, seguridad de código, etc. Tal vez te haya echado a perder lo fácil que ha hecho .Net hacer otras tareas complicadas.;-)

Otros consejos

Me he enfrentado a un problema similar.Sin embargo, VirtualPathProvider es demasiado complicado de implementar para una ganancia tan pequeña, sin mencionar que parece que tiene el potencial de ser un poco arriesgado en cuanto a seguridad de implementar.Encontré dos posibles soluciones:

1) Reflexiona para llegar a lo que quieres:

var page = HttpContext.Current.Handler as Page;
string text = "<table><tr><td>Testing!!!</td></tr></table>";
var systemWebAssembly = System.Reflection.Assembly.GetAssembly(typeof(Page));
var virtualPathType = systemWebAssembly.GetTypes().Where(t => t.Name == "VirtualPath").FirstOrDefault(); // Type.GetType("System.Web.VirtualPath");
var createMethod = virtualPathType.GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public).Where(m => m.Name == "Create" && m.GetParameters().Length == 1).FirstOrDefault();
object virtualPath = createMethod.Invoke(null, new object[]
{ 
    page.AppRelativeVirtualPath 
});
var template = (ITemplate)typeof(TemplateParser).GetMethod("ParseTemplate", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).Invoke(null, new object[]{text, virtualPath, true});

2) Utilice una solución un tanto intrincada:

var page = HttpContext.Current.Handler as Page;
string text = "<table><tr><td>Testing!!!</td></tr></table>";
string modifiedText = string.Format("<asp:UpdatePanel runat=\"server\"><ContentTemplate>{0}</ContentTemplate></asp:UpdatePanel>", text);
var control = page.ParseControl(modifiedText);
var updatePanel = control.Controls[0] as UpdatePanel;
var template = updatePanel.ContentTemplate;

Administro abiertamente que ninguna de las dos es una gran solución.Idealmente, habría un método en .Net Framework para este tipo de cosas.Algo como:

public class TemplateParser
{
    public static ITemplate ParseTemplate(string content, string virtualPath, bool ignoreParserFilter)
    {
        return TemplateParser.ParseTemplate(string content, VirtualPath.Create(virtualPath), ignoreParserFilter);
    }
}

Eso aliviaría toda la necesidad de implementar VirtualPathProvider.Tal vez veamos eso en ASP.NET vNext :-)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top