.NET Standard パッケージを Azure Artifacts へ公開

# 背景

.NET Core または .NET Framework の共通ライブラリとして .NET Standard 基盤ライブラリを作成し、プライベートな NuGet パッケージを Azure Artifacts へ公開して Azure Artifacts で配信確認する手順をメモしておきます。

## .NET Standard とは

.NET Standard に従って作成された API は、.NET Framework、.NET Core、Xamarin といった全ての .NET 実装において、共通となるクラスライブラリを提供します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/e8ee6861-b8f9-6268-f7b9-b3d90026d232.png)

## Azure Artifacts とは

Azure DevOps が提供しているサービスの一つです。
詳しい内容はこちらのリンクを参考してください。

[Azure DevOps を完全理解する 目次](https://qiita.com/ymasaoka/items/c43ac02e0bc9cbdadd65)


# 環境

- Windows 10 Version 1709 以上
- Visual Studio 2019 Community 以上
    - [こちらでダウンロード](https://visualstudio.microsoft.com/ja/downloads/)
    - プロジェクト形式をSDKスタイルで作成できます。
- .NET Core 3.1 (v3.1.8)
    - [こちらでダウンロード](https://dotnet.microsoft.com/download/dotnet-core/3.1)

# .NET Standard ライブラリ作成と Azure Artifacts へ公開

## パッケージ名の識別子

`Company.HelloWorld.v1`というパッケージの識別子で作成したいので、公開してあるパッケージが存在するか確認しておきます。重複しているパッケージがなくても作れない場合があります。（プライベートとして登録など）
識別子は大文字と小文字が区別され、nuget.org 全体で一意である必要があります。

https://www.nuget.org/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/43150dd0-0216-e754-ef46-09816de0d686.png)

## Azure Artifacts で Feed 作成

Azure DevOps 画面の Artifacts をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/6375ec5b-31ab-b1fb-a3f0-363dc40194d4.png)

Create Feed をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/224ce767-7315-dabc-449a-27197f7e8f21.png)

Feed 名を入力して他にはデフォルトにしておきます。
デフォルトでは Azure AD のメンバーと Azure DevOps プロジェクト範囲で公開し、Upstream sourcesで取得したパッケージはArtifect内にキャッシュされ、安定運用できる設定です。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/5974503a-4721-44d5-1f5d-2df8bc03430c.png)

Connect to feed をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/853a959d-5523-4e2a-897c-ada8e6a3b495.png)

Visual Studio で接続するので Visual Studio をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/114384d8-8233-6c53-9caf-17719908f38b.png)

下記のようにマシンセットアップがでたら、次の Visual Studio で設定するのでメモしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/db590dfe-faa1-d257-7570-1aa7eb143eab.png)

もし、下記のようにソースの項目でURLが正しく表示されない場合は、画面を再度、開いてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/1d0caea4-e6b5-cf27-07c1-8733a3aba227.png)


## .NET Standard クラスライブラリのプロジェクト作成

「.NET Standard クラスライブラリ」の新しいプロジェクトを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/bead5794-9dc9-72a0-d1a7-c6e0d1b7ebe5.png)

ソリューションを含めた形でプロジェクト名とソリューション名を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/d6c9ab38-40cf-e5c9-d4ad-79ebe5b5109d.png)

公開するのでモードをReleaseに変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/da242523-d1a6-0c90-029d-75c6bde63b00.png)

プロジェクトのプロパティを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/35797173-4c37-703f-a11b-cce36c7e9946.png)

アプリケーションメニューでは対象のプレームワークを選択しておきます。デフォルトでは`2.0`ですが、最新は`2.1`です。
バージョンごとの互換性はMicrosoftのドキュメントを参照してください。
[.NET 実装のサポート](https://docs.microsoft.com/ja-jp/dotnet/standard/net-standard#net-implementation-support)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/80393e21-1b23-54d4-0570-b4e2c7ec57b1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/0e216abe-5575-bbaa-27e8-4ffba1475590.png)

ビルドメニューでは`XMLドキュメントファイル`をチェックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/85517c6e-68e1-6411-f7bd-84fa71ec367a.png)

パッケージメニューでは`ビルドで NuGet パッケージを生成`をチェックして他にパッケージ情報など修正しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/67a2b6da-19df-964b-7edc-57c6732e176d.png)


## Visual Studio で NuGet パッケージソース登録

Visual Studio で 「ツール > NuGetパッケージマネージャー > パッケージマネージャー設定」 選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/52393cb7-d39a-a932-43c7-0b827bc32ea1.png)

「パッケージソース > プラスボタン」をクリックして先ほど、メモしておいたVisual Studioのマシンセットアップの名前とソース情報を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/a787b6d7-6cba-2a96-2970-713bfbe5e0b6.png)


## .NET Standard クラスライブラリ作成

サンプルソースコードの入力し、ソースファイル名を変更します。
ソース内容はコンストラクタが呼び出される際にコンソール出力する簡単なコードです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/5c9d708c-b2ad-dffa-8782-2d112eeedd6c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/50e8779b-afc0-025b-2278-b92dbc04c1ca.png)

```csharp
using System;

namespace Company.HelloWorld.v1
{
    public class HelloWorld
    {
        /// <summary>
        /// HelloWorldサマリー
        /// </summary>
        public HelloWorld()
        {
            Console.WriteLine("HelloWorldコンストラクタ");
        }
    }
}
```

