Andrey on .NET | Основы. Часть 6 – Заготовки (scaffolding)

Основы. Часть 6 – Заготовки (scaffolding)

Слово scaffold переводится с английского языка как "строительные леса". Поскольку прямой перевод в данном случае не является самым удачным, то в далее будет использоваться слово "заготовка". Давайте разберемся, что это такое, зачем они нужны и как они упрощают разработку ASP.NET MVC приложений.

Зачем нужны заготовки?

Наверное многим приходилось не раз сталкиваться с созданием однотипных блоков приложения. Зачастую их нельзя просто взять и вынести в отдельный класс или метод. Хорошим примером в ASP.NET MVC может служить исходный код Контроллера на начальном этапе разработки. Зачастую он повторяется от проекта к проекту или даже от Контроллера к Контроллеру, а все отличия заключатся только в именах классов. Создавать такой код каждый раз с нуля достаточно утомительно.

Здесь и приходят на помощь заготовки – шаблоны, которые позволяют генерировать программный код. Но кроме самих прототипов исходных текстов они могут включать в себя логику создания их частей. Таким образом, могут быть подставлены имена свойств и классов, подключены нужные пространства имен и т.д.

Обратите внимание, что целью заготовок не является быстрое создание законченного рабочего кода. Их результат, как правило, требует последующей доработки под конкретную задачу. Именно поэтому они называются "заготовки" или "строительные леса", что в обоих вариантах перевода отражает их суть.

Подключаем заготовки

Рассматриваемая функциональность не является встроенной в Visual Studio изначально. Для её подключения в проект удобнее всего воспользоваться консолью NuGet. Откроем её и введем следующую команду: Install-Package MvcScaffolding. В результате будет выведено:

PM> Install-Package MvcScaffolding
'T4Scaffolding (≥ 1.0.0)' not installed. Attempting to retrieve dependency from source...
Done.
Successfully installed 'T4Scaffolding 1.0.1'.
Successfully installed 'MvcScaffolding 1.0.0'.
Successfully added 'T4Scaffolding 1.0.1' to BookCatalog.
Successfully added 'MvcScaffolding 1.0.0' to BookCatalog. 

Те, кто предпочитают использоваться графическую оболочку, могут также выполнить поиск установочного пакета MvcScaffolding в галерее NuGet.

Диалог добавления Контроллера с заготовкамиОбратите внимание, что в процессе установки также был добавлен еще один пакет: T4Scaffolding. Именно он и обеспечивает обработку заготовок и создание файлов с исходным кодом, добавляемых в проект. Стоит отметить, что он может быть использован также в других типах проектов. А вот MvcScaffolding это дополнительный набор заготовок именно для ASP.NET MVC.

После установки заготовки доступны как через консоль NuGet, так и через графический интерфейс помощника ASP.NET MVC при добавлении Контроллера. Рассмотрим и будем использовать в дальнейшем первый вариант, так как он предоставляет больше возможностей в работе.

Команды настройки

Ввод команд для использования заготовок осуществляется в консоли NuGet. Соответственно, все команды поддерживают подсказки для ввода по нажатию кнопки Tab.

Get-Scaffolder <DefaultName>

Эта команда выводит перечень доступных для использования заготовок. Например:

PM> Get-Scaffolder

Name                                Description            Package
----                                -----------            -------
MvcScaffolding.Action               Creates an action...  MvcScaffolding 1.0.0
MvcScaffolding.ActionUnitTest       Creates a unit te...  MvcScaffolding 1.0.0
MvcScaffolding.ActionWithUnitTest   Creates an action...  MvcScaffolding 1.0.0
MvcScaffolding.AspxView             Adds an ASP.NET M...  MvcScaffolding 1.0.0
MvcScaffolding.Controller           Adds an ASP.NET M...  MvcScaffolding 1.0.0
MvcScaffolding.RazorView            Adds an ASP.NET M...  MvcScaffolding 1.0.0
MvcScaffolding.Views                Adds ASP.NET MVC ...  MvcScaffolding 1.0.0
T4Scaffolding.CustomScaffolder      Creates an entire...  T4Scaffolding 1.0.1
T4Scaffolding.CustomTemplate        Allows you to mod...  T4Scaffolding 1.0.1
T4Scaffolding.EFDbContext           Makes an EF DbCon...  T4Scaffolding 1.0.1
T4Scaffolding.EFRepository          Creates a reposit...  T4Scaffolding 1.0.1

