Использование NuGet. Часть 3 – Создаем установочный пакет

NuGet logo В прошлой части было рассмотрено как подключить к NuGet локальный репозиторий. Это удобное решение для установки библиотек собственной разработки. Осталось разобраться как создать свой пакет.

Для его создания потребуется утилита “NuGet.exe Command Line”, которую можно загрузить с официальной страницы проекта на CodePlex.Скопируем её в папку, доступную из командной строки. В качестве подходящего места может выступить “(Program files)\Microsoft Visual Studio 10.0\Common7\Tools”.

Создаем проект библиотеки

Прежде чем создать установочный пакет, необходимо подготовить библиотеку, которая будет в него включена. В неё включим атрибуты проверки данных, созданные в цикле статей “ASP.NET MVC 3 в деталях”. Обратите внимание, что для подключения этой библиотеки к проекту необходимо не только добавить её сборку, но и скопировать дополнительные JavaScript-файлы.

Имя решения (solution) возьмем произвольное. А вот название проекта будет совпадать с используемым в библиотеке пространством имен MVCDemo.Attributes.Validation. Включем в него следующие исходные файлы атрибутов проверки данных:

  • BlockHtmlAttribute.cs
  • EqualAttribute.cs
  • StringLengthRangeAttribute.cs

Кроме того, в папке Scripts\Validation разместим JavaScript-файлы для поддержки проверки данных на стороне клиента:

  • BlockHtmlAttribute.js
  • EqualAttribute.js

Чтобы не акцентировать внимание на создании библиотеки (class library), можно сразу загрузить готовый проект. Соберем его в режиме Release. Все готово для создания установочного пакета NuGet.

Создаем установочный пакет

Чтобы лучше понять принципы работы NuGet, соберем установочный пакет вручную. Для этого в корневой папке решения создадим папку nuget-package (имя произвольное) для размещения его файлов.

Структура папок

По умолчанию, все папки и файлы, включая вложенные, в указанном для создания сборки месте будут включены в установочный пакет. Однако, NuGet определяет три специальных имени для папок, содержимое которых будет обработано особым образом:

  • tools – папка для утилит, которые должны быть доступны из командной строки. После установки её путь добавляется в список, расположенный в переменной среды Path.
  • lib – хранилище сборок проекта. Именно сюда необходимо скопировать их DLL файлы.
  • content – место хранения дополнительных файлов. Его внутренняя структура может быть любой. При этом она один в один будет перенесена в корневую папку проекта при установке пакета.

Кроме того, папка lib имеет дополнительное соглашение. Сборки, размещенные непосредственно в ней, будут подключены к проекту для любой версии .NET Framework. Но при необходимости DLL файлы можно разделить в зависимости от версии .NET или Silverlight для которых они предназначены. Для этого файлы необходимо разместить в подпапке с названием и номером версии платформы. Для интерпретации этого имени NuGet использует класс FrameworkName. Поэтому возможно использовать как полные имена, так и сокращения. Кроме того, при отсутствии имени считается что подразумевается .NET Framework. Таким образом, “4.0” эквивалентно ”.NetFramework 4.0”.

Может возникнуть вопрос: а что будет если расположить файлы и самой lib и в подпапках для различных версий .NET? В этом случае, файлы из основной папки всегда будут добавляться в проект, а из подпапок – только в проект, ориентированный на указанную платформу и её версию.

Таким образом структура может выглядеть следующим образом:

  • content
  • lib
    • .NetFramework 1.1
    • .NetFramework 2.0
    • .NetFramework 4.0
    • Silverlight 3.0
    • Silverlight 4.0
  • tools

Разумеется, необходимо создавать только те папки, в которых будут размещены файлы.

В случае с создаваемым для примера установочным пактом необходимо:

  • в content скопировать папку Scripts;
  • сборку MVCDemo.Attributes.Validation.dll из папки Release проекта перенести в lib;
  • папки tools в данном примере не будет.

Описываем спецификацию библиотеки

Теперь необходимо создать описание установочного пакета. Это будет файл в формате XML с именем библиотеки и расширением “.nuspec”. Создадим CustomValidationAttributesLib.nuspec в папке install-package. Его структура достаточно понятная, поэтому давайте сразу посмотрим на пример:

<?xml version="1.0" encoding="utf-8"?> 
<package> 
  <metadata> 
    <id>MVCDemo.Attributes.Validation</id> 
    <version>1.0.0</version> 
    <authors>Andrey Veselov</authors>
    <description>Custom validation attributes for ASP.NET and ASP.NET MVC.</description> 
    <language>en-US</language>
    <licenseUrl>http://andrey.moveax.ru/terms-of-use.aspx</licenseUrl>
    <projectUrl>http://andrey.moveax.ru/</projectUrl>
    <tags>ASP.NET MVC</tags>
  </metadata> 
</package>

Отдельно можно отметить только тег id. Это уникальный идентификатор библиотеки, который должен быть равен имени используемого ей пространства имен. Кроме того, id и номер версии будут использованы для создания имени установочного пакета.

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

Создаем установочный пакет

Запустим “Visual Studio Command Prompt” и перейдем в папку nuget-package. В ней выполним следующую команду (nuget.exe должен быть доступен из командной строки):

nuget pack AdditionalValidationAttributes.nuspec

В результате будет создан установочный пакет “MVCDemo.Attributes.Validation.1.0.0.nupkg”. По формату это zip-файл который можно открыть в любом архиваторе. Кроме того, для их просмотра можно воспользоваться утилитой “NuGet Package Explorer”.

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

Проверка

Для проверки создадим простой ASP.NET MVC 3 проект NuGetMvсDemo. Модель TestModel будет содержать два свойства, для проверки атрибутов из AdditionalValidationAttributes:

namespace NuGetMvсDemo.Models
{
    using System.ComponentModel.DataAnnotations;

    public class TestModel
    {
        [Required]
        [DataType(DataType.MultilineText)]
        public string TextBlock { get; set; }

        public bool BooleanValue { get; set; }        
    }
}

Добавим Контроллер HomeController с единственным Действием Create:

namespace NuGetMvсDemo.Controllers
{
    using System.Web.Mvc;

    public class HomeController : Controller
    {

        // GET: /Home/Create
        public ActionResult Create()
        {
            return View();
        }

        //
        // POST: /Home/Create
        [HttpPost]
        public ActionResult Create(FormCollection collection)
        {
            return View();
        }
    }
}

Теперь необходимо создать строго-типизированное Представление для Действия, используя для этого Модель TestModel и шаблон Create.

Остается только в методе RegisterRoutes() изменить Действие по умолчанию:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new {
            controller = "Home",
            action = "Create",
            id = UrlParameter.Optional
        } // Parameter defaults
    );

}

Можно запустить проект и убедиться что форма выводится без ошибок.

Теперь откроем консоль “Package Manager Console” и установим в качестве текущего источника локальный репозиторий “Local NuGet repository”. Ведем команду “Get-Package -ListAvailable” и получим следующий список:

PM> Get-Package -ListAvailable

Id                             Version              Description                            
--                             -------              -----------                            
Castle.Core                    1.2.0                Core of the castle project             
Castle.DynamicProxy            2.2.0                Castle DynamicProxy is a library for...
log4net                        1.2.10               log4net is a tool to help the progra...
MVCDemo.Attributes.Validation  1.0.0                Custom validation attributes for ASP...
NLog                           1.0.0.505            NLog is a logging platform for .NET ...
NLog                           2.0.0.0              NLog is a logging platform for .NET ...
RazorEngine                    2.1                  A templating engine built upon Micro...

Установим пакет “MVCDemo.Attributes.Validation”:

PM> Install-Package MVCDemo.Attributes.Validation
Successfully installed 'MVCDemo.Attributes.Validation 1.0.0'.
Successfully added 'MVCDemo.Attributes.Validation 1.0.0' to NuGetMvDemo.

Обратите внимание, что в папку Scripts добавилась папка Validation c JavaScript-файлами для проверки данных на стороне клиента. Кроме того, подключена сборка “MVCDemo.Attributes.Validation.dll”. В случае удаления библиотеки все эти изменения будут отменены, а соответствующие файлы стерты.