ビルドします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/a717287a-3f10-d647-3121-626841ebf6e0.png)

`エクスプローラーでフォルダーを開く`選択してプロジェクトフォルダー移動し、`bin\Release`配下にパッケージファイルが存在しているか確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/55a9b231-c1ac-f449-cbd8-7625cfda8ba0.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/2c531ae3-357b-0b68-e017-8f619a0cf840.png)


## Azure Artifacts へ公開

Azure DevOps の Artifacts で再度、`Connect to feed`をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/b9690cb7-9a86-4af5-d758-5e02537bf3d7.png)

`NuGet.exe`をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/6abb993a-3af5-f591-7a3e-01fa90dedad4.png)

`Get the tools`をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/715151bb-ebf1-c9b2-ac85-205540d2e9e2.png)

`Download the latest NuGet`をクリックして最新バージョンをプロジェクトフォルダーにダウンロードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/cd7285f5-bf15-8828-d358-a199fed408fc.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/a1d6ec73-7da4-563e-e55e-ff7732696e20.png)

Visual Studio で`NuGet.Config`というファイルを`新しい項目`を選択して追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/b04e4e07-668a-0bda-16dc-07658808df33.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/4ca11c2d-2da1-9e54-8ae8-ad7c6c58b9b4.png)

ファイル中身を先ほど、Azure Artifacts の NuGet 内容をそのまま入力しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/bfe2daaf-9239-0ee1-82eb-95e7259d22f8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/8c29e328-8a5e-fe67-4eef-45fb9509e5f5.png)

ここまでするとプロジェクトフォルダーでは下記のファイルが存在します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/1b3d3b0e-7774-25c1-cc4a-f48e9e5c09d8.png)

コマンドプロンプトを起動し、プロジェクトフォルダーまで移動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/92337732-238f-a6c7-734a-b237c9aed5aa.png)

最初のみですが、下記のようなコマンドでパッケージを復旧します。

```terminal
> nuget.exe restore Company.HelloWorld.v1.csproj
```

下記のような Azure Artifacts へ公開します。

```terminal
> nuget.exe push -Source "MyFirstHelloWorld" -ApiKey az "<Company.HelloWorld.v1.1.0.0.nupkgパス>"
```

ここで認証が行われます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/a8716b33-7630-9902-51c6-284d5b448af5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/a93d4e3f-51ea-dd23-1e8e-5da4ca66aba0.png)

Azure Artifacts 画面に`Company.HelloWorld.v1`が現れたら成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/c1dc9261-1ffa-db47-fa21-b09b56e5a280.png)

# Azure Artifacts で配信確認

## .NET Core コンソールアプリで確認

既存ソリューションから新しいプロジェクトを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/ea55d7ab-988d-7b3b-b595-fc43d51d4c96.png)

.NET Core コンソールアプリを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/a4170bac-000b-6280-29c6-6a6cb5fe8e30.png)

プロジェクト情報を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/85d66057-72a5-ba90-58fb-e951f1d5bea0.png)

NuGet パッケージの管理を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/14a0c5d5-6e4d-f32d-f791-18580f94afc6.png)

パッケージソースを Azure Artifacts で作成した Feed 名に変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/8394ef3d-f17d-9844-58b9-2c1e0a3bf14f.png)

公開したパッケージ`Company.HelloWorld.v1`を選択し、インストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/ebf0b38a-e23e-1251-a5fc-c280dc8125cf.png)

デフォルトソースコードを修正します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/13b9b0cc-120f-ed06-d18f-7bffab1f74e2.png)

```csharp
using System;
using Company.HelloWorld.v1;

namespace ConsoleApp4NetCore
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            var helloworld = new HelloWorld();
            Console.ReadKey();
        }
    }
}
```

ビルドして確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/519ee338-c3c9-82e7-8113-ace20a6e89fe.png)


## .NET Framework コンソールアプリで確認

既存ソリューションから新しいプロジェクトを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/ea55d7ab-988d-7b3b-b595-fc43d51d4c96.png)

.NET Framework コンソールアプリを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/45730b5c-4728-01bd-c2a3-6abd11019109.png)

プロジェクト情報を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/2f2de127-f05e-5622-450b-6c4f82bf97b0.png)

NuGet パッケージの管理を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/14a0c5d5-6e4d-f32d-f791-18580f94afc6.png)

パッケージソースを Azure Artifacts で作成した Feed 名に変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/8394ef3d-f17d-9844-58b9-2c1e0a3bf14f.png)

公開したパッケージ`Company.HelloWorld.v1`を選択し、インストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/ebf0b38a-e23e-1251-a5fc-c280dc8125cf.png)

デフォルトソースコードを修正します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/4de12046-8f04-363c-88b9-0586f266f24b.png)

```csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Company.HelloWorld.v1;

namespace ConsoleAppNetFramework
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            var helloworld = new HelloWorld();
            Console.ReadKey();
        }
    }
}
```

ビルドして確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/519ee338-c3c9-82e7-8113-ace20a6e89fe.png)

# まとめ

筆者は Blazor プロジェクトにてビジネスロジックをパッケージ化するのに Azure Artifacts を使っています。言うまでもないですが、 Azure DevOps の他のサービス(Boards, Repos, Pipelines, Test Plans)を連携することでさらに力を発揮します。