Usando o mecanismo de vista de barbear de uma maneira diferente
-
25-09-2019 - |
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/
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 só 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