Question

Je pensais que ce serait intéressant si je pouvais utiliser le nouveau moteur MVC Razor View comme une technologie de publipostage. Il peut encore faire partie d'un site Web MVC et ne doit pas être l'application de la console autonome.

Exemple:

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

Alors le string output = "Hello Billy Boy, How are you today?"

La chose principale est que je veux le modèle à partir d'une chaîne entraînée plutôt que d'une vue ou PartialView.

Quelqu'un sait si cela est possible?

Mise à jour:

Ben et Matt a fait un projet sur CodePlex: http://razorengine.codeplex.com/

Était-ce utile?

La solution

Avertissement

Ceci est un code laid laid qui a été piraté ensemble sans le tester autre que le faire fonctionner correctement.

VirtualPathProvider

Étant donné que nous ne traitons pas avec des vues réelles sur le serveur, nous devons ajouter notre propre fournisseur de chemin de dire MVC où obtenir nos modèles générés dynamiquement. Il devrait y avoir d'autres tests comme vérifier les chaînes Dictionnaire pour voir si la vue a été ajouté.

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)]));
        }
    }
}

Rendu classe

Cette classe prend votre modèle en tant que paramètre constructeur et l'ajoute à un dictionnaire statique qui est ensuite lu par le VirtualPathProvider ci-dessus. Vous appelez ensuite Render et vous pouvez le cas échéant passer d'un modèle. Cela ajoutera le type de modèle complet du @inherits et préfixer que pour le contenu du fichier.

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

Dans votre fichier global.asax, vous devrez ajouter ce qui suit à la Application_Start

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

Appeler le code

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

Remarques

uniquement fonctionne avec les modèles typés. Je tentais de passer dans une nouvelle {Name = « Billy Boy »} et il jette des erreurs. Je ne sais pas pourquoi et ne pas vraiment l'air trop profondément.

C'était amusant, merci d'avoir posé cette question.

Autres conseils

Razor a été conçu avec un fonctionnement autonome à l'esprit. Il n'y a pas beaucoup de documentation sur ce mode encore (car il est tout encore en développement), mais un coup d'oeil à ce blog par Andrew Nurse: http://vibrantcode.com/blog/2010/7/22/using-the-razor-parser-outside-of -aspnet.html

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top