Имена из колонки Name необходимо будет использовать для указания выбранной заготовки.

Опционально можно указать в качестве параметра команды имя по умолчанию (что это такое будет пояснено в описании следующей команды). В этом случае будет выведено название текущей установленной для него заготовки. Например:

PM> Get-Scaffolder View

Name                                Description            Package                       
----                                -----------            -------                       
MvcScaffolding.RazorView            Adds an ASP.NET MV...  MvcScaffolding 1.0.0

Get-DefaultScaffolder

Отображает список сокращенных имен (DefaultName) и присвоенных им заготовок (ScaffolderName).

PM> Get-DefaultScaffolder 

DefaultName                      ScaffolderName
-----------                      --------------
Action                           MvcScaffolding.Action
Controller                       MvcScaffolding.Controller
CustomScaffolder                 T4Scaffolding.CustomScaffolder
CustomTemplate                   T4Scaffolding.CustomTemplate
DbContext                        T4Scaffolding.EFDbContext
Repository                       T4Scaffolding.EFRepository
UnitTest                         MvcScaffolding.ActionUnitTest
View                             MvcScaffolding.RazorView
Views                            MvcScaffolding.Views

Сокращенным именам в левой колонке в данной конфигурации соответствуют заготовки, указанные в правой колонке. Такой подход удобен по двум причинам:

  1. Во первых, удобнее указывать сокращенное имя. Ведь вполне ожидаемо, что если в проекте используется движок представлений Razor, то сами Представления будут создаваться с помощью заготовки MvcScaffolding.RazorView. В этом случае можно просто указывать View.
  2. Во вторых, это увеличивает гибкость самой системы, так как в процессе генерации исходного кода заготовки могут вызывать друг друга. При этом будут использоваться имена по умолчанию. Например, MvcScaffolding.Controller обращается к заготовкам Repository и View. Последняя может соответствовать как MvcScaffolding.RazorView, так и MvcScaffolding.AspxView. В зависимости от этого будут генерироваться Представления, содержащие код для движков Razor или WebForms.

Set-DefaultScaffolder <DefalutName> <ScaffolderName>

Устанавливает соответствие сокращенного имени и заготовки. Например, чтобы View присвоить MvcScaffolding.AspxView необходимо дать следующую команду:

PM> Set-DefaultScaffolder View MvcScaffolding.AspxView

Команды генерации исходного кода

В общем виде команда для генерации исходного кода на основе заготовки выглядит так:

Scaffold <Name> [Parameters]

В качестве первого параметра Name указывается имя заготовки (по умолчанию или полное). От него зависит идущий следом список параметров Parameters. Рассмотрим некоторые варианты.

Scaffold Controller <СontrollerNameOrModelType> [Parameters]

Создает Контроллер на базе указанного типа Модели и связанные с ним Представления для Команд Create, Details, Delete, Edit и Index. Кроме того, добавляет исходный код для работы с базой данных посредством Entity Framework Code First.

Значение ControllerNameOrModelType определяет имя Контроллера или тип Модели в том случае, если они должны быть схожи. Например, команда Scaffold Controller Tag, используя описание класса Tag, создаст Контроллер Tags и реализующий его класс TagsController.