Изменим Модель и задействуем в ней новые атрибуты проверки данных:

namespace NuGetMvDemo.Models
{
    using System.ComponentModel.DataAnnotations;
    using MVCDemo.Attributes.Validation;

    public class TestModel
    {
        [Required]
        [DataType(DataType.MultilineText)]
        [BlockHtml (ErrorMessage="Html is not allowed.")]
        [StringLengthRange(2,20)]
        public string TextBlock { get; set; }

        [Equal(true, ErrorMessage="Please check this checkbox.")]
        public bool BooleanValue { get; set; }        
    }
}

Так же в Представление необходимо добавить ссылки на JavaScript-файлы:

@model NuGetMvDemo.Models.TestModel
@{
    ViewBag.Title = "Create";
}
<h2>
    Create</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/Validation/BlockHtmlAttribute.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/Validation/EqualAttribute.js")" type="text/javascript"></script>

@using (Html.BeginForm()) {

    .........

Запустим проект и убедимся, что новые атрибуты работоспособны.

Автоматизируем создание установочного пакета

Копировать файлы каждый раз вручную не очень удобно. Конечно можно написать cmd-файл, но есть решение удобнее: спецификация NuGet позволяет указать файлы для включения в пакет. Таким образом, нет необходимости копировать их в папку.

Удалим все, за исключением “CustomValidationAttributesLib.nuspec”, из папки nuget-package. Теперь откроем файл спецификаций и добавим в него список файлов:

<?xml version="1.0" encoding="utf-8"?> 
<package> 
  <metadata> 
    <id>MVCDemo.Attributes.Validation</id> 
    <version>1.0.0</version> 
    <authors>Andrey Veselov</authors>
    <description>Custom validation attributes for ASP.NET and ASP.NET MVC.</description> 
    <language>en-US</language>
    <licenseUrl>http://andrey.moveax.ru/terms-of-use.aspx</licenseUrl>
    <projectUrl>http://andrey.moveax.ru/</projectUrl>
    <tags>ASP.NET MVC</tags>
  </metadata>
  <files>
    <file src="..\MVCDemo.Attributes.Validation\bin\Release*.dll" target="lib" />
    <file src="..\MVCDemo.Attributes.Validation\Scripts\Validation*.js" target="content\Scripts\Validation" />    
  </files>
</package>

Файл или их группа (по маске) задается тегом . Атрибут src определяет откуда их необходимо взять. При этом относительные пути считаются указанными относительно папки, где расположен файл со спецификацией. Второй атрибут target показывает место размещения в установочном пакете.

Важный момент – в этом случае будут использоваться только указанные в спецификации файлы.

В действия после сборки проекта (post-build step) добавим вызов “NuGet Command Line”. При помощи условия поставим ограничение, что установочный пакет будет собираться только вместе с Release версией:

if $(ConfigurationName) == Release "$(DevEnvDir)..\Tools\nuget" pack "$(SolutionDir)nuget-package\CustomValidationAttributesLib.nuspec" /OutputDirectory "$(SolutionDir)nuget-package"

В данной команде используется опциональный параметр OutputDirectory. Он указывает куда сохранить файл созданного установочного пакета. Кроме того, подразумевается что nupack.exe скопирован в папку “Microsoft Visual Studio 10.0\Common7\Tools”.

Соберем проект и убедимся, что при сборке Release-версии в папку nuget-package добавляется “MVCDemo.Attributes.Validation.1.0.0.nupkg”. При необходимости можно настроить публикацию пакета сервер или копирование его в локальный репозиторий.

И в завершении серии, предлагаю ознакомиться с справкой по использованию NuGet. В ней, кроме краткого изложения описанных в серии возможностей, рассмотрен вопрос модификации конфигурационных и исходных файлов проекта. Кроме того, есть инструкция по подключению поддержки nuspec-файлов в Visual Studio IntelliSense.


Исходный код различных вариантов проекта проекта (C#, Visual Studio 2010): Проект исходной демонстрационной библиотеки (10 Kb) Проект с созданием установочного пакета вручную (17 Kb) Проект с автоматическим созданием установочного пакета (11 Kb) Проект тестового ASP.NET MVC проекта (464 Kb)