Тег-хэлперы (Tag Helpers) – новая функция MVC, которую удобно использовать для генерации HTML кода. Они выглядят как обычные HTML элементы и атрибуты, но обрабатываются движком Razor на стороне сервера. Тег-хэлперы во многом представляют собой альтернативный синтаксис для HTML Helpers, но также они позволяют сделать то, что было трудно или невозможно сделать с помощью HTML Helpers. У каждого тег-хэлпера свое поведение и возможности. Эта статья рассмотрит базовые тег-хэлперы, существующие в MVC 6 (ASP .NET Core 1.0, как стало известно совсем недавно).
Если вы создаете новый MVC 6 проект с помощью Visual Studio, то встроенные тег-хэлперы будут доступны по умолчанию. Можно добавить тег-хэлперы из любой сборки / пространства имен, используя директиву @addTagHelper в cshtml файлах.
Чтобы добавить тег-хэлперы глобально для всего проекта, добавьте директиву @addTagHelper в файл Views/_ViewImports.cshtml.
Как видно из их названий, эти тег-хэлперы созданы для упрощения добавления тегов link и script в создаваемую HTML разметку. Например, с их помощью можно упростить добавление ссылок на большое число файлов в девелопмент среде, использование CDN с откатом на локальные файлы и инвалидацию кеша.
Рассмотрим пример, в котором мы хотим добавить ссылки на все js файлы в определенной папке (рисунок 1).
Мы можем это легко сделать с помощью тег-хэлпера Script, добавив все файлы по шаблону:
В результате будет сгенерирована следующая HTML разметка:
В данном примере мы использовали шаблон /app/**/*.js, потому что нам нужно было включить еще и js файлы из подпапок. Если же мы хотим добавить ссылки на все js файлы из одной папки, то используем шаблон /app/*.js.
Наряду с атрибутом asp-src-include существует и атрибут asp-src-exclude. Например, в предыдущем примере мы можем сделать так, чтобы ссылки на js файлы в подпапке services не были добавлены:
Тег-хэлпер Link работает точно так же, только с атрибутами asp-href-include и asp-href-exclude.
Теперь рассмотрим атрибуты этих тег-хэлперов, которые помогут подключать CDN. Преимущества использования CDN для хостинга файлов таких популярных фреймворков как jQuery и Bootstrap очевидны: уменьшается нагрузка на наши сервера и потенциально увеличивается производительность у клиента (например, актуальная версия файла уже может быть в кеше браузера у клиента). Среди минусов – нужно предусмотреть возможность того, что CDN не отвечает и нам нужно отдавать файлы со своего сервера. С помощью тег-хэлперов это сделать проще:
Атрибуты asp-fallback-test позволяют указать свойства или объекты, которые нужно проверить для того, чтобы узнать, был ли загружен файл или нет. Если нет, то файл будет загружен с использованием пути, заданном в атрибуте asp-fallback-href. Сгенерированная HTML разметка:
Cache busting (инвалидация кеша) – механизм, добавляющий идентификатор версии файла (на основе его содержимого) к имени файла для css и js файлов. В этом случае можно указать браузеру, что эти файлы можно кешировать на неопределенно долгое время, в случае их изменения имя у них также изменится. Для того чтобы включить этот механизм, достаточно добавить атрибут asp-append-version:
Сгенерированный HTML:
Тег-хэлпер Environment используется (обычно вместе с тег-хэлперами Link и Script) для генерирования различной HTML разметки в зависимости от среды: девелопмент vs тест vs продакшен. Этот тег-хэлпер используется следующим образом: оберните в этот тег часть HTML кода и укажите среду или среды, для которых эта часть разметки должна быть включена в выходной файл. В следующем примере в девелопмент среде мы подключаем все css файлы по отдельности, а в средах Staging и Production используем скомбинированную минифицированную версию.
В девелопмент среде будет сгенерирован следующий HTML код:
В средах Staging и Production будет добавлена ссылка на минифицированную версию:
Сам тег environment не посылается клиенту. Его значение задается переменной Hosting:Environment. В ASP.NET Core 1.0 (MVC 6) Hosting:Environment используется для тех же целей, для каких раньше использовалась Debug / Release конфигурация. Обычно Hosting:Environment принимает значения: Development, Staging и Production. Значением по умолчанию при запуске сайта из Visual Studio является Development. В этом можно убедиться, открыв свойства MVC проекта в Visual Studio (рисунок 2).
Для того, чтобы протестировать среды Staging или Production, нужно создать новый профиль отладки (Debug Profile) и установить требуемое значение Hosting:Environment. Например, рассмотрим, как создать профиль Production (рисунок 3).
Теперь в выпадающем списке Run в Visual Studio можно выбрать профиль “IIS Express – Prod” (рисунок 4).
Именно в этом разделе тег-хэлперы делают свою работу лучше всего, увеличивая читаемость и простоту cshtml представлений. В качестве примера рассмотрим простую логин форму со следующей моделью:
Теперь посмотрим, как можно сгенерировать поле ввода для свойства UserName.
Когда мы используем HTML хэлпер, то вызываем обычный C# метод, который возвращает некоторую HTML разметку. С тег-хэлперами мы имеем дело сразу с обычной HTML разметкой, в которой встречаются MVC специфичные атрибуты. В результате обоих подходов на выходе мы получим один и тот же сгенерированный HTML код:
Почему подход с тег-хэлперами лучше? Код с ними становится читаемее и проще. Например, мы хотим добавить к полю ввода класс:
В данном случае код с использованием тег-хэлперов однозначно выигрывает и в красоте, и в простоте.
Теперь приведем код всей формы логина в двух вариантах.
Как мы видим, версия с тег-хэлперами выглядит проще и читаемее. Особенно мне нравится отсутствие выражения using для генерации формы, мне всегда это казалось каким-то хаком. Еще стоит отметить, что нам теперь не нужно явно добавлять AntiForgeryToken на форму. Тег-хэлпер form делает это автоматически, если не отключить это поведение атрибутом asp-anti-forgery=”false”.
Конечно, Visual Studio подсвечивает атрибуты тег-хэлперы, чтобы их легко можно было отличить от стандартных HTML атрибутов (рисунок 5):
Внутри атрибутов asp-for работает IntelliSense, подсказывающий имена свойств модели (рисунок 6).
Теперь рассмотрим атрибуты тег-хэлпера form. Например для того, чтобы связать форму с определенным действием определенного контроллера, используются атрибуты asp-controller и asp-action:
В результате будет сгенерирована следующая HTML разметка:
Как мы видим, по умолчанию добавляется AntiForgeryKey, а методу формы присваивается значение POST. Это поведение можно изменить, добавив в разметку переопределение атрибута method. Все HTML атрибуты, добавленные в разметку, попадут в сгенерированный код. Однако стоит учесть, что нельзя одновременно задать атрибут action и один из атрибутов asp-controller / asp-action, в этом случае будет выброшено исключение: «Cannot override the ‘action’ attribute for . A with a specified ‘action’ must not have attributes starting with ‘asp-route-‘ or an ‘asp-action’ or ‘asp-controller’ attribute.»
Иногда действию контроллера нужно передать дополнительные параметры. Это можно сделать с помощью атрибутов, начинающихся с asp-route-. Например, в действие Login часто передается параметр ReturnUrl, вот как это можно сделать с использованием тег-хэлперов:
В итоге будет сгенерирован такой HTML код:
Используя такой синтаксис, можно указывать столько параметров, сколько необходимо.
Еще тег-хэлпер form поддерживает возможность указать именованный маршрут вместо пары контроллер / действие. Предположим, что мы определили маршрут с именем login в MVC коде:
Тогда мы можем указать этот маршрут для формы, используя атрибут asp-route:
Что в свою очередь сгенерирует точно такую же HTML разметку, как и в предыдущем случае:
Тег-хэлпер input является альтернативой Html.EditorFor. В следующем примере будем использовать такой простой класс модели представления:
Поле ввода для Email можно создать с помощью asp-for атрибута:
В результате чего получим следующую HTML разметку:
Тег-хэлпер добавляет атрибуты id и name, значение которых задается именем свойства, указанным в asp-for. Тип сгенерированного input был установлен в text потому, что тип свойства Email string. Если бы тип свойства был bool, то тег-хэлпер сгенерировал бы input с типом checkbox. Ниже представлена таблица соответствия .NET типов и HTML input типов.
Тег-хэлпер input принимает во внимание не только тип свойства, но и валидационные атрибуты. Например, добавим [Required] к свойству Email:
В этом случае в сгенерированной HTML разметке будет атрибут data-val-required, который используется jQuery Validation.
Если добавить атрибут [EmailAddress] к свойству модели, то будет сгенерирован input с типом email и атрибутом data-val-email. Ниже приведена таблица с указанием .NET атрибутов, которые соответствуют различным типам HTML input.
Также можно использовать дочерние объекты в моделях представления. Чуть усложним нашу модель.
В представлении мы можем создать поле ввода для Address.AddressLine1:
В результате получим следующий HTML код:
Конечно, все атрибуты, которые будут в cshtml файле применены тег-хэлперу input, будут добавлены в сгенерированную HTML разметку.
Еще одной возможностью, предоставляемой тег-хэлпером input, является использование обычной <a href=” msdn.microsoft.com/en-us/library/dwhawy9k.aspx”>строки форматирования, широко использующейся в .NET. Для этого используется атрибут asp-format, например:
В этом случае число будет показано с 4 знаками после запятой, например, 1.2000. Никаких дополнительных атрибутов не добавляется.
Как мы уже говорили, Visual Studio предоставляет IntelliSense для тег-хэлпера input, подсвечивает ошибки, если есть ошибка в имени свойства. Исключение в таком случае будет выброшено во время компиляции, но по умолчанию Razor представления не прекомпилируются, поэтому эта ошибка будет видна только при первом обращении к странице.
Тег-хэлпер textarea во многом похож на ранее рассмотренный input и является альтернативой Html.TextAreaFor. Он также использует атрибут asp-for. Рассмотрим следующую модель представления:
Мы используем тег-хэлпер textarea следующим образом:
Что сгенерирует следующую HTML разметку:
В сгенерированном элементе textarea определены name, id, добавлены валидационные атрибуты.
Мы увидели, что добавлять валидационные атрибуты несложно, теперь обсудим, где показывать валидационные сообщения. Раньше для этого использовался метод Html.ValidationMessageFor, теперь – атрибут asp-validation-for, применяемый к элементу span.
Это сгенерирует следующую HTML разметку, в случае если поле Email было сделано обязательным, но не было заполнено:
Тег-хэлпер нашел валидационное сообщение для свойства Email и добавил его в содержимое элемента span. Также он добавил data-valmsg-* атрибуты, чтобы клиентская валидация jQuery для поля Email работала с этим элементом. Обычно тег-хэлпер валидации будет помещен на форму рядом с полем, которое он валидирует. Как и для всех остальных тег-хэлперов, все HTML атрибуты, которые вы к нему добавите, попадут в сгенерированную HTML разметку.
Теперь рассмотрим аналог Html.ValidationSummary(true) – тег-хэлпер Validation Summary, который агрегирует валидационные сообщения для валидационных сообщений уровня всей модели и/или уровня свойств модели. Этот тег-хэлпер представляет собой атрибут asp-validation-summary, который добавляется к элементу div. Возможные значения этого атрибута:
Этот код сгенерирует следующую разметку в случае, когда валидационных ошибок нет:
Если же у нас есть ошибки валидации:
Тег-хэлпер label является самымскучным простым тег-хэлпером, заменой Html.LabelFor. Его единственная задача – сгенерировать элемент label для поля, имя которого указано в атрибуте asp-for. Значение для содержимого этого label задается свойством Name атрибута Description. Рассмотрим такую модель представления:
Теперь используем тег-хэлпер label:
Что в результате даст нам следующую HTML разметку:
Тег-хэлпер select используется для создания выпадающих списков в HTML разметке вместо Html.DropDownListFor. Пусть у нас есть модель со свойством CountryCode, которое мы хотим заполнять с помощью выпадающего списка:
Теперь с помощью тег-хэлпера свяжем это поле с элементом select.
И получим следующий HTML код:
Конечно, этот код не несет практической ценности, потому что выпадающий список еще пуст. Есть 2 способа его заполнить. Первый (для совсем маленьких списков): все возможные варианты задать вручную в представлении:
В этом случае значение будет выбрано исходя из значения свойства в модели. Например, если CountryCode равен “CA”, будет сгенерирована следующая HTML разметка:
Второй способ задания возможных значений – динамическая загрузка из источника данных. Для этого нужен источник данных типа IEnumerable<SelectListItem> (или SelectList), пусть в нашем случае он доступен в ViewBag.Countries. Для привязки источника данных используется атрибут asp-items:
Для того, чтобы сгенерированный элемент select поддерживать возможность выбора нескольких элементов, достаточно, чтобы свойство модели имело тип IEnumerable, например:
В коде использования тег-хэлпера ничего не меняем:
Но сгенерированная HTML разметка будет другой:
Тег-хэлпер anchor служит для генерации ссылок и является заменой как Html.ActionLink, так и Url.Action, с помощью которых мы обычно писали вот так:
И в результате получали две одинаковые ссылки:
Теперь с помощью тег-хэлпера anchor и атрибутов asp-controller, asp-action ссылку можно добавить следующим образом:
Как и в случае остальных тег-хэлперов, их использование позволяет проще добавить дополнительные классы и атрибуты для этих элементов, в отличие от Html.ActionLink(«Register », «Create», “Account”, null, new { class= «css-class»} ).
Если в метод контроллера надо передать дополнительные параметры, то это можно сделать так же, как и для тег-хэлпера form: с помощью атрибутов asp-route-*, например:
Также можно указать именованный маршрут (опять точно так же, как для form):
Ранее используемый Html.ActionLink позволял указать протокол, хост и фрагмент генерируемого URL. У тег-хэлпера есть для этого свои атрибуты:
У тег-хэлпера cache нет аналога среди Html хэлперов, да и обычным HTML элементом он не является. Он позволяет закешировать свое содержимое в памяти. Перед каждой обработкой своего содержимого он проверяет, не было ли оно уже сохранено в MemoryCache. Если содержимое найдено в кеше, оно отправляется сразу в Razor движок, если нет – сначала Razor обработает его, а потом оно сохранится в кеш. По умолчанию тег-хэлпер сгенерирует уникальный ID своего содержимого. Вот так его можно использовать в представлениях:
Тег cache не будет включен в сгенерированную HTML разметку, это просто директива для движка, что на протяжении 10 минут клиенту можно посылать уже обработанную и закешированную версию представления _WhatsNew.
Если не указать время жизни закешированной версии, то по умолчанию она будет отдаваться все время жизни приложения (или до первого ресайкла пула). Тег-хэлпер cache поддерживает следующие опции задания времени жизни закешированного объекта:
По умолчанию ключ объекта в кеше генерируется уникально на основе контекста тег-хэлпера, что позволяет использовать несколько тег-хэлперов cache на одной странице без путаницы их содержимого в кеше. С помощью атрибутов vary-by можно задавать более сложные ключи, позволяющие кешировать разное содержимое тег-хэлпера cache для разных запросов. Рассмотрим возможные варианты атрибутов vary-by.
Так как все закешированное содержимое хранится в IMemoryCache, то его размер ограничен размером доступной оперативной памяти. Поэтому если процесс начинает испытывать нехватку памяти, кеш будет удалять свои элементы для освобождения памяти. С помощью атрибута priority можно указать, какие объекты следует удалять первыми, а какие оставлять в кеше. Возможные значения этого атрибута: Low, Normal, High и NeverRemove. Например, укажем, что содержимое тег-хэлпера можно считать неприоритетным:
Ограничения этого тег-хэлпера связаны с тем, что он использует MemoryCache в свое реализации. Первое ограничение связано с тем, что любой перезапуск процесса, ресайкл пула приложения и похожее действие инвалидирует весь наш кеш, в облаке такое может произойти, если сайт переедет на новую машину. Поэтому нельзя считать этот кеш надежным. Второе ограничение также связано с тем, что кеш хранится в памяти. Если пользователь в рамках сессии будет перенаправлен на разные веб-сервера, потенциально он может увидеть разное содержимое одного и того же элемента. Это связано с тем, что у каждого сервера будет своя версия кеша, реализация MemoryCache не является распределенной. В данном случае может помочь привязка пользователя к одному и тому же серверу (sticky session, server affinity).
Этот простой в использовании тег-хэлпер состоит из всего одного атрибута asp-append-version, добавляемого к тегу img. Если передать этому атрибуту значение true, то к URL изображения будет добавлена строка, зависящая от содержимого картинки (как и в случае css / js файлов), что позволит браузеру кешировать ее неопределенно долгое время.
В результате будет сгенерирована похожая HTML разметка:
Использование этого тег-хэлпера упрощает выбор политики кеширования изображений сайта: при маленьком времени кеширования нивелируется выгода от его применения, при большом – потенциально при обновлении изображения клиент в течение долгого времени продолжает использовать старую локально закешированную версию изображения.
С одной стороны плохо, что все наши представления с версией MVC <= 5 надо переписывать, но с использованием тег-хэлперов они выглядят чище, их легче использовать дизайнерам / верстальщикам, теперь они выглядят как обычный HTML с дополнительными атрибутами. Следующий раз рассмотрим создание своего тег-хэлпера, а пока качайте VS 2015 Community Edition, создавайте свой первый проект ASP.NET Core 1.0!
Документация по тег-хэлперам
Документация по последней версии ASP.NET MVC
Visual Studio 2015 Community Edition
Добавление тег-хэлперов для использования в представлении
Если вы создаете новый MVC 6 проект с помощью Visual Studio, то встроенные тег-хэлперы будут доступны по умолчанию. Можно добавить тег-хэлперы из любой сборки / пространства имен, используя директиву @addTagHelper в cshtml файлах.
@addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"
Чтобы добавить тег-хэлперы глобально для всего проекта, добавьте директиву @addTagHelper в файл Views/_ViewImports.cshtml.
Link и Script
Как видно из их названий, эти тег-хэлперы созданы для упрощения добавления тегов link и script в создаваемую HTML разметку. Например, с их помощью можно упростить добавление ссылок на большое число файлов в девелопмент среде, использование CDN с откатом на локальные файлы и инвалидацию кеша.
Рассмотрим пример, в котором мы хотим добавить ссылки на все js файлы в определенной папке (рисунок 1).
Мы можем это легко сделать с помощью тег-хэлпера Script, добавив все файлы по шаблону:
<script asp-src-include="~/app/**/*.js"></script>
В результате будет сгенерирована следующая HTML разметка:
<script src="/app/app.js"></script>
<script src="/app/controllers/controller1.js"></script>
<script src="/app/controllers/controller2.js"></script>
<script src="/app/controllers/controller3.js"></script>
<script src="/app/controllers/controller4.js"></script>
<script src="/app/services/service1.js"></script>
<script src="/app/services/service2.js"></script>
В данном примере мы использовали шаблон /app/**/*.js, потому что нам нужно было включить еще и js файлы из подпапок. Если же мы хотим добавить ссылки на все js файлы из одной папки, то используем шаблон /app/*.js.
Наряду с атрибутом asp-src-include существует и атрибут asp-src-exclude. Например, в предыдущем примере мы можем сделать так, чтобы ссылки на js файлы в подпапке services не были добавлены:
<script asp-src-include="~/app/**/*.js" asp-src-exclude="~/app/services/**/*.js" >
</script>
Тег-хэлпер Link работает точно так же, только с атрибутами asp-href-include и asp-href-exclude.
Теперь рассмотрим атрибуты этих тег-хэлперов, которые помогут подключать CDN. Преимущества использования CDN для хостинга файлов таких популярных фреймворков как jQuery и Bootstrap очевидны: уменьшается нагрузка на наши сервера и потенциально увеличивается производительность у клиента (например, актуальная версия файла уже может быть в кеше браузера у клиента). Среди минусов – нужно предусмотреть возможность того, что CDN не отвечает и нам нужно отдавать файлы со своего сервера. С помощью тег-хэлперов это сделать проще:
<link rel="stylesheet" href="//ajax.aspnetcdn.com/ajax/bootstrap/3.0.0/css/bootstrap.min.css"
asp-fallback-href="~/lib/bootstrap/css/bootstrap.min.css"
asp-fallback-test-class="hidden"
asp-fallback-test-property="visibility"
asp-fallback-test-value="hidden" />
<script src="//ajax.aspnetcdn.com/ajax/bootstrap/3.0.0/bootstrap.min.js"
asp-fallback-src="~/lib/bootstrap/js/bootstrap.min.js"
asp-fallback-test="window.jQuery">
</script>
Атрибуты asp-fallback-test позволяют указать свойства или объекты, которые нужно проверить для того, чтобы узнать, был ли загружен файл или нет. Если нет, то файл будет загружен с использованием пути, заданном в атрибуте asp-fallback-href. Сгенерированная HTML разметка:
<link rel="stylesheet" href="//ajax.aspnetcdn.com/ajax/bootstrap/3.0.0/css/bootstrap.min.css" />
<meta name="x-stylesheet-fallback-test" class="hidden" />
<script>!function(a,b,c){var d,e=document,f=e.getElementsByTagName("SCRIPT"),g=f[f.length-1].previousElementSibling,h=e.defaultView&&e.defaultView.getComputedStyle?e.defaultView.getComputedStyle(g):g.currentStyle;if(h&&h[a]!==b)for(d=0;d<c.length;d++)e.write('<link rel="stylesheet" href="'+c[d]+'"/>')}("visibility","hidden",["\/lib\/bootstrap\/css\/bootstrap.min.css"]);</script>
<script src="//ajax.aspnetcdn.com/ajax/bootstrap/3.0.0/bootstrap.min.js">
</script>
<script>(typeof($.fn.modal) === 'undefined'||document.write("<script src=\"\/lib\/bootstrap\/js\/bootstrap.min.js\"><\/script>"));</script>
Cache busting (инвалидация кеша) – механизм, добавляющий идентификатор версии файла (на основе его содержимого) к имени файла для css и js файлов. В этом случае можно указать браузеру, что эти файлы можно кешировать на неопределенно долгое время, в случае их изменения имя у них также изменится. Для того чтобы включить этот механизм, достаточно добавить атрибут asp-append-version:
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true"/>
Сгенерированный HTML:
<link rel="stylesheet" href="/css/site.min.css?v=UdxKHVNJA5vb1EsG9O9uURFDfEE3j1E3DgwL6NiDGMc" />
Environment
Тег-хэлпер Environment используется (обычно вместе с тег-хэлперами Link и Script) для генерирования различной HTML разметки в зависимости от среды: девелопмент vs тест vs продакшен. Этот тег-хэлпер используется следующим образом: оберните в этот тег часть HTML кода и укажите среду или среды, для которых эта часть разметки должна быть включена в выходной файл. В следующем примере в девелопмент среде мы подключаем все css файлы по отдельности, а в средах Staging и Production используем скомбинированную минифицированную версию.
<environment names="Development">
<link rel="stylesheet" href="~/css/site1.css" />
<link rel="stylesheet" href="~/css/site2.css" />
</environment>
<environment names="Staging,Production">
<link rel="stylesheet" href="~/css/site.min.css" asp-file-version="true"/>
</environment>
В девелопмент среде будет сгенерирован следующий HTML код:
<link rel="stylesheet" href="/css/site1.css" />
<link rel="stylesheet" href="/css/site2.css" />
В средах Staging и Production будет добавлена ссылка на минифицированную версию:
<link rel="stylesheet" href="/css/site.min.css?v=UdxKHVNJA5vb1EsG9O9uURFDfEE3j1E3DgwL6NiDGMc"/>
Сам тег environment не посылается клиенту. Его значение задается переменной Hosting:Environment. В ASP.NET Core 1.0 (MVC 6) Hosting:Environment используется для тех же целей, для каких раньше использовалась Debug / Release конфигурация. Обычно Hosting:Environment принимает значения: Development, Staging и Production. Значением по умолчанию при запуске сайта из Visual Studio является Development. В этом можно убедиться, открыв свойства MVC проекта в Visual Studio (рисунок 2).
Для того, чтобы протестировать среды Staging или Production, нужно создать новый профиль отладки (Debug Profile) и установить требуемое значение Hosting:Environment. Например, рассмотрим, как создать профиль Production (рисунок 3).
- Кликнуть правой кнопкой мыши по проекту в обозревателе решений и выбрать Свойства.
- Выбрать вкладку Debug (Отладка).
- Нажмите New… для создания нового профиля и назовите его “IIS Express – Prod”.
- В выпадающем списке Launch выберите “IIS Express”.
- Добавьте новую переменную окружения с именем “Hosting:Environment” и значением “Production”.
- Сохраните проект.
Теперь в выпадающем списке Run в Visual Studio можно выбрать профиль “IIS Express – Prod” (рисунок 4).
Form
Именно в этом разделе тег-хэлперы делают свою работу лучше всего, увеличивая читаемость и простоту cshtml представлений. В качестве примера рассмотрим простую логин форму со следующей моделью:
public class LoginViewModel
{
public string UserName { get; set; }
public string Password { get; set; }
}
Теперь посмотрим, как можно сгенерировать поле ввода для свойства UserName.
<!--С помощью Html Helper (MVC 5 и ниже)-->
@Html.EditorFor(l => l.UserName)
<!--С помощью Tag Helper (MVC 6)-->
<input asp-for="UserName" />
Когда мы используем HTML хэлпер, то вызываем обычный C# метод, который возвращает некоторую HTML разметку. С тег-хэлперами мы имеем дело сразу с обычной HTML разметкой, в которой встречаются MVC специфичные атрибуты. В результате обоих подходов на выходе мы получим один и тот же сгенерированный HTML код:
<input name="UserName" class="text-box single-line" id="UserName" type="text" value="">
Почему подход с тег-хэлперами лучше? Код с ними становится читаемее и проще. Например, мы хотим добавить к полю ввода класс:
<!--С помощью Html Helper (MVC 5 и ниже)-->
@Html.EditorFor(l => l.UserName, new { htmlAttributes = new { @class = "form-control" } })
<!--С помощью Tag Helper (MVC 6)-->
<input asp-for="UserName" class="form-control" />
В данном случае код с использованием тег-хэлперов однозначно выигрывает и в красоте, и в простоте.
Теперь приведем код всей формы логина в двух вариантах.
Код формы с использование HTML Helpers
@using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { role = "form" }))
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
<div class="row">
@Html.LabelFor(m => m.UserName, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.UserName, "", new { @class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="row">
@Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.PasswordFor(m => m.Password, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Password, "", new { @class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-offset-2 col-md-2">
<input type="submit" value="Log in" class="btn btn-primary" />
</div>
</div>
</div>
}
Та же самая форма с использованием тег-хэлперов
<form asp-controller="Account" asp-action="Login" asp-route-returnurl="@ViewBag.ReturnUrl" method="post" class="form-horizontal" role="form">
<div asp-validation-summary="ValidationSummary.All" class="text-danger"></div>
<div class="form-group">
<label asp-for="UserName" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="UserName" class="form-control" />
<span asp-validation-for="UserName" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Password" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Password" class="form-control" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Log in" class="btn btn-default" />
</div>
</div>
</form>
Как мы видим, версия с тег-хэлперами выглядит проще и читаемее. Особенно мне нравится отсутствие выражения using для генерации формы, мне всегда это казалось каким-то хаком. Еще стоит отметить, что нам теперь не нужно явно добавлять AntiForgeryToken на форму. Тег-хэлпер form делает это автоматически, если не отключить это поведение атрибутом asp-anti-forgery=”false”.
Конечно, Visual Studio подсвечивает атрибуты тег-хэлперы, чтобы их легко можно было отличить от стандартных HTML атрибутов (рисунок 5):
Внутри атрибутов asp-for работает IntelliSense, подсказывающий имена свойств модели (рисунок 6).
Теперь рассмотрим атрибуты тег-хэлпера form. Например для того, чтобы связать форму с определенным действием определенного контроллера, используются атрибуты asp-controller и asp-action:
<form asp-controller="Account"
asp-action="Login">
//Элементы формы
</form>
В результате будет сгенерирована следующая HTML разметка:
<form action="/Account/Login" method="post">
//Элементы формы
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8AFtmUdx-b5MkQvAyGYbjFmMGSMv0Fmk7gG4RqGXlkNV6yqKqj6fgqnOh4TLT6ZnWSaqtAbKkgpEB20lvfkc2iOKZKIqt3tJ4Jij8DjmatTrZo-DKVOLwwOzj3kB8VKpFwc0rQMjaJTTC_gVv5f0vAg">
</form>
Как мы видим, по умолчанию добавляется AntiForgeryKey, а методу формы присваивается значение POST. Это поведение можно изменить, добавив в разметку переопределение атрибута method. Все HTML атрибуты, добавленные в разметку, попадут в сгенерированный код. Однако стоит учесть, что нельзя одновременно задать атрибут action и один из атрибутов asp-controller / asp-action, в этом случае будет выброшено исключение: «Cannot override the ‘action’ attribute for . A with a specified ‘action’ must not have attributes starting with ‘asp-route-‘ or an ‘asp-action’ or ‘asp-controller’ attribute.»
Иногда действию контроллера нужно передать дополнительные параметры. Это можно сделать с помощью атрибутов, начинающихся с asp-route-. Например, в действие Login часто передается параметр ReturnUrl, вот как это можно сделать с использованием тег-хэлперов:
<form asp-controller="Account"
asp-action="Login"
asp-route-returnurl="@ViewBag.ReturnUrl"
method="post" >
</form>
В итоге будет сгенерирован такой HTML код:
<form action="/Account/Login?returnurl=%2FHome%2FAbout" method="post">
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8AFtmUdx-b5MkQvAyGYbjFmMGSMv0Fmk7gG4RqGXlkNV6yqKqj6fgqnOh4TLT6ZnWSaqtAbKkgpEB20lvfkc2iOKZKIqt3tJ4Jij8DjmatTrZo-DKVOLwwOzj3kB8VKpFwc0rQMjaJTTC_gVv5f0vAg">
</form>
Используя такой синтаксис, можно указывать столько параметров, сколько необходимо.
Еще тег-хэлпер form поддерживает возможность указать именованный маршрут вместо пары контроллер / действие. Предположим, что мы определили маршрут с именем login в MVC коде:
routes.MapRoute(
name: "login",
template: "login",
defaults: new { controller = "Account", action = "Login" });
Тогда мы можем указать этот маршрут для формы, используя атрибут asp-route:
<form asp-route="login"
asp-route-returnurl="@ViewBag.ReturnUrl"
method="post" >
</form>
Что в свою очередь сгенерирует точно такую же HTML разметку, как и в предыдущем случае:
<form action="/login?returnurl=%2FHome%2FAbout" method="post">
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8AFtmUdx-b5MkQvAyGYbjFmMGSMv0Fmk7gG4RqGXlkNV6yqKqj6fgqnOh4TLT6ZnWSaqtAbKkgpEB20lvfkc2iOKZKIqt3tJ4Jij8DjmatTrZo-DKVOLwwOzj3kB8VKpFwc0rQMjaJTTC_gVv5f0vAg">
</form>
Input
Тег-хэлпер input является альтернативой Html.EditorFor. В следующем примере будем использовать такой простой класс модели представления:
public class SimpleViewModel
{
public string Email { get; set; }
}
Поле ввода для Email можно создать с помощью asp-for атрибута:
<input asp-for="Email" />
В результате чего получим следующую HTML разметку:
<input type="text" id="Email" name="Email" value="thisaddress@isfrommymodel.com" />
Тег-хэлпер добавляет атрибуты id и name, значение которых задается именем свойства, указанным в asp-for. Тип сгенерированного input был установлен в text потому, что тип свойства Email string. Если бы тип свойства был bool, то тег-хэлпер сгенерировал бы input с типом checkbox. Ниже представлена таблица соответствия .NET типов и HTML input типов.
.NET тип | HTML input тип |
String | type=”text” |
DateTime | type=”datetime” |
Byte | type=”number” |
Int16, Int32, Int64 | type=”number” |
Single, Double | type=”number” |
Boolean | type=”checkbox” |
Тег-хэлпер input принимает во внимание не только тип свойства, но и валидационные атрибуты. Например, добавим [Required] к свойству Email:
public class SimpleViewModel
{
[Required]
public string Email { get; set; }
}
В этом случае в сгенерированной HTML разметке будет атрибут data-val-required, который используется jQuery Validation.
<input type="text" data-val="true"
data-val-required="The Email field is required."
id="Email"
name="Email"
value="" />
Если добавить атрибут [EmailAddress] к свойству модели, то будет сгенерирован input с типом email и атрибутом data-val-email. Ниже приведена таблица с указанием .NET атрибутов, которые соответствуют различным типам HTML input.
Атрибут | HTML input тип |
[EmailAddress] | type=”email” |
[Url] | type=”url” |
[HiddenInput] | type=”hidden” |
[DataType(DataType.Password)] | type=”password” |
[DataType(DataType.Date)] | type=”date” |
[DataType(DataType.Time)] | type=”time” |
Также можно использовать дочерние объекты в моделях представления. Чуть усложним нашу модель.
public class AddressViewModel
{
public string AddressLine1 { get; set; }
}
public class RegisterViewModel
{
public string UserName { get; set;}
public AddressViewModel Address { get; set; }
}
В представлении мы можем создать поле ввода для Address.AddressLine1:
<input asp-for="Address.AddressLine1" />
В результате получим следующий HTML код:
<input name="Address.AddressLine1" id="Address_AddressLine1" type="text" value="">
Конечно, все атрибуты, которые будут в cshtml файле применены тег-хэлперу input, будут добавлены в сгенерированную HTML разметку.
Еще одной возможностью, предоставляемой тег-хэлпером input, является использование обычной <a href=” msdn.microsoft.com/en-us/library/dwhawy9k.aspx”>строки форматирования, широко использующейся в .NET. Для этого используется атрибут asp-format, например:
<input asp-for="SomeNumber" asp-format="{0:N4}"/>
В этом случае число будет показано с 4 знаками после запятой, например, 1.2000. Никаких дополнительных атрибутов не добавляется.
Как мы уже говорили, Visual Studio предоставляет IntelliSense для тег-хэлпера input, подсвечивает ошибки, если есть ошибка в имени свойства. Исключение в таком случае будет выброшено во время компиляции, но по умолчанию Razor представления не прекомпилируются, поэтому эта ошибка будет видна только при первом обращении к странице.
TextArea
Тег-хэлпер textarea во многом похож на ранее рассмотренный input и является альтернативой Html.TextAreaFor. Он также использует атрибут asp-for. Рассмотрим следующую модель представления:
public class SimpleViewModel
{
[Required]
[MaxLength(5000)]
public string Description { get; set; }
}
Мы используем тег-хэлпер textarea следующим образом:
<textarea asp-for="Description"></textarea>
Что сгенерирует следующую HTML разметку:
<textarea name="Description" id="Description"
data-val-required="The Description field is required."
data-val-maxlength-max="5000"
data-val-maxlength="The field Description must be a string or array type with a maximum length of '5000'."
data-val="true"></textarea>
В сгенерированном элементе textarea определены name, id, добавлены валидационные атрибуты.
Validation
Мы увидели, что добавлять валидационные атрибуты несложно, теперь обсудим, где показывать валидационные сообщения. Раньше для этого использовался метод Html.ValidationMessageFor, теперь – атрибут asp-validation-for, применяемый к элементу span.
<span asp-validation-for="Email"></span>
Это сгенерирует следующую HTML разметку, в случае если поле Email было сделано обязательным, но не было заполнено:
<span class="field-validation-error"
data-valmsg-replace="true"
data-valmsg-for="Email">
The Email field is required.</span>
Тег-хэлпер нашел валидационное сообщение для свойства Email и добавил его в содержимое элемента span. Также он добавил data-valmsg-* атрибуты, чтобы клиентская валидация jQuery для поля Email работала с этим элементом. Обычно тег-хэлпер валидации будет помещен на форму рядом с полем, которое он валидирует. Как и для всех остальных тег-хэлперов, все HTML атрибуты, которые вы к нему добавите, попадут в сгенерированную HTML разметку.
Теперь рассмотрим аналог Html.ValidationSummary(true) – тег-хэлпер Validation Summary, который агрегирует валидационные сообщения для валидационных сообщений уровня всей модели и/или уровня свойств модели. Этот тег-хэлпер представляет собой атрибут asp-validation-summary, который добавляется к элементу div. Возможные значения этого атрибута:
- ValidationSummary.All – будут показаны и сообщения уровня всей модели, и сообщения для всех ее свойств.
- ValidationSummary.ModelOnly – будут показаны только сообщения уровня всей модели
- ValidationSummary.None – тег-хэлпер ничего не делает, как если бы вы не добавляли атрибут asp-validation-summary. Единственным применением видится быстрое отключение всех валидационных сообщений для каких-то своих девелоперских нужд.
<div asp-validation-summary="ValidationSummary.All"></div>
Этот код сгенерирует следующую разметку в случае, когда валидационных ошибок нет:
<div class="validation-summary-valid" data-valmsg-summary="true">
<ul>
<li style="display: none;"></li>
</ul>
</div>
Если же у нас есть ошибки валидации:
<div class="validation-summary-errors" data-valmsg-summary="true">
<ul>
<li>The Email field is required.</li>
<li>The Password field is required.</li>
</ul>
</div>
Label
Тег-хэлпер label является самым
public class SimpleViewModel
{
[Display(Name="Email Address")]
public string Email { get; set; }
}
Теперь используем тег-хэлпер label:
<label asp-for="Email"></label>
Что в результате даст нам следующую HTML разметку:
<label for="Email">Email Address</label>
Select
Тег-хэлпер select используется для создания выпадающих списков в HTML разметке вместо Html.DropDownListFor. Пусть у нас есть модель со свойством CountryCode, которое мы хотим заполнять с помощью выпадающего списка:
public class SimpleViewModel
{
public string CountryCode { get; set; }
}
Теперь с помощью тег-хэлпера свяжем это поле с элементом select.
<select asp-for="CountryCode"></select>
И получим следующий HTML код:
<select name="CountryCode" id="CountryCode">
</select>
Конечно, этот код не несет практической ценности, потому что выпадающий список еще пуст. Есть 2 способа его заполнить. Первый (для совсем маленьких списков): все возможные варианты задать вручную в представлении:
<select asp-for="CountryCode">
<option value="CA">Canada</option>
<option value="US">US</option>
<option value="--">Other</option>
</select>
В этом случае значение будет выбрано исходя из значения свойства в модели. Например, если CountryCode равен “CA”, будет сгенерирована следующая HTML разметка:
<select name="CountryCode" id="CountryCode">
<option selected="selected" value="CA">Canada</option>
<option value="US">US</option>
<option value="--">Other</option>
</select>
Второй способ задания возможных значений – динамическая загрузка из источника данных. Для этого нужен источник данных типа IEnumerable<SelectListItem> (или SelectList), пусть в нашем случае он доступен в ViewBag.Countries. Для привязки источника данных используется атрибут asp-items:
<select asp-for="CountryCode"
asp-items="ViewBag.Countries">
</select>
Для того, чтобы сгенерированный элемент select поддерживать возможность выбора нескольких элементов, достаточно, чтобы свойство модели имело тип IEnumerable, например:
public class SimpleViewModel
{
public IEnumerable<string> CountryCodes { get; set; }
}
В коде использования тег-хэлпера ничего не меняем:
<select asp-for="CountryCodes"
asp-items="ViewBag.Countries">
</select>
Но сгенерированная HTML разметка будет другой:
<select name="CountryCodes"
id="CountryCodes"
multiple="multiple">
<option selected="selected"
value="CA">Canada</option>
<option value="USA">United States</option>
<option value="--">Other</option>
</select>
Anchor
Тег-хэлпер anchor служит для генерации ссылок и является заменой как Html.ActionLink, так и Url.Action, с помощью которых мы обычно писали вот так:
@Html.ActionLink("Register", "Register", "Account")
<a href="@Url.Action("Register", "Account")">Register</a>
И в результате получали две одинаковые ссылки:
<a href="/Account/Register">Register</a>
<a href="/Account/Register">Register</a>
Теперь с помощью тег-хэлпера anchor и атрибутов asp-controller, asp-action ссылку можно добавить следующим образом:
<a asp-controller="Account"
asp-action="Register">Register</a>
Как и в случае остальных тег-хэлперов, их использование позволяет проще добавить дополнительные классы и атрибуты для этих элементов, в отличие от Html.ActionLink(«Register », «Create», “Account”, null, new { class= «css-class»} ).
Если в метод контроллера надо передать дополнительные параметры, то это можно сделать так же, как и для тег-хэлпера form: с помощью атрибутов asp-route-*, например:
<a asp-controller="Product"
asp-action="Display"
asp-route-id="@ViewBag.ProductId">
View Details</a>
Также можно указать именованный маршрут (опять точно так же, как для form):
<a asp-route="login">Login</a>
Ранее используемый Html.ActionLink позволял указать протокол, хост и фрагмент генерируемого URL. У тег-хэлпера есть для этого свои атрибуты:
<a asp-controller="Account"
asp-action="Register"
asp-protocol="https"
asp-host="asepecificdomain.com"
asp-fragment="fragment">Register</a>
<!-- или только указывая протокол -->
<a asp-controller="Account"
asp-action="Register"
asp-protocol="https">Register</a>
Cache
У тег-хэлпера cache нет аналога среди Html хэлперов, да и обычным HTML элементом он не является. Он позволяет закешировать свое содержимое в памяти. Перед каждой обработкой своего содержимого он проверяет, не было ли оно уже сохранено в MemoryCache. Если содержимое найдено в кеше, оно отправляется сразу в Razor движок, если нет – сначала Razor обработает его, а потом оно сохранится в кеш. По умолчанию тег-хэлпер сгенерирует уникальный ID своего содержимого. Вот так его можно использовать в представлениях:
<cache expires-after="@TimeSpan.FromMinutes(10)">
@Html.Partial("_WhatsNew")
*last updated @DateTime.Now.ToLongTimeString()
</cache>
Тег cache не будет включен в сгенерированную HTML разметку, это просто директива для движка, что на протяжении 10 минут клиенту можно посылать уже обработанную и закешированную версию представления _WhatsNew.
Если не указать время жизни закешированной версии, то по умолчанию она будет отдаваться все время жизни приложения (или до первого ресайкла пула). Тег-хэлпер cache поддерживает следующие опции задания времени жизни закешированного объекта:
- expires-after: задает промежуток времени от текущего момента, во время которого кеш считается валидным, например, 5 секунд. Атрибут expires-after ожидает объект типа TimeSpan:
<cache expires-after="@TimeSpan.FromSeconds(5)"> <!-- содержимое --> *last updated @DateTime.Now.ToLongTimeString() </cache>
- expires-on: принимает объект типа DateTime, который показывает, в какой момент кеш перестанет быть валидным:
<cache expires-on="@DateTime.Today.AddDays(1).AddTicks(-1)"> <!--содержимое--> *last updated @DateTime.Now.ToLongTimeString() </cache>
- expires-sliding: принимает объект типа TimeSpan, который задает промежуток времени, если в течение которого объект в кеше не запрашивался, то кеш перестает быть валидным.
<cache expires-sliding="@TimeSpan.FromMinutes(5)"> <!-- содержимое --> *last updated @DateTime.Now.ToLongTimeString() </cache>
По умолчанию ключ объекта в кеше генерируется уникально на основе контекста тег-хэлпера, что позволяет использовать несколько тег-хэлперов cache на одной странице без путаницы их содержимого в кеше. С помощью атрибутов vary-by можно задавать более сложные ключи, позволяющие кешировать разное содержимое тег-хэлпера cache для разных запросов. Рассмотрим возможные варианты атрибутов vary-by.
- vary-by-user: принимает булевское значение, позволяет кешировать различное содержимое для различных залогиненных пользователей. К ключу объекта в кеше добавляется имя пользователя.
<cache vary-by-user="true"> <!-- содержимое --> *last updated @DateTime.Now.ToLongTimeString() </cache>
- vary-by-route: принимает список имен параметров маршрутизации, значения которых будут добавлены к ключу объекта. Например, так можно кешировать содержимое в зависимости от значения параметра id:
<cache vary-by-route="id"> <!-- содержимое --> *last updated @DateTime.Now.ToLongTimeString() </cache>
- vary-by-query: принимает список имен параметров запроса, значения которых будут добавлены к ключу объекта в кеше. Например, так можно кешировать в зависимости от значения параметра search:
<cache vary-by-query="search"> <!-- содержимое --> *last updated @DateTime.Now.ToLongTimeString() </cache>
- vary-by-header: принимает имя HTTP заголовка (одно, не список), значение которого будет добавлено к ключу. Вот так можно кешировать содержимое в зависимости от заголовка User-Agent:
<cache vary-by-header="User-Agent"> <!-- содержимое --> *last updated @DateTime.Now.ToLongTimeString() </cache>
- vary-by: позволяет кешировать различное содержимое тег-хэлпера в зависимости от значения произвольной строки, если ни один из рассмотренных выше атрибутов vary-by-* не подходит. Например, можно добавить свойство ProductId, хранящееся во ViewBag:
<cache vary-by="@ViewBag.ProductId"> <!-- содержимое --> *last updated @DateTime.Now.ToLongTimeString() </cache>
- Составные ключи: можно применять сразу несколько различных атрибутов vary-by, например и по пользователю, и по параметру маршрутизации id:
<cache vary-by-user="true" vary-by-route="id"> <!-- содержимое --> *last updated @DateTime.Now.ToLongTimeString() </cache>
Так как все закешированное содержимое хранится в IMemoryCache, то его размер ограничен размером доступной оперативной памяти. Поэтому если процесс начинает испытывать нехватку памяти, кеш будет удалять свои элементы для освобождения памяти. С помощью атрибута priority можно указать, какие объекты следует удалять первыми, а какие оставлять в кеше. Возможные значения этого атрибута: Low, Normal, High и NeverRemove. Например, укажем, что содержимое тег-хэлпера можно считать неприоритетным:
@using Microsoft.Framework.Caching.Memory
<cache vary-by-user="true"
priority="@CachePreservationPriority.Low">
<!-- содержимое -->
*last updated @DateTime.Now.ToLongTimeString()
</cache>
Ограничения этого тег-хэлпера связаны с тем, что он использует MemoryCache в свое реализации. Первое ограничение связано с тем, что любой перезапуск процесса, ресайкл пула приложения и похожее действие инвалидирует весь наш кеш, в облаке такое может произойти, если сайт переедет на новую машину. Поэтому нельзя считать этот кеш надежным. Второе ограничение также связано с тем, что кеш хранится в памяти. Если пользователь в рамках сессии будет перенаправлен на разные веб-сервера, потенциально он может увидеть разное содержимое одного и того же элемента. Это связано с тем, что у каждого сервера будет своя версия кеша, реализация MemoryCache не является распределенной. В данном случае может помочь привязка пользователя к одному и тому же серверу (sticky session, server affinity).
Image
Этот простой в использовании тег-хэлпер состоит из всего одного атрибута asp-append-version, добавляемого к тегу img. Если передать этому атрибуту значение true, то к URL изображения будет добавлена строка, зависящая от содержимого картинки (как и в случае css / js файлов), что позволит браузеру кешировать ее неопределенно долгое время.
<img src="~/images/logo.png"
alt="company logo"
asp-append-version="true" />
В результате будет сгенерирована похожая HTML разметка:
<img src="/images/logo.png?v=W2F5D366_nQ2fQqUk3URdgWy2ZekXjHzHJaY5yaiOOk"
alt="company logo"/>
Использование этого тег-хэлпера упрощает выбор политики кеширования изображений сайта: при маленьком времени кеширования нивелируется выгода от его применения, при большом – потенциально при обновлении изображения клиент в течение долгого времени продолжает использовать старую локально закешированную версию изображения.
Заключение
С одной стороны плохо, что все наши представления с версией MVC <= 5 надо переписывать, но с использованием тег-хэлперов они выглядят чище, их легче использовать дизайнерам / верстальщикам, теперь они выглядят как обычный HTML с дополнительными атрибутами. Следующий раз рассмотрим создание своего тег-хэлпера, а пока качайте VS 2015 Community Edition, создавайте свой первый проект ASP.NET Core 1.0!
Ссылки
Документация по тег-хэлперам
Документация по последней версии ASP.NET MVC
Visual Studio 2015 Community Edition