Pergunta

Eu pensei que seria interessante se eu pudesse usar o novo mecanismo MVC Razor View como uma tecnologia de mesclagem de correio. Ainda pode fazer parte de um site do MVC e não precisa ser um aplicativo de console independente.

Exemplo:

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

Então o string output = "Hello Billy Boy, How are you today?"

O principal é que eu quero que o modelo seja dirigido de uma string em vez de uma visualização ou visualização parcial.

Alguém sabe se isso é possível ?

ATUALIZAR:

Ben e Matt fizeram um projeto no CodePlex: http://razorengine.codeplex.com/

Foi útil?

Solução

Aviso

Este é um código feio feio que foi invadido sem testá -lo além de fazê -lo funcionar corretamente.

VirtualPathProvider

Como não estamos lidando com visualizações reais no servidor, precisamos adicionar nosso próprio provedor de caminho para informar ao MVC onde obter nossos modelos gerados dinamicamente. Deve haver mais testes, como verificar o dicionário do Strings para ver se a visualização foi adicionada.

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

Classe de renderização

Esta classe pega seu modelo como um parâmetro construtor e o adiciona a um dicionário estático que é lido pelo VirtualPathProvider acima de. Você então liga Render E você pode opcionalmente passar em um modelo. Isso adicionará o tipo de modelo totalmente qualificado ao @inherits e prenda isso ao conteúdo do arquivo.

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

No seu arquivo global.asax, você terá que adicionar o seguinte ao Application_Start

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

Chamando o código

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

Notas

este funciona com modelos digitados. Tentei passar em um novo {name = "billy boy"} e está lançando erros. Não sei por que e não pareceu muito profundamente.

Isso foi divertido, obrigado por fazer esta pergunta.

Outras dicas

Razor foi projetado com operação independente em mente. Ainda não há muita documentação sobre esse modo (já que ainda está em desenvolvimento), mas dê uma olhada nesta postagem do blog de Andrew Nurse: http://vibrantcode.com/blog/2010/7/22/using-the-razor-parser-ultside-of-asaspnet.html

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