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

时间:2015-07-22 10:56:33

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

我有一些有控制器和视图的模块。它基本上是我的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 /查看/主页/ TestView.cshtml   〜/../ Module1.Web /浏览/首页/ TestView.cshtml   /Module1.Web/Views/Home/TestView.cshtml   /../ Module1.Web /查看/主页/ TestView.cshtml

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

但在这里我也没有任何成功。

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

有什么建议吗?

3 个答案:

答案 0 :(得分:8)

控制器将自动加载。要加载视图,您需要EmbeddedFileProviderCompositeFileProvider,这两者都是新视图,因此您需要从aspnetvnext Feed中获取视图。

在启动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

答案 1 :(得分:2)

我认为观看次数必须存在于主要网络应用4018

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

至少这是我希望采取的方法,以便其他人可以稍后阅读和/或修改我的观点。

我认为另一个选择是预先编译视图,使它们不像磁盘上那样存在于.cshtml文件中,但这会让其他人更难以自定义视图。

答案 2 :(得分:2)

我使用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:我没有在已发布的应用程序上对此进行测试。但如果出现一些路径问题,很容易解决它;)