如何将外部项目中的控制器和视图包含到MVC6中

本文关键字:视图 包含 MVC6 控制器 外部 项目 | 更新日期: 2023-09-27 18:04:04

我有一些模块有控制器和视图。它基本上是我的web应用程序的扩展。每个模块都在一个类库中。

我想从我的web应用程序加载这些程序集。但是我运气不好。


我的解决方案文件结构如下:

src
|
|-- Web.Common  (Class Library Project)
|   |- Files like: filters, my own controller etc...
|    
|-- WebApplication (ASP.NET5 WebSite)
|   |- wwwroot
|   |- Controllers
|   |- Views
|   |- etc...
|
|-- Module 1 (Class Library Project)
|   |- Controllers
|   |- Views
|
|-- Module 2 etc...

这些是我尝试过的:


我尝试实现我自己的IViewLocationExpander

public class CustomViewLocationExpander : IViewLocationExpander
{
    public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
    {
        yield return "/../Module1.Web/Views/Home/TestView.cshtml";
        yield return "../Module1.Web/Views/Home/TestView.cshtml";
        yield return "/Module1.Web/Views/Home/TestView.cshtml";
        yield return "~/../Module1.Web/Views/Home/TestView.cshtml";
    }
    public void PopulateValues(ViewLocationExpanderContext context)
    {
    }
}

我尝试了所有想到的方法,但都没有成功:(

:

InvalidOperationException:未找到视图"TestView"。以下位置被搜索:

~/Module1.Web/视图/Home/TestView.cshtml~/. ./Module1.Web/视图/Home/TestView.cshtml/Module1.Web/视图/Home/TestView.cshtml/. ./Module1.Web/视图/Home/TestView.cshtml


所以我想也许默认的IFileProvider不会在WebApp的根路径外看,并决定尝试实现我自己的IFileProvider。

但是在这里我也没有成功。


也许有一个特性可以通过调用一些ASP来实现这一点。. NET方法,但我不知道。

显示吗?

如何将外部项目中的控制器和视图包含到MVC6中

控制器将自动加载。要加载视图,您将需要EmbeddedFileProviderCompositeFileProvider,它们都是新的,因此您需要从aspnetvnext提要获取它们。

在启动MVC6项目的project.json中引用它们:

"Microsoft.AspNet.FileProviders.Composite": "1.0.0-*",
"Microsoft.AspNet.FileProviders.Embedded": "1.0.0-*",

更新Startup.cs中的服务注册:

    services.Configure<RazorViewEngineOptions>(options =>
    {
        options.FileProvider = new CompositeFileProvider(
            new EmbeddedFileProvider(
                typeof(BooksController).GetTypeInfo().Assembly,
                "BookStore.Portal" // your external assembly's base namespace
            ),
            options.FileProvider
        );
    });

在外部程序集的project.json中,添加以下内容:

  "resource": "Views/**"

下面是一个示例实现,您可以克隆并运行以查看其实际效果:https://github.com/johnnyoshika/mvc6-view-components

我认为视图必须存在于主web应用程序中,除非你想使用一些非标准的第三方解决方案

我的理解是,在beta7中,我们将能够将视图和其他内容文件打包到类库nuget中,该nuget是在VS 2015中构建类库时创建的。但我的理解是,当主web应用程序添加依赖于这样的nuget时,内容文件将被添加到主web应用程序,即我的视图将被添加到views/MyModule或类似的东西下,以便它们可以从主web应用程序中使用。

至少这是我期望采取的方法,这样我的视图以后可以被其他人读取和/或修改。

我认为另一种选择是预编译视图,这样它们就不会以。cshtml文件的形式存在于磁盘上,但这会使其他人更难以自定义视图。

我通过使用IViewLocationExpanderPhysicalFileProvider实现了这一点

我使用剃刀引擎的IFileProvider设置根路径到src文件夹。通过附加程序集名称,我得到了项目根路径的路径。

public class MultiAssemblyViewLocationExpander : IViewLocationExpander
{
    public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
    {
        var actionContext = (ResultExecutingContext)context.ActionContext;
        var assembly = actionContext.Controller.GetType().Assembly;
        var assemblyName = assembly.GetName().Name;
        foreach (var viewLocation in viewLocations)
            yield return "/" + assemblyName + viewLocation;
    }
    public void PopulateValues(ViewLocationExpanderContext context)
    {
    }
}

ConfigureServices方法中:

services.Configure<RazorViewEngineOptions>(options =>
{
    options.FileProvider = new PhysicalFileProvider(HostingEnvironment.WebRootPath + "..''..''");
    options.ViewLocationExpanders.Add(new MultiAssemblyViewLocationExpander ());
});

PS:我没有在已发布的应用程序上进行测试。但是如果出现一些路径问题就很容易修复了;)