Опциональные параметры позволяют переопределить поведение по умолчанию. Их список включает:

  • -ControllerName – позволяет определить имя Контроллера. По умолчанию оно будет получено из второго параметра команды (СontrollerNameOrModelType) .
  • -ModelType – используется для указания используемого типа Модели, если его имя должно отличаться от имени создаваемого Контроллера.
  • -Project – определяет проект, в который будут добавлены генерируемые файлы. По умолчанию используется вариант, выбранный в выпадающем меню "Default project" консоли NuGet.
  • -CodeLanguage – указывает язык, на котором должны быть созданы файлы. Возможно указать два варианта: cs для C# и vb для VisualBasic. По умолчанию используется язык проекта.
  • -DbContextType – задает имя класса контекста доступа к базе данных (что это такое будет рассмотрено позже при изучении основ Entity Framework). По умолчанию будет использовано имя <yourProjectName>Context.
  • -Repository – при использовании этого параметра для доступа к базе данных будет применен шаблон Репозиторий (Repository). По умолчанию вместо это в Контроллер вносится код работы с Entity Framework Code First.
  • -Layout – позволяет задать свой шаблон разметки страниц для генерируемых Представлений.
  • -Force – указывает на то, что все генерируемые файлы могут перезаписывать существующие. По умолчанию создаются только файлы, которых не было в проекте.
  • -NoChildItems – отключает создание Представлений, контекста базы данных и т. д. В результате будет сгенерирован только файл с классом Контроллера.
  • -Area – определяет область ASP.NET MVC, в которую должны быть включены генерируемые файлы. На момент написания этой статьи автоматическое создание новых областей не поддерживается. Поэтому при необходимости их нужно самостоятельно добавлять в проект.
  • -ReferenceScriptLibraries – добавляет ссылки на библиотеки jQuery в создаваемые Представления.

Например, команда для создания контроллера TagList (класс TagListController) на используя класс Модели Tag с перезаписью всех уже существующих файлов будет выглядеть следующим образом:

PM> Scaffold Controller Tag –ControllerName TagList -Force

Scaffold View <ControllerName> <ViewName> <Parameters>

Создает пустое Представление для указанного Контроллера. Обратите внимание, что в качестве его имени ControllerName должно быть указано название (например, Tags), а не имя класса (TagsController), в котором содержится его реализация.

Поддерживаемые опциональные параметры:

  • -TemplateName – имя шаблона (Create, Delete, Details, Edit, Index или Edit). При указании данного параметра вместо пустого будет создано соответствующее Представление.
  • -ModelType – указывает тип Модели. В результате сгенерированное Представление будет строго-типизированным.
  • -Project – см. описание выше
  • -Area – см. описание выше
  • -Layout – см. описание выше
  • -CodeLanguage – см. описание выше
  • -Force – см. описание выше
  • -ReferenceScriptLibraries – см. описание выше

Scaffold Views <ModelType>

Создает набор стандартных Преставлений (Create, Delete, Details, Edit и Index) для указанного типа Модели. Используется заготовкой создания Контроллера, если не была указана опция -NoChildItems.

Scaffold DbContext <ModelType> <dbContextName> <Parameters>

Генерирует для указанного типа Модели исходный код класса контекста работы с базой данных, который используется в Entity Framework Code First. Если он уже существует, то просто добавляет необходимые свойства, не изменяя остальное его содержимое.

Поддерживаются следующие опциональные параметры:

  • -Project – см. описание выше
  • -Area – см. описание выше
  • -CodeLanguage – см. описание выше
  • -Force – см. описание выше
  • -DbContextType – см. описание выше

Scaffold Repository <modelType> <Parameters>

Используется для создания класса, реализующего шаблон Репозиторий (Repository) для работы с базой данной посредством Entity Framework Code First. Также создает описание его интерфейса. Все это вместе является более гибкой альтернативой размещению кода взаимодействия с данной библиотекой в Контроллере, как это делает помощник ASP.NET MVC 3.

При создании Контроллера командой Scaffold Controller можно также задействовать создание репозитория если указать опциональный параметр: -Repository.

Поддерживаются следующие опциональные параметры:

  • -NoChildItems – создается только код интерфейса Репозитория и его реализация для указанного типа Модели. По умолчанию кроме него создается или модифицируется контекст базы данных.
  • -Project – см. описание выше
  • -Area – см. описание выше
  • -CodeLanguage – см. описание выше
  • -Force – см. описание выше

Scaffold CustomTemplate <ScaffolderName> <TemplateName>

Создает копию шаблона TemplateName из заготовки ScaffolderName для модификации. Исходный файл будет скопирован в папку \CodeTemplates\Scaffolders\. Расположенные в ней заготовки используются в текущем проекте вместо оригинальных.

Поддерживаются следующие опциональные параметры:

  • -Project – см. описание выше
  • -CodeLanguage – см. описание выше
  • -Force – см. описание выше

Например, для создания копии заготовки Репозитория необходимо дать следующую команду:

PM> Scaffold CustomTemplate T4Scaffolding.EFRepository Repository

В результате в папку CodeTemplates\Scaffolders\T4Scaffolding.EFRepository будет скопирован файл Repository.cs.t4. Язык определяется самим проектом или указанием параметром -CodeLanguage.

Scaffold CustomScaffolder <NewScaffolderName>

Создает код, необходимый для создания собственной заготовки под названием NewScaffolderName. В отличии от предыдущего варианта, требует создание не только заготовки кода, но и PowerShell скрипта. Последний отвечает за настройку параметров генерации файлов.

Переходим к действиям

Как хорошо видно из описания выше заготовки это отличный инструмент для автоматизации рутинных частей разработки веб-проекта, особенно на начальном этапе. Кроме того, он позволяет создать Контроллеры с использованием шаблона Репозиторий, что увеличивает гибкость кода.

В следующей части, посмотрим на заготовки в действии – отредактируем и используем их для создания Контроллеров разрабатываемого демонстрационного веб-приложения BookCatalog.

Комментарии (15) -

почему то команда Get-Scaffolder не срабатывает, в чем может быть причина?

@ Dauren: А что выдает?

Дмитрий 06.12.2011 22:26:15

При создании контроллера Tag создается файл BookCatalogContext, в котором объявлен  public DbSet<BookCatalog.Models.Tag> Tags { get; set; }.
А в контроллере все ссылки идут на свойство Tag(соответственно, выдает ошибку). Плюс вызываются несуществующие функции этого класса

@ Дмитрий: А какой командой создавали? Сейчас проверил - все содздается корректно как со старой, так с новой версией MVCScaffolding.

Да, я использовал:
Scaffold Сontroller Tag -DbContextType CatalogContext -Repository -ReferenceScriptLibraries

Андрей
Аналогичная проблема

PM> Get-Scaffolder
The term 'Get-Scaffolder' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was
included, verify that the path is correct and try again.
At line:1 char:15
+ Get-Scaffolder <<<<
    + CategoryInfo          : ObjectNotFound: (Get-Scaffolder:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

@ Alexey: Какая версия MVCScaffolding?


MvcScaffolding                 1.0.6        
T4Scaffolding                  1.0.5

Хм... видимо вам стоит обратиться к разработчикам MvcScaffolding и сообщить об ошибке. Попробовал на указанной версии - Get-Scaffolder выдает список заготовок.

Andrey
В списке доступных команд (get-help get-*) данной команды просто нет. Все равно, спасибо за помощь и за Ваш курс. Очень интересно и доступно.

@ Alexey: У вас точно проявляется какая-то ошибка. Из любопыства создал пустой проект, обновил все пакеты, потом Install-Package MvcScaffolding и get-help get-s*. Get-Scaffolder есть.

По поводу проблемы выше и для будущих читателей поста, замечу, что для себя я эту проблему решил достаточно быстро.)) Во всём виноват оказался PowerShell.
В общем: нужно изменить политику безопасности в отношении исполнения скриптов. На данную тему можно или погуглить или бингнуть пару раз, ну или можно изменить например политику на RemoteSigned командой PS> Get-ExecutionPolicy RemoteSigned.
Не плохая статья на xakep.ru, где упоминается данная тема: http://www.xakep.ru/post/50777/

Если у кого-то проблема с Get-Scaffolder, просто обновите NuGet Package Manager. И все у вас будет работать.

@ Veligord:
нужно обновить NuGet хотя бы до версии 1.2 (текущая на момент коммента 1.6, лучше конечно обновлять сразу до неё)
А если не хочет обновляться (vs2010 ultimate - есть такая проблема) - снесите старый вручную, ибо через студию тоже не обновляется.
Вот порядок действий:
закрыть все открытые студии
вручную удалить папку C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft Corporation\NuGet Package Manager
скачать с сайта и запустить NuGet.Tools.vsix
Профит!

Это рекомендации от разрабов NuGet, не я придумал.

Dzmuh:
Get-ExecutionPolicy RemoteSigned

Set-ExecutionPolicy RemoteSigned, а не Get. Но все-равно не помогает. Версия NuGet 1.4

Добавить комментарий