ASP MVC Core RC1将控制器,视图和模型放在运行时加载的其他程序集中

时间:2016-03-30 10:53:44

标签: c# asp.net-core asp.net-core-mvc

我们目前正在开发一个动态系统,需要在运行时加载一些扩展。

扩展构建在与MVC应用程序相同的体系结构上,即MVC应用程序,即控制器文件夹,其中包含以Controller结尾的类,位于/ View / ControllerName中的关联视图和ViewComponents以及相关模型。

无法将此项目添加为项目的引用,因此我创建了一个在运行时加载它们的中间件:

foreach (var item in extensions)
{
   Assembly.LoadFrom($@"extensions\{item.Name}.dll");
}

到目前为止,它们在运行时加载。但是,当我尝试访问在扩展程序控制器之一中创建的路由时,WebSite会给我404响应。

我尝试添加扩展程序作为参考,但效果很好,所以这不是我的扩展程序中的问题。

如何设法将我的dll控制器注册到MVC主站点?

这不是ASP MVC 4,这是ASP Core,因此这个答案似乎无效:asp.net mvc put controllers into a separate project

尽管依赖注入可能是一种解决方案,但我找不到任何解决方案来为自己制作扩展注册服务(对于扩展创建者而言,它很复杂)。

扩展的路由选择是控制器端:

[Route("[controller]/[action]")]
public class LotteryController : Controller { ... }

在我的Startup.cs上,我实际上保留了默认路由:

 app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });

事实是,我希望我的扩展程序启用路由:http://localhost/Lottery/Index

它给了我一个空白页面。出于测试目的,我当前的Index操作是

 // GET Index
 public IActionResult Index()
{
   return Content("From extension");
   //return View();
}

这是我的扩展项目层次结构

enter image description here

2 个答案:

答案 0 :(得分:7)

MVC将自动查找在启动时从Controller继承并包含它们的控制器。这将适用于外部程序集,但很可能只适用于静态链接的程序集。

如果您正在动态加载它们,您可能想要尝试延迟MVC的启动或单独注册程序集。

此代码段显示如何搜索其他程序集以获取控制器。可以找到解释这一点的完整文章here。加载程序集后,您可以使用它来强制MVC搜索控制器。

services.AddMvc().AddControllersAsServices(new[]
{ 
    typeof(MyController).Assembly,
    typeof(ExternalPocoController).Assembly 
}); 

这将搜索那些程序集的控制器。唯一需要注意的是可能无法找到相关的视图。老实说我不确定,因为我只使用过WebAPI控制器。 修改: This看起来可能是让视图正常工作的方法

作为旁注,我可能建议使用路径装饰器或通过旧方式映射路线。使用两者似乎是一个麻烦的方法。

答案 1 :(得分:1)

加载程序集时,需要手动为操作添加ActionDescriptor实例。实际上MVC6使用'复合root'并创建不可变路由表。您可以实现自定义IActionDescriptorCollectionProvider并替换DI中的默认值:

services.Replace(ServiceDescriptor.Describe(typeof(IActionDescriptorCollectionProvider), typeof(CustomActionDescriptorCollectionProvider), ServiceLifetime.Singleton));

并且在财产的获取中:

public ActionDescriptorCollection ActionDescriptors

返回默认值(在启动时构建)和您自己的ActionDescriptor。 在我的解决方案中,我创建了中间存储,当我加载动态汇编时,我将自己的ActionDescriptor放入其中,并且在IActionDescriptorCollectionProvider中我只是检查这个商店