ASP.NET Core のチュートリアルで少しハマった話

こんにちは。エクセルソフトの田淵です。

### 発端

[ASP\.NET Core で Razor ページ Web アプリを作成する \| Microsoft Docs](https://docs.microsoft.com/ja-jp/aspnet/core/tutorials/razor-pages/?view=aspnetcore-2.0)

このチュートリアルを ASP.NET Core 2.0 でやっていて、モデルの追加まで来ました。

> 2018/6/19 現在のこのエントリーを書いている最中に [ASP.NET Core 2.1 が GA していた](https://www.microsoft.com/net/download/visual-studio-sdks) ことを知りました笑
> 2.1 でやり直します…

[ASP\.NET Core での Razor ページ アプリへのモデルの追加 \| Microsoft Docs](https://docs.microsoft.com/ja-jp/aspnet/core/tutorials/razor-pages/model?view=aspnetcore-2.0)

EntityFramworkCore 2.0 を使って作業をしていて、「データベース接続文字列の追加」の部分で

<img width="650" alt="Surface_2018-06-19 18_45_01.png" src="https://qiita-image-store.s3.amazonaws.com/0/32453/966a5f03-6068-63dd-e97d-4d4944ea0c66.png">

という記述があったので、`appsettings.json` に次のように記載しました。（ふむふむ、Logging の **下ね** という理解）

```json
{
  "Logging": {
    "IncludeScopes": false,
    "Debug": {
      "LogLevel": {
        "Default": "Warning"
      }
    },
    "ConnectionStrings": {
      "MovieContext": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true"
    },
    "Console": {
      "LogLevel": {
        "Default": "Warning"
      }
    }
  }
}
```

これが大失敗。そのまま次の手順に進み「データベース コンテキストの登録」をやって、その次の手順「スキャフォールディング ツールの追加と初期移行の実行」で

```
Install-Package Microsoft.VisualStudio.Web.CodeGeneration.Design -Version 2.0.3
Add-Migration Initial
Update-Database
```

をパッケージマネージャーから入れろというのでパッケージをインストールして、`Add-Migration Initial` をやったら以下のエラーががが。。

```
System.ArgumentNullException: Value cannot be null.
Parameter name: connectionString
   at Microsoft.EntityFrameworkCore.Utilities.Check.NotEmpty(String value, String parameterName)
   at Microsoft.EntityFrameworkCore.SqlServerDbContextOptionsExtensions.UseSqlServer(DbContextOptionsBuilder optionsBuilder, String connectionString, Action`1 sqlServerOptionsAction)
   at ITStudySearch.WebApi.Startup.<ConfigureServices>b__4_0(DbContextOptionsBuilder options) in D:\_dev\BitBucket\itstudysearch\ITStudySearch\ITStudySearch.WebApi\Startup.cs:line 32
   at Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.DbContextOptionsFactory[TContext](IServiceProvider applicationServiceProvider, Action`2 optionsAction)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitIEnumerable(IEnumerableCallSite enumerableCallSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.FindContextTypes()
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.FindContextType(String name)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_1.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Value cannot be null.
Parameter name: connectionString
```

ぬぬぬぬ？？？？ということで、

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">この手順にあるPackage Managerでの「Add-Migration Initial」で引数はNullにできないってエラーが出る。が、解決方法が分からない。（初めてやる時はこんな感じなんですね。 ＞ <a href="https://t.co/lODVMznfVC">https://t.co/lODVMznfVC</a> Core での Razor ページ アプリへのモデルの追加 | Microsoft Docs: <a href="https://t.co/OXWg7PrysH">https://t.co/OXWg7PrysH</a></p>&mdash; 田淵 義人＠エクセルソフト (@ytabuchi) <a href="https://twitter.com/ytabuchi/status/1008641781703905281?ref_src=twsrc%5Etfw">2018年6月18日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


呟いたら [@beach_side](https://twitter.com/beach_side) さんが助けてくれました。

> ConnectionString取れないなら、appsettings.jsonで、接続文字列書く場所（セクション)が間違えてるとか？
> よくあるのは、Logging セクションの中に書いてるとか...

Logging セクションの中… だと…？

その通りでした。

正解は以下でした。お恥ずかしいですが、画像の見た目に騙されてしまいました。

```json
{
  "Logging": {
    "IncludeScopes": false,
    "Debug": {
      "LogLevel": {
        "Default": "Warning"
      }
    },
    "Console": {
      "LogLevel": {
        "Default": "Warning"
      }
    }
  },
  "ConnectionStrings": {
    "MovieContext": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}
```


### 教訓

JSON を触る時は Visual Studio や IDE で対になっている `{}` や `[]` がハイライトされて分かるようになっていると思うので、編集する場所を間違えないようにしよう。

です。



以上です。