Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to include controllers and views from an external project into MVC6?

I have some modules which has controllers and views. It is basically an extension for my web application. Each module is in a class library.

I want to load these assemblies from my web application. But I'm without luck here.


My solutions file structure is like:

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...

These are what I tried:


I tried to implement my own 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)
    {

    }
}

I tried all kind of paths that came to my mind but no luck :(

I get:

InvalidOperationException: The view 'TestView' was not found. The following locations were searched:

~/Module1.Web/Views/Home/TestView.cshtml ~/../Module1.Web/Views/Home/TestView.cshtml /Module1.Web/Views/Home/TestView.cshtml /../Module1.Web/Views/Home/TestView.cshtml


So I thought maybe the default IFileProvider doesn't look outside the WebApp's root path and decided to try implementing my own IFileProvider.

But here I didn't have any success neither.


Maybe there is a feature to achieve this by calling some ASP.NET methods but I don't know it.

Any suggests?

like image 982
Yves Avatar asked Jul 22 '15 10:07

Yves


1 Answers

Controllers will get loaded automatically. To load views, you will need EmbeddedFileProvider and CompositeFileProvider, both of which are new, so you'll need to get them from the aspnetvnext feed.

Reference them in your startup MVC6 project's project.json:

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

Update your service registration in 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
        );
    });

In project.json of your external assembly, add this:

  "resource": "Views/**"

Here's a sample implementation that you can clone and run to see it in action: https://github.com/johnnyoshika/mvc6-view-components

like image 111
Johnny Oshika Avatar answered Nov 14 '22 23:11

Johnny Oshika