Domanda

Sto cercando di implementare alcuni modelli in un'applicazione web e volevo utilizzare i controlli basati su modelli di ASP.NET.Tuttavia, non voglio fare affidamento su file .ascx fisici o su VirtualPathProvider per caricare i modelli.

Voglio essere in grado di caricare i modelli da un database o un altro datastore (in memoria?). Esiste un'implementazione di un metodo LoadTemplate () che restituisce un ITemplate data una rappresentazione di stringa di un modello .ascx?

In caso contrario, come potrei scriverne uno?

Per tua informazione, Kentico ha una funzionalità simile, ma si basa su VirtualPathProvider per poter utilizzare LoadTemplate() sulla classe TemplateControl.Con questo metodo, sono in grado di caricare modelli (li chiamano trasformazioni) memorizzati nel database.

È stato utile?

Soluzione

Sì, VirtualPathProvider è probabilmente il metodo che vorrai utilizzare, se una stringa o un database è la fonte che desideri utilizzare.(Esistono anche generatori di codice che possono emettere codice, ma di solito vengono utilizzati quando si crea il codice in modo dinamico, non caricando da una fonte esterna come nel tuo caso.)

Tuttavia, non si menziona il perché non si desidera utilizzare VirtualPathProvider.È dovuto al fatto che non lo desideri o non puoi farlo a causa di alcuni requisiti speciali che hai in una situazione particolare?

Infine, se "sembra banale" caricare e compilare codice dinamicamente, allora non sai cosa deve fare l'intero sistema .Net prima di poter eseguire codice dinamico: generazione di assembly, compilazione e JIT, applicazionecontesti, risoluzione dei nomi di classi / membri, sicurezza del codice, ecc. Forse sei appena stato viziato dalla facilità con cui .Net ha reso altre attività complicate.;-)

Altri suggerimenti

Ho riscontrato un problema simile.Tuttavia, VirtualPathProvider è troppo idraulico da implementare per un guadagno così piccolo, per non parlare del fatto che sembra che abbia il potenziale per essere un po 'rischioso per la sicurezza da implementare.Ho trovato due possibili soluzioni:

1) Usa la riflessione per ottenere ciò che desideri:

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) Usa una soluzione un po '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;

Ammetto apertamente che nessuna delle due è un'ottima soluzione.Idealmente, ci sarebbe un metodo in .Net Framework per questo genere di cose.Qualcosa come:

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

Ciò allevierebbe l'intera necessità di implementare VirtualPathProvider.Forse lo vedremo in ASP.NET vNext :-)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top