2015-07-22 4 views
6

Ich habe einige Module, die Controller und Ansichten hat. Es ist im Grunde eine Erweiterung für meine Webanwendung. Jedes Modul befindet sich in einer Klassenbibliothek.Wie können Controller und Ansichten von einem externen Projekt in MVC6 integriert werden?

Ich möchte diese Baugruppen aus meiner Webanwendung laden. Aber ich habe kein Glück hier.


Meine Lösungen Dateistruktur ist wie:

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

Diese sind, was ich versucht:


Ich habe versucht, mein eigenes 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) 
    { 

    } 
} 

Ich habe versucht, zu implementieren alle Arten von pa ths, die

ich mir in den Sinn, aber kein Glück :(kam:

InvalidOperationException: Die Ansicht ‚Testview‘ wurde nicht gefunden. Folgende Standorte wurden gesucht:

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


Also dachte ich, vielleicht die Standard IFileProvider nicht außerhalb des root-Pfad der WebApp sieht und beschlossen, zu versuchen, meine Umsetzung eigener IFileProvider.

Aber hier hatte ich auch keinen Erfolg.


Vielleicht gibt es eine Funktion, um dies zu erreichen, indem Sie einige ASP.NET-Methoden aufrufen, aber ich weiß es nicht.

Irgendwelche Vorschläge?

Antwort

8

Controller werden automatisch geladen. Um Ansichten zu laden, benötigen Sie EmbeddedFileProvider und CompositeFileProvider, die beide neu sind. Sie müssen sie daher vom aspnetvnext Feed beziehen.

Referenz sie in Ihrem Start MVC6 Projekt project.json:

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

Aktualisieren Sie Ihre Service-Registrierung 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 Ihrer externen Montage, fügen Sie diese:

"resource": "Views/**" 

Hier ' s Eine Beispielimplementierung, die Sie klonen und ausführen können, um sie in Aktion zu sehen: https://github.com/johnnyoshika/mvc6-view-components

+0

Ich hätte gerne mehrere Baugruppen, die Sichten und Steuerungslogik in eine zentrale Web-App einbringen. Irgendwelche Gedanken darüber, wie man ein Array von FileProvidern anvisiert? – Matthew

+1

@Matthew, 'CompositeFileProvider' akzeptiert eine Sammlung von' FileProviders', so dass Sie beliebig viele registrieren können. 'neuer CompositeFileProvider (EmbeddedFileProvider, EmbeddedFileProvider, EmbeddedFileProvider, etc)'. –

+0

@Matthew, wenn Sie sich die Beispielimplementierung ansehen, mit der ich oben verlinkt habe, sehen Sie ein Beispiel, in dem ich Ansichten von mehreren Assemblys einlese. Hier ist der entsprechende Code: https://github.com/johnnyoshika/mvc6-view-components/blob/master/Web/Startup.cs#L27 –

2

Ich denke, die Ansichten in dem Haupt-Web-App ist leben müssen unless you want to use some non-standard 3rd party solutions

Mein Verständnis in beta7, dass wir in der Lage sein werden, Ansichten und andere Content-Dateien in einer Klassenbibliothek nuget zu verpacken, die erstellt wird, wenn wir die Klasse bauen Bibliothek mit VS 2015. Aber wenn die Haupt-Web-App eine Abhängigkeit von einem solchen Nuget hinzufügt, werden die Inhaltsdateien zur Hauptweb-App hinzugefügt, dh meine Ansichten werden unterhalb von Views/MyModule oder so ähnlich hinzugefügt Sie können von der Haupt-Webanwendung aus verwendet werden.

Zumindest ist dies der Ansatz, den ich erwarte, damit meine Ansichten später von anderen gelesen und/oder geändert werden können.

Ich denke, die andere Option besteht darin, die Ansichten vorkompilieren, so dass sie nicht als .cshtml-Dateien auf der Festplatte vorhanden sind, aber dies würde es anderen schwieriger machen, die Ansichten anzupassen.

+0

Wir möchten unsere Module extern liefern. Sie sollten durch Kopieren oder Löschen des Ordners hinzugefügt oder entfernt werden können. Deshalb wollen wir sie nicht zum Hauptprojekt machen. Wir wollen sie auch nicht zu einer selbstlaufenden Webanwendung machen. – Yves

+0

Ich habe vorübergehend eine Lösung gefunden (auch hier gepostet) und benutze sie im Moment. Ich werde auf diese Beta7-Funktion warten, um es zu versuchen. – Yves

2

ich erreicht dies durch IViewLocationExpander und PhysicalFileProvider

ich mit IFileProvider auf des Messers Motor den Wurzelpfad zum src Ordner festlegen verwendet. Durch Anhängen des Assemblynamens erhalte ich den Pfad des Projektstammpfads.

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) 
    { 

    } 
} 

Und in ConfigureServices Methode:

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

PS: ich dies nicht auf eine veröffentlichte Anwendung testen. Aber es wird einfach sein, es zu beheben, wenn einige Pfadprobleme auftreten;)

Verwandte Themen