Продолжаем нашу рубрику на тему ASP.NET Core публикацией от Дмитрия Сикорского ( ДмитрийСикорский ) — руководитель компании «Убраянцы» из Украины.Теги: #.В своей следующей статье Дмитрий рассказывает о своем опыте нестандартной работы с представлениями в ASP.NET Core. Предыдущие статьи рубрики всегда можно прочитать по ссылке.
#aspnetcolumn — Владимир Юнев В последнее время я много работал над своей модульной платформой для ASP.NET 5 (теперь ASP.NET Core 1.0).
В рамках этого проекта мне приходилось решать различные задачи, и одна из них — работа с представлениями, которые находятся либо просто в нестандартных местах, либо вообще вне основной сборки веб-приложения.
В этой статье я попытаюсь рассказать вам, какие у вас есть варианты, если вам нужно что-то подобное.
Представления в нестандартных местах основной сборки веб-приложения.
Если по какой-то причине ваши представления оказались за пределами назначенной им папки «Представления» (но все равно остались внутри основного проекта приложения), вам необходимо будет сообщить об этом Razor. Если раньше для этого приходилось писать класс, производный от RazorViewEngine, то теперь это стало немного проще.
Для начала реализуем интерфейс IViewLocationExpander (напомню, что «{1}» в строковой константе будет заменено на имя контроллера, а «{0}» на имя действия):
Совет! Вы можете попробовать сами или загрузив исходный код с GitHub. https://github.com/DmitrySikorsky/AspNet5Views .
Затем «регистрируем» экземпляр полученного класса в методе ConfigurationServices:public class CustomViewLocationExpander : IViewLocationExpander { public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations) { List<string> expandedViewLocations = new List<string>(); expandedViewLocations.AddRange(viewLocations); expandedViewLocations.Add("/Views/SomeExtraFolder/{1}/{0}.
cshtml"); return expandedViewLocations; } public void PopulateValues(ViewLocationExpanderContext context) { } }
services.Configure<RazorViewEngineOptions>(options => { options.ViewLocationExpanders.Add(new CustomViewLocationExpander()); } );
Вот и все, теперь Razor примет к сведению наш новый макет представления.
Представления ресурсов в других сборках
На самом деле, я не знаю о преимуществах (но знаю о недостатках!) этого подхода перед следующим, но все же считаю необходимым поговорить об этом.Для того, чтобы представления помещались в сборку в качестве ресурсов, нужно добавить в project.json соответствующего проекта следующую строку (на самом деле, таким образом в ресурсы превращаются не только представления): "resource": "Просмотры/**" Чтобы такие представления впоследствии обнаруживались Razor, необходимо реализовать интерфейс IFileProvider и назначить экземпляр результирующего класса соответствующему свойству в методе ConfigurationServices в основном проекте:
services.Configure<RazorViewEngineOptions>(options => { options.FileProvider = this.GetFileProvider(this.applicationBasePath); } );
Метод GetFileProvider создает экземпляр нашего класса CompositeFileProvider, который по сути просто объединяет несколько разных поставщиков (в нашем случае — физические файлы в основной папке проекта и ресурсы из указанных сборок).Основным недостатком этого подхода является то, что мы не можем использовать типы, определенные в сборках, на которые нет явных ссылок в основном проекте, для типизации представлений.
Например, вы не можете использовать типы, определенные в проекте, в котором находятся сами представления.
Это происходит потому, что представления ресурсов компилируются во время выполнения и, соответственно, их типы моделей не могут быть найдены.
Это не проблема, если есть возможность явно добавлять зависимости, но если вам нужно загружать сборки динамически, во время выполнения, то этого сделать нельзя.
Следующий подход решает эту проблему.
(На самом деле, насколько я понимаю, это еще можно решить.
Я обсуждал этот вопрос здесь: https://github.com/aspnet/Mvc/issues/3413 , но дальше этого обсуждения дело еще не пошло.
)
Предварительно скомпилированные представления в других сборках
Пожалуй, если вам нужно разместить представления в разных сборках вашего приложения (например, чтобы разделить его на независимые части и упростить обслуживание и совместную работу), то это лучший вариант. Как и в предыдущем случае, при использовании предварительно скомпилированных представлений не нужно копировать их на сервер при публикации, что существенно ускоряет процесс (вместо множества cshtml-файлов копируется только один dll-файл).Но, в отличие от представлений в виде ресурсов, такие представления, как следует из названия, компилируются на этапе сборки проекта, а не во время выполнения, что, во-первых, позволяет заранее выявить в них все ошибки, а во-вторых, заметно экономит время при запуске приложения при доступе к определенным страницам.
Чтобы заставить компилятор скомпилировать представления, просто создайте класс RazorPreCompilation в соответствующем проекте, унаследуйте его от RazorPreCompileModule, переопределите его метод EnablePreCompilation, чтобы он возвращал true, и, наконец, поместите его в папку \Compiler\PreProcess:
public class RazorPreCompilation : RazorPreCompileModule { protected override bool EnablePreCompilation(BeforeCompileContext context) => true; }
В основном проекте приложения, чтобы сообщить Razor, что он должен использовать предварительно скомпилированные представления из других сборок, вы просто передаете набор этих сборок соответствующему методу:services.AddMvc() .
AddPrecompiledRazorViews( new Assembly[] { Assembly.Load(new AssemblyName("AspNet5Views.PrecompiledViews")) } );
Этого достаточно, чтобы все заработало.Как я писал выше, благодаря тому, что представления компилируются на этапе сборки всего проекта, мы имеем возможность типизировать их типами, на которые нет ссылок в основном проекте приложения.
выводы
В общем, все довольно просто.Два последних подхода имеют существенный недостаток, а именно необходимость перезапуска всего приложения для изменения, например, даже самой незначительной детали в макете.
Но, с другой стороны, это все равно гораздо удобнее, чем копировать представления из всех частей приложения в основной проект, если вам действительно нужно разделить приложение на части.
Я подготовил небольшой тестовый проект, чтобы вы могли сами попробовать все описанное в этой статье: https://github.com/DmitrySikorsky/AspNet5Views .
Авторам
Друзья, если вы заинтересованы поддержать рубрику собственным материалом, пишите мне на почту [email protected] чтобы обсудить все детали.Мы ищем авторов, которые смогут интересно рассказать об ASP.NET и других темах.
об авторе
Сикорский Дмитрий Александрович Компания «Убраянцы» (г.http://ubrainians.com/ ) Владелец, менеджер ДмитрийСикорский
NET #asp.net core #ASP.NET #ASP #ASP #Views #Views #razor ##aspnetcolumn ##aspnetcolumn
-
Онлайн-Помощь Php Для Dreamweaver
19 Oct, 24 -
История О Том, Как Я Не Нашел Инженера
19 Oct, 24 -
#18 Мосдроид Аргон На Ламоде — Анонс
19 Oct, 24 -
Майнинг Токенов Waves И Комиссии
19 Oct, 24 -
Астрономы Нашли Обитаемую Планету
19 Oct, 24