Domanda

Ho pensato che sarebbe stato interessante se ho potuto utilizzare il nuovo motore MVC Razor vista come una tecnologia di stampa unione. Si può ancora essere parte di un sito web MVC e non deve essere stand-alone console app.

Esempio:

string  myTemplate = "Hello @Name,  How are you today?";
ViewModel.Name = "Billy Boy";
string output = RazorViewEngineRender( myTemplate, ViewModel );

Poi il string output = "Hello Billy Boy, How are you today?"

La cosa principale è che voglio il modello per essere guidato da una stringa piuttosto che una vista o PartialView.

Qualcuno sa se questo è possibile?

UPDATE:

Ben e Matt ha fatto un progetto su CodePlex: http://razorengine.codeplex.com/

È stato utile?

Soluzione

Attenzione

Questo è un codice brutto brutto che è stato messo insieme senza prove diverso riuscite a farla funzionare correttamente.

VirtualPathProvider

Dal momento che non si tratta di vista reale sul server dobbiamo aggiungere il nostro provider di percorso per dire MVC dove trovare i nostri modelli generati in modo dinamico. Ci dovrebbe essere più prove di come controllare le corde dizionario per vedere se è stata aggiunta la vista.

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 Classe

Questa classe prende il modello come un parametro del costruttore e lo aggiunge a una statica dizionario che viene poi letto dal VirtualPathProvider sopra. È quindi chiamare Render e si può opzionalmente passare in un modello. Questo aggiungerà il tipo di modello completo del @inherits e anteporre che per il contenuto del file.

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

Nel file Global.asax si dovrà aggiungere il seguente alla Application_Start

System.Web.Hosting.HostingEnvironment.RegisterVirtualPathProvider(new Controllers.StringPathProvider());

Chiamare il codice

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

Note

Questo solo lavori con i modelli tipizzati. Ho tentato di passare in una nuova {Name = "Billy Boy"} e sta gettando errori. Io non sono sicuro perché e ha fatto in realtà non guardare troppo profondamente in essa.

Questo è stato divertente, grazie per questa domanda.

Altri suggerimenti

Razor è stato progettato con il funzionamento stand-alone in mente. Non c'è molto documentazione su quella modalità ancora (dal momento che è tutto ancora in fase di sviluppo), ma dare un'occhiata a questo post sul blog di Andrew Infermiera: http://vibrantcode.com/blog/2010/7/22/using-the-razor-parser-outside-of -aspnet.html

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