Pergunta

Estou procurando implementar alguns modelos em um aplicativo da web e queria utilizar os controles de modelo do ASP.NET.No entanto, não quero depender de arquivos físicos .ascx ou do VirtualPathProvider para carregar os modelos.

Quero poder carregar os modelos de um banco de dados ou outro armazenamento de dados (na memória?). Existe alguma implementação de um método LoadTemplate () que retorna um ITemplate dada uma representação de string de um modelo .ascx?

Se não, como faria para escrever um?

Para sua informação, Kentico tem um recurso semelhante, mas eles contam com o VirtualPathProvider para usar o LoadTemplate() na classe TemplateControl.Com esse método, eles são capazes de carregar modelos (eles os chamam de transformações) armazenados no banco de dados.

Foi útil?

Solução

Sim, VirtualPathProvider é provavelmente o método que você desejará usar, se uma string ou banco de dados for a fonte que deseja usar.(Existem também geradores de código que podem emitir código, mas geralmente aqueles são usados ao construir o código dinamicamente - não carregando de uma fonte externa como no seu caso.)

No entanto, você não mencionou por que não deseja usar o VirtualPathProvider.É por não querer ou não pode por causa de alguns requisitos especiais que você tem em uma determinada situação?

Finalmente, se "parece trivial" carregar e compilar o código dinamicamente, você não sabe o que todo o sistema .Net tem que fazer antes de executar o código dinâmico - geração de montagem, compilação e JIT, aplicativocontextos, resolução de nome de classe / membro, segurança de código, etc. Talvez você só tenha estragado com a facilidade com que o .Net tornou a realização de outras tarefas complicadas.;-)

Outras dicas

Tenho enfrentado um problema semelhante.No entanto, o VirtualPathProvider é muito complicado de implementar para um ganho tão pequeno - sem mencionar que parece que tem o potencial de ser um pouco arriscado de implementar em termos de segurança.Encontrei duas soluções possíveis:

1) Use reflexão para chegar ao que deseja:

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) Use uma solução alternativa um tanto hacky:

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;

Eu admito abertamente que nenhuma das duas é uma boa solução.Idealmente, haveria um método no .Net Framework para esse tipo de coisa.Algo como:

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

Isso aliviaria toda a necessidade de implementar o VirtualPathProvider.Talvez veremos isso no ASP.NET vNext :-)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top