使用VirtualPathProvider从DLL中加载ASP.NET MVC视图

40

基于这个问题here,并使用在这里找到的代码,我正在尝试加载嵌入在另一个DLL项目中的视图资源,原问题的作者表示他已经成功实现了这一点 - 但我无法让它工作,因为似乎MVC视图引擎正在拦截请求并仍然查看文件系统中的视图。异常:

Server Error in '/' Application.
The view 'Index' or its master could not be found. The following locations were searched:
~/Views/admin/Index.aspx
~/Views/admin/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx
~/App/Views/admin/Index.aspx
~/App/Views/admin/Index.ascx
~/App/Views/Shared/Index.aspx
~/App/Views/Shared/Index.ascx 

我正在使用一个CustomViewEngine,就像Rob Connery的/App结构一样:

public class CustomViewEngine : WebFormViewEngine
    {
         public CustomViewEngine()
         {
             MasterLocationFormats = new[] { 
                "~/App/Views/{1}/{0}.master", 
                "~/App/Views/Shared/{0}.master" 
                };

             ViewLocationFormats = new[] { 
                "~/App/Views/{1}/{0}.aspx", 
                "~/App/Views/{1}/{0}.ascx", 
                "~/App/Views/Shared/{0}.aspx", 
                "~/App/Views/Shared/{0}.ascx" 
                };

             PartialViewLocationFormats = ViewLocationFormats;
         }
    }

这是我的路由:

    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute("Home", "", new {controller = "Page", action = "Index", id = "Default"});
    routes.MapRoute("Default", "Page/{id}", new { controller = "Page", action = "Index", id = "" });
    routes.MapRoute("Plugins", "plugin/{controller}/{action}", new { controller = "", action = "Index", id = "" });
    routes.MapRoute("Error", "{*url}", new { controller = "Error", action = "ResourceNotFound404" });
在我的 AssemblyResourceProvider 中,我正在检查路径是否以 ~/plugin/ 开头,然后使用 dll 文件命名约定 plugin.{controller}.dll
有什么建议吗? 更新: 当针对 http://localhost/plugin/admin 的路由请求到达 VirtualFileProvider 时,它没有任何 View 附加在末尾。因此,在 VirtualFileProvider 的 Open 方法中,虚拟路径 ~/plugin/admin 被传递进来,而应该是根据我的上面定义的路由 ~/plugin/admin/Index.aspx。我是搞砸了我的路由还是应该期望这种情况发生?

3
第一个FileExists调用发生在控制器运行之前,必须返回false,否则IIS将尝试将其作为静态文件提供。实际aspx文件的请求稍后发生,在控制器请求视图时进行。 - Tom Clarkson
2个回答

24
  1. 你必须在Global.asaxApplication_Start处理程序中注册VirtualPathProvider
  2. 你必须使用特殊路径调用您DLL中的视图,例如:return View("~/Plugin/YOURDLL.dll/FULLNAME_YOUR_VIEW.aspx");

这篇文章提供了可下载的代码示例,演示了这一过程:

http://www.wynia.org/wordpress/2008/12/aspnet-mvc-plugins/


什么是插件文件夹?还是只是命名空间? - Mou
1
有一个叫做互联网档案馆的东西,它有这个页面:https://web.archive.org/web/20150414200605/http://wynia.org/wordpress/2008/12/aspnet-mvc-plugins - jmcd

4
内置的WebFormsViewEngine使用VirtualPathProviders,因此如果您编写了一个VPP并注册它,您将不需要对视图引擎进行任何更改。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接