我在我的 Asp.Net MVC 4 项目中无法解决 404 响应。它内置于针对 4.5 的 VS2012 中。
我已将预编译的视图和控制器内置到独立的 DLL 中。我能够动态加载 DLL 并从我的核心项目中检查它们,甚至调用它们的方法;但是,似乎 MVC 框架不知道控制器。我在这里很近,但缺少一些东西。
控制器和视图的背景
控制器构建在独立的 MVC 项目中,并继承自Controller
. 那里没有什么太有趣的事情发生。视图使用 RazorGenerator 并成为项目中的类。
项目的输出是一个正确包含控制器和视图的 DLL。
IPlugin
DLL在库中的一个单独的类(不是控制器的一部分)中实现了一个特定的接口,我们称之为它。
加载 DLL
在 Visual Studio 中以管理员身份运行,我编译了托管在 IIS 下的应用程序。构建项目后,我将插件 DLL 放入我的“插件”目录。没有调试(这在以后变得很重要),我打开 IE 并导航到该站点。 请注意,此时应用程序已构建,但从未运行,因此将触发启动事件。如果我回收应用程序池,这里的一切仍然是一致的。
我有一个Startup
有两个方法的类,PreStart
并分别使用和PostStart
调用这些方法。WebActivator.PreApplicationStartMethod
WebActivator.PostApplicationStartMethod
PreStart
是我执行以下操作的地方:
- 获取我的“插件”目录中所有插件 DLL 的列表
- 将所有插件复制到
AppDomain.CurrentDomain.DynamicDirectory
- 加载类型...如果它包含一个
IPlugin
I 然后- 将程序集添加到 BuildManager
- 在实现IPlugin的类上调用一些方法
在“PostStart”中,我执行了这段代码(基于来自 RazorGenerator.Mvc 的代码):
foreach (var assembly in Modules.Select(m=>m.Value))
{
var engine = new PrecompiledMvcEngine(assembly)
{
UsePhysicalViewsIfNewer = HttpContext.Current.Request.IsLocal
};
ViewEngines.Engines.Insert(0, engine);
VirtualPathFactoryManager.RegisterVirtualPathFactory(engine);
}
Modules
在这种情况下是一个键/值对,其中的值是加载的程序集。这段代码的目的是通过为每个知道如何解析视图的程序集添加一个视图引擎来确保 MVC 知道视图(这是 RazorGenerator 的一部分)。
我怎么知道我很接近(但显然缺少雪茄)
IPlugin
定义了一个名为RegisterRoutes
where 的方法,你猜对了,为实现接口的人注册路由。我调用此方法PreStart
并添加路由 - 我已验证这些存在于我的路由表中。例如,在我的插件中定义的路由上,通过在 期间动态调用方法创建,PreStart
在检查我的路由时,我看到这样的东西作为 DataToken:
Namespaces = Plugin.Name.Controllers
因此,路由已注册,程序集已加载,我已验证 DLL 已正确复制到 AppDomain 的 DynamicDirectory。我能够调用在运行时动态加载的类的成员。但是当我导航到与路由匹配的 URL 时,我得到一个 404。这不是“找不到视图”的 YSOD,它更像是根本找不到控制器。
这是让我感到困惑的部分:如果此时不做任何事情,我返回 Visual Studio 并按 F5 ...一切正常。
就像 Visual Studio 以某种我无法识别的方式意识到控制器,而 MVC 框架正在接受它。
最后,一个问题
我错过了什么,如何让 MVC 框架了解我的控制器?
嘿,在这一点上,如果你还在读这个,谢谢。:)