Is there a convenient way to return a view from a string instead of having to come from a file on disk?
I've implemented a custom VirtualPathProvider
that handles retrieving views from a database, but I don't always want the view to be stored in the database.
Update 2-15-2011
I stumbled across a very nice open source component that simplifies the process of compiling Razor views in code.I've replaced much of the Virtual Path Provider code with this component, and it's working incredibly well. I recommend it to anyone that's trying to compile views from a database or elsewhere who doesn't need the additional capabilities of a virtual path provider. This component lets you compile the view directly within your controller/app/whatever (web context and controller context not required) without having to jump through the VPP hoops.
You can run the view yourself by creating a RazorTemplateEngine
which reads your source and compiles into a WebViewPage
.
You can then run the WebViewPage
by writing
webViewPage.OverridenLayoutPath = LayoutPath;
webViewPage.VirtualPath = ViewPath;
webViewPage.ViewContext = viewContext;
webViewPage.ViewData = viewContext.ViewData;
webViewPage.InitHelpers();
WebPageRenderingBase startPage = null;
if (RunViewStartPages) {
startPage = StartPageLookup(webViewPage, RazorViewEngine.ViewStartFileName, ViewStartFileExtensions);
}
webViewPage.ExecutePageHierarchy(new WebPageContext(context: viewContext.HttpContext, page: null, model: null), writer, startPage);
To support the new @model
keyword, you'll need to override methods in your RazorEngineHost to use MVC's custom generators:
public override RazorCodeGenerator DecorateCodeGenerator(RazorCodeGenerator incomingCodeGenerator) {
if (incomingCodeGenerator is CSharpRazorCodeGenerator) {
return new MvcCSharpRazorCodeGenerator(incomingCodeGenerator.ClassName,
incomingCodeGenerator.RootNamespaceName,
incomingCodeGenerator.SourceFileName,
incomingCodeGenerator.Host);
}
else if (incomingCodeGenerator is VBRazorCodeGenerator) {
return new MvcVBRazorCodeGenerator(incomingCodeGenerator.ClassName,
incomingCodeGenerator.RootNamespaceName,
incomingCodeGenerator.SourceFileName,
incomingCodeGenerator.Host);
}
return base.DecorateCodeGenerator(incomingCodeGenerator);
}
public override ParserBase DecorateCodeParser(ParserBase incomingCodeParser) {
if (incomingCodeParser is CSharpCodeParser) {
return new MvcCSharpRazorCodeParser();
}
else if (incomingCodeParser is VBCodeParser) {
return new MvcVBRazorCodeParser();
}
else {
return base.DecorateCodeParser(incomingCodeParser);
}
}