App.Web
和App.Views
是我在一个解决方案中的项目,我将 View 放入App.Views中并用RazorGenerator预编译。如果我像这样使用App.Web
,效果很好
它可以在App.Web中成功呈现此 View
public ActionResult Index() {
return View("~/Views/Index.cshtml");
}
但是当我尝试
RenderViewToString
时,它返回null
。class FakeController : ControllerBase
{
protected override void ExecuteCore() { }
public static string RenderViewToString(string controllerName, string viewName, object viewData)
{
using (var writer = new StringWriter())
{
var routeData = new RouteData();
routeData.Values.Add("controller", controllerName);
var fakeControllerContext = new ControllerContext(new HttpContextWrapper(new HttpContext(new HttpRequest(null, "http://google.com", null), new HttpResponse(null))), routeData, new FakeController());
var razorViewEngine = new RazorViewEngine();
var razorViewResult = razorViewEngine.FindView(fakeControllerContext, viewName, "", false);
var viewContext = new ViewContext(fakeControllerContext, razorViewResult.View, new ViewDataDictionary(viewData), new TempDataDictionary(), writer);
razorViewResult.View.Render(viewContext, writer);
return writer.ToString();
}
}
}
这是怎么回事,
FakeController.RenderViewToString("FakeName", "~/Views/Index.csthml", MessageModel);
This is discussed and probably solved in asp.net core,但我正在使用asp.net mvc 5。
您能帮我弄清楚为什么它不起作用吗?
最佳答案
您正在尝试使用Razor View Engine获取预编译的 View 。这是个错误。 Razor引擎基于cshtml文件生成 View 。但是,在使用预编译 View 的情况下,RazorGenerator
已将cshtml文件编译为从System.Web.Mvc.WebViewPage
派生的一组类。这些类覆盖方法Execute()
(由RazorGenerator
基于输入cshtml自动生成),该方法将html写入以输出TextWriter
。
不再需要原始 View 文件(cshtml),因此不会与应用程序一起部署。当您调用试图定位cshtml并基于其构建 View 的Razor时,它预期会返回null
View 。
ASP.NET MVC支持多个 View 引擎(实现System.Web.Mvc.IViewEngine
的类)。 RazorViewEngine
是其中之一。 RazorGenerator.Mvc
NuGet软件包添加了自己的 View 引擎(PrecompiledMvcEngine
),该引擎基于预编译的 View 工作。注册的 View 引擎存储在ViewEngines.Engines
集合中。当您安装RazorGenerator.Mvc
NuGet软件包时,它将添加RazorGeneratorMvcStart
类,该类注册PrecompiledMvcEngine
的实例:
[assembly: WebActivatorEx.PostApplicationStartMethod(typeof(App.Views.RazorGeneratorMvcStart), "Start")]
namespace App.Views {
public static class RazorGeneratorMvcStart {
public static void Start() {
var engine = new PrecompiledMvcEngine(typeof(RazorGeneratorMvcStart).Assembly) {
UsePhysicalViewsIfNewer = HttpContext.Current.Request.IsLocal
};
ViewEngines.Engines.Insert(0, engine);
// StartPage lookups are done by WebPages.
VirtualPathFactoryManager.RegisterVirtualPathFactory(engine);
}
}
}
您应使用
PrecompiledMvcEngine
的此实例而不是RazorViewEngine
来访问预编译的 View 。这是RenderViewToString
方法的调整后的代码:public static string RenderViewToString(string controllerName, string viewName, object viewData)
{
using (var writer = new StringWriter())
{
var routeData = new RouteData();
routeData.Values.Add("controller", controllerName);
var fakeControllerContext = new ControllerContext(new HttpContextWrapper(new HttpContext(new HttpRequest(null, "http://google.com", null), new HttpResponse(null))), routeData, new FakeController());
var viewEngine = ViewEngines.Engines.OfType<PrecompiledMvcEngine>().FirstOrDefault();
if (viewEngine == null)
{
throw new InvalidOperationException("PrecompiledMvcEngine is not registered");
}
var viewResult = viewEngine.FindView(fakeControllerContext, viewName, "", false);
var viewContext = new ViewContext(fakeControllerContext, viewResult.View, new ViewDataDictionary(viewData), new TempDataDictionary(), writer);
viewResult.View.Render(viewContext, writer);
return writer.ToString();
}
}
一个重要的注意事项:应该将
RazorGenerator.Mvc
NuGet软件包与 View 一起安装到项目中(App.Views
),而不是Web应用程序项目中,因为PrecompiledMvcEngine
将当前程序集用作预编译 View 的源。 Aslo确保未将RazorGeneratorMvcStart
添加到App.Web
项目中。当我添加了对RazorGenerator.Mvc.dll
程序集的引用时,它就发生了。Sample Project on GitHub
关于asp.net - RazorViewEngine.FindView找不到预编译的 View ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49399800/