在 ASP.NET MVC 5 中从数据库加载 Razor 视图
Posted
技术标签:
【中文标题】在 ASP.NET MVC 5 中从数据库加载 Razor 视图【英文标题】:Load Razor Views From Database in ASP.NET MVC 5 【发布时间】:2016-11-25 08:10:15 【问题描述】:我们正在尝试在 ASP.NET MVC 5 中开发企业 CMS 应用程序。用户需要从管理应用程序中创建新页面、更改现有页面内容或删除页面。另一个要求是某些页面可以包含用 Razor 语法编写的自定义小部件。
这两个要求导致我从数据库加载剃刀视图。我用谷歌搜索并找到了几个例子。
第一个是扩展 VirtualPathProvider 并在 Application_Start 方法中使用下面的表达式注册它。
protected void Application_Start()
...
HostingEnvironment.RegisterVirtualPathProvider(new MyVirtualPathProvider());
当我尝试运行它时,它会抛出下面的错误
[InvalidOperationException:'~/Views/Home/Index.aspx' 处的视图必须派生自 ViewPage、ViewPage、ViewUserControl 或 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 上下文)+291 System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) +13 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 过滤器,Int32 filterIndex,ResultExecutingContext preContext,ControllerContext controllerContext,ActionResult actionResult)+56 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 过滤器,Int32 filterIndex,ResultExecutingContext preContext,ControllerContext controllerContext,ActionResult actionResult)+420 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 过滤器, 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,控制器控制器)+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 结果) +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:未找到视图“索引”或其主视图,或者没有视图引擎支持搜索的位置。搜索了以下位置: ~/Views/Home/Index.cshtml ~/Views/Home/Index.vbhtml ~/Views/Shared/Index.cshtml ~/Views/Shared/Index.vbhtml] System.Web.Mvc.ViewResult.FindView(ControllerContext 上下文)+382 System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext 上下文)+116 System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) +13 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 过滤器,Int32 filterIndex,ResultExecutingContext preContext,ControllerContext controllerContext,ActionResult actionResult)+56 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 过滤器,Int32 filterIndex,ResultExecutingContext preContext,ControllerContext controllerContext,ActionResult actionResult)+420 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 过滤器, 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,控制器控制器)+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 结果) +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)。我得到的最好的解决方案是从头开始编写一个自定义视图引擎,但是要让它像剃刀视图引擎一样工作还有很多工作要做。是否有任何其他技巧可以使这些示例正常工作,或者任何其他替代方法?
【问题讨论】:
【参考方案1】:看看这些链接。希望这可能会有所帮助。
http://rebuildall.umbraworks.net/2009/11/17/ASP_NET_MVC_and_virtual_views
Using custom VirtualPathProvider to load embedded resource Partial Views
Storing ASP.Net MVC Views in the Database
ASP.NET MVC load Razor view from database
【讨论】:
以上是关于在 ASP.NET MVC 5 中从数据库加载 Razor 视图的主要内容,如果未能解决你的问题,请参考以下文章
无法在 ASP.NET MVC 5 中从视图到控制器获取 Select2 标记值
在 MVC4 RTM 中从 ASP.NET 成员身份迁移到 SimpleMembership
在 asp.net-mvc 中从服务器读取文本文件的最佳方法是啥
在asp.net mvc中从具有多对多关系的数据库中获取记录
在 ASP.Net MVC 应用程序中从 Facebook SDK for .Net 获取 Facebook 用户访问令牌