在ASP.NET MVC中从数据库加载Razor视图5

我们正在尝试在ASP.NET MVC 5中开发一个企业CMS应用程序。用户需要从管理应用程序创建新页面,更改现有页面内容或者全部删除页面。 另一个要求是,某些页面可以包含用Razor语法编写的自定义小部件。

这2个要求导致我从数据库加载剃须刀视图。 我搜索了一下,找到了几个例子。

第一个是扩展VirtualPathProvider,并在Application_Start方法中使用下面的表达式注册它。

protected void Application_Start()
{
    ...
    HostingEnvironment.RegisterVirtualPathProvider(new MyVirtualPathProvider());
}

当我尝试运行这个时,它会抛出下面的错误

[InvalidOperationException: The view at '~/Views/Home/Index.aspx' must derive from ViewPage, ViewPage, ViewUserControl, or ViewUserControl.]
    System.Web.Mvc.WebFormView.RenderView(ViewContext viewContext, TextWriter writer, Object instance) +180
    System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer) +107
    System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) +291
    System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) +13
    System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +56
    System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +420
    System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +52
    System.Web.Mvc.Async.c__DisplayClass2b.b__1c() +173
    System.Web.Mvc.Async.c__DisplayClass21.b__1e(IAsyncResult asyncResult) +100
    System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
    System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
    System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +27
    System.Web.Mvc.Controller.b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +13
    System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +29
    System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
    System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +36
    System.Web.Mvc.Controller.b__15(IAsyncResult asyncResult, Controller controller) +12
    System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +22
    System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
    System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +26
    System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10
    System.Web.Mvc.MvcHandler.b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +21
    System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +29
    System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
    System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +28
    System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
    System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9644097
    System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

另一个例子是

protected void Application_Start()
{
    ...
    ViewEngines.Engines.Clear();
    ViewEngines.Engines.Add(new MyViewEngine());
}

private class MyViewEngine : RazorViewEngine
{
    public MyViewEngine()
    {
        this.VirtualPathProvider = new MyVirtualPathProvider();
    }
}

当指定的文件(例如/View/Home/Index.cshtml)在文件系统中时,即使它没有任何内容,它也可以工作。 当我从文件系统中删除文件时,会引发下面的错误

[InvalidOperationException: The view 'Index' or its master was not found or no view engine supports the searched locations. The following locations were searched:
    ~/Views/Home/Index.cshtml
    ~/Views/Home/Index.vbhtml
    ~/Views/Shared/Index.cshtml
    ~/Views/Shared/Index.vbhtml]
    System.Web.Mvc.ViewResult.FindView(ControllerContext context) +382
    System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) +116
    System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) +13
    System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +56
    System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +420
    System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +52
    System.Web.Mvc.Async.c__DisplayClass2b.b__1c() +173
    System.Web.Mvc.Async.c__DisplayClass21.b__1e(IAsyncResult asyncResult) +100
    System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
    System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
    System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +27
    System.Web.Mvc.Controller.b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +13
    System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +29
    System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
    System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +36
    System.Web.Mvc.Controller.b__15(IAsyncResult asyncResult, Controller controller) +12
    System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +22
    System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
    System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +26
    System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10
    System.Web.Mvc.MvcHandler.b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +21
    System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +29
    System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
    System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +28
    System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
    System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9644097
    System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

即使您覆盖VirtualPathProvider以从数据库加载视图数据,RazorViewEngine也会尝试在文件系统中查找该文件。

我猜这些例子在ASP.NET MVC的早期版本中工作(我认为是2或3)。 我得到的最佳解决方案是从零开始编写自定义视图引擎,但要完成像剃须刀视图引擎一样的工作还有很多工作要做。 有没有其他技巧可以让这些例子起作用,或者有其他的选择吗?


看看这些链接。 希望这可能有所帮助。

http://rebuildall.umbraworks.net/2009/11/17/ASP_NET_MVC_and_virtual_views

使用自定义VirtualPathProvider加载嵌入式资源部分视图

在数据库中存储ASP.Net MVC视图

ASP.NET MVC从数据库加载Razor视图

链接地址: http://www.djcxy.com/p/72703.html

上一篇: Load Razor Views From Database in ASP.NET MVC 5

下一篇: Get error when I called RedirectToAction in server