Как включить контроллеры и представления из внешнего проекта в MVC6?
У меня есть несколько модулей, которые имеют контроллеры и представления. Это в основном расширение для моего веб-приложения. Каждый модуль находится в библиотеке классов.
Я хочу загрузить эти сборки из моего веб-приложения. Но здесь мне не везет.
Моя структура файлов решений выглядит следующим образом:
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)
{
}
}
Я перепробовал все пути, которые приходили мне в голову, но безуспешно : (
I получить:
Исключение InvalidOperationException: представление 'TestView' не найдено. Были проведены поиски в следующих местах:
~ / Module1.Web / Views / Home / TestView.cshtml
~/../ Module1.Web / Views / Home / TestView.cshtml
/ Module1.Web / Views / Home / TestView.cshtml
/../ Module1.Web / Views / Home / TestView.cshtml
Поэтому я подумал, что, возможно, ifileprovider по умолчанию не смотрит за пределы корневого пути веб-приложения, и решил попробовать реализовать свой собственный IFileProvider.
Но здесь у меня тоже не было никакого успеха.
Может быть, есть функция для достижения этого, вызывая некоторые ASP.NET методы, но я этого не знаю.
Есть предположения?
3 ответов:
Контроллеры будут загружаться автоматически. Чтобы загрузить представления, вам понадобятся
EmbeddedFileProviderиCompositeFileProvider, оба из которых являются новыми, поэтому вам нужно будет получить их из ленты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
Я думаю, что представления должны жить в главном веб-приложении , Если вы не хотите использовать какие-то нестандартные сторонние решения
Насколько я понимаю, в beta7 мы сможем упаковывать представления и другие файлы содержимого в библиотеку классов nuget, которая создается при построении библиотеки классов с помощью VS 2015. Но я понимаю, что когда основное веб-приложение добавляет зависимость от такого nuget, файлы содержимого будут добавлены в основное веб-приложение, т. е. мои представления будут добавлены ниже Views/MyModule или что-то в этом роде, чтобы их можно было использовать из основного веб-приложения.
По крайней мере, это тот подход, который я ожидаю принять, чтобы мои взгляды могли быть прочитаны и/или изменены позже другими.
Я думаю, что другой вариант-предварительно скомпилировать представления таким образом, чтобы они не существовали на диске как.файлы cshtml, но это сделает его более трудным для других, чтобы настроить представления.
Я достиг этого с помощью
IViewLocationExpanderиPhysicalFileProviderЯ использовал
IFileProviderдвижка razor, чтобы задать корневой путь к папке 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методе:PS: Я не тестировал это на опубликованном приложении. Но это будет легко исправить, если возникнут некоторые проблемы пути;)services.Configure<RazorViewEngineOptions>(options => { options.FileProvider = new PhysicalFileProvider(HostingEnvironment.WebRootPath + "..\\..\\"); options.ViewLocationExpanders.Add(new MultiAssemblyViewLocationExpander ()); });
Comments