LoginSignup
5
4

More than 3 years have passed since last update.

macOSでASP .NET Coreを使ってAPIサーバをHerokuにデプロイする

Last updated at Posted at 2020-07-31

macOSで.NET Coreを使ってAPIサーバをHerokuにデプロイするまでの手順をまとめます。

前提条件

実行環境は macOS Catalina です。
以下のツールはインストール済みとします。

  • VS Code
  • Docker

何を作るの?

シンプルなTodo管理APIサーバを構築します。データはデータベースに保存します。

.NET Core macOS版のインストール

Microsoftのウェブサイトからダウンロードしてインストールします。

必要な.NETツールをインストール

dotnet tool install --global dotnet-aspnet-codegenerator
dotnet tool install --global dotnet-ef

プロジェクトの作成

webapiテンプレートを使ってプロジェクトを作成します。
--no-httpsをつけないと、デフォルトでlocalhostの証明書を作る流れになってややこしくなります。

dotnet new webapi -o TodoApi --no-https

初期パッケージのインストール

Entity Framework Coreを使って、データベースへの書き込みを実現するので、以下のようにパッケージをインストールします。
ただ、今回はSQLiteだけ使うので、Microsoft.EntityFrameworkCore.Sqlite だけインストールしても問題ありません。

cd TodoApi
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Sqlite
dotnet add package Microsoft.EntityFrameworkCore.InMemory

初回起動

dotnet run で起動できます。

dotnet run

info: Microsoft.Hosting.Lifetime[0]
      Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /Users/XXXXX/TodoApi

その後、curlを以下のように実行するとテンプレートの初期設定であるWeatherForecastの情報が取得できます。

curl http://localhost:5000/WeatherForecast

次のようなJSONが返されます。

[
   {
      "date" : "2020-08-01T08:48:53.47458+09:00",
      "summary" : "Mild",
      "temperatureC" : 39,
      "temperatureF" : 102
   },
   {
      "date" : "2020-08-02T08:48:53.474598+09:00",
      "summary" : "Mild",
      "temperatureC" : -20,
      "temperatureF" : -3
   },
   {
      "date" : "2020-08-03T08:48:53.474609+09:00",
      "summary" : "Scorching",
      "temperatureC" : 47,
      "temperatureF" : 116
   },
   {
      "date" : "2020-08-04T08:48:53.474619+09:00",
      "summary" : "Scorching",
      "temperatureC" : 54,
      "temperatureF" : 129
   },
   {
      "date" : "2020-08-05T08:48:53.474629+09:00",
      "summary" : "Sweltering",
      "temperatureC" : 39,
      "temperatureF" : 102
   }
]

モデルクラス TodoItem の追加

以下のようにTodoItem.csファイルをModelsフォルダの下に作成します。

TodoItem.cs
public class TodoItem
{
    public long Id { get; set; }
    public string Name { get; set; }
    public bool IsComplete { get; set; }
}

データベースコンテキストの追加

同様にModelsフォルダの下にTodoContext.csを作成します。

TodoContext.cs
using Microsoft.EntityFrameworkCore;

namespace TodoApi.Models
{
    public class TodoContext : DbContext
    {
        public TodoContext(DbContextOptions<TodoContext> options)
            : base(options)
        {
        }

        public DbSet<TodoItem> TodoItems { get; set; }
    }
}

Startup.cs を修正

Startup.csを以下のように修正します。ここで先ほど作成したモデルクラスやデータベースコンテキストを登録します。
今回は、SQLiteを使うのでそれ以外をコメントアウトしています。

Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

// 追加
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;

namespace TodoApi
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<TodoContext>(opt =>
                //opt.UseInMemoryDatabase("TodoList"));
                opt.UseSqlite("Filename=db.sqlite3"));  // 今回はこれを使う。 SQLiteのファイル名は db.sqlite3
                //opt.UseNpgsql("Host=localhost;Database=mydb;Port=15432;Username=user;Password=password")); // PosgreSQL
                //opt.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); // SQL Server

            services.AddControllers();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

コントローラを生成

必要なパッケージを追加します。

dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet add package Microsoft.EntityFrameworkCore.Design

コントローラTodoItemsControllerを生成します。

dotnet aspnet-codegenerator controller -name TodoItemsController -async -api -m TodoItem -dc TodoContext -outDir Controllers

この状態で自動的にTodoItemのCRUD APIが実装されます。

データベースマイグレーションとデータベースの更新

dotnet ef migrations add <どんな変更を加えたのかを表す任意の名称>という形でマイグレーションを作成します。
dotnet ef database updateでデータベースを更新します。

dotnet ef migrations add InitialCreate
dotnet ef database update

APIを試してみる

dotnet runでサーバを起動します。

POSTのテスト

curl -X POST \
     -H "Content-Type:application/json" \
     -d '{"Name":"Task 01", "IsComplete":false}' \
     http://localhost:5000/api/TodoItems

curl -X POST \
     -H "Content-Type:application/json" \
     -d '{"Name":"Task 02", "IsComplete":false}' \
     http://localhost:5000/api/TodoItems

GETのテスト:一覧取得

curl http://localhost:5000/api/TodoItems
[{"id":1,"name":"Task 01","isComplete":false},{"id":2,"name":"Task 02","isComplete":false}]

PUTのテスト

curl -X PUT \
     -H "Content-Type:application/json" \
     -d '{"Id":2, "IsComplete":true}' \
     http://localhost:5000/api/TodoItems/2

GETのテスト:特定レコードの取得

curl http://localhost:5000/api/TodoItems/2
{"id":2,"name":"Task 02","isComplete":true}

DELETEのテスト

curl -X DELETE \
     -H "Content-Type:application/json" \
     http://localhost:5000/api/TodoItems/2
{"id":2,"name":"Task 02","isComplete":true}

TodoItemにカラムを追加

以下のようにTodoItemCreatedAtを追加します。

TodoItem.cs
using System;  // 追加

public class TodoItem
{
    public long Id { get; set; }
    public string Name { get; set; }
    public bool IsComplete { get; set; }
    public DateTime CreatedAt { get; set; } // 追加
}

以下のようにマイグレーションを実行します。

dotnet ef migrations add AddDateColumn
dotnet ef database update

データベースが更新されたことを確認

sqlite db.sqlite3
sqlite> PRAGMA table_info('TodoItems');
0|Id|INTEGER|1||1
1|Name|TEXT|0||0
2|IsComplete|INTEGER|1||0
3|CreatedAt|TEXT|1|'0001-01-01 00:00:00'|0
sqlite> 

Herokuへデプロイ

以下のようなDockerfileを作ります。

Dockerfile
FROM mcr.microsoft.com/dotnet/core/aspnet

COPY bin/Release/netcoreapp3.1/publish/ App/
WORKDIR /App

CMD export ASPNETCORE_URLS=http://0.0.0.0:$PORT; dotnet TodoApi.dll

デプロイファイルを生成します。
bin/Release/netcoreapp3.1/ 配下にリリースようファイル群が生成されます。

dotnet publish -c Release

Herokuのインスタンスを作成して、Dockerfileをpush & releaseします。

heroku create 
heroku container:login
heroku container:push web --app <appName>
heroku container:release web --app <appName>

参考

チュートリアル: ASP.NET Core で Web API を作成する
https://docs.microsoft.com/ja-jp/aspnet/core/tutorials/first-web-api?view=aspnetcore-3.1&tabs=visual-studio-code#prerequisites

チュートリアル: 移行機能の使用 - ASP.NET MVC と EF Core
https://docs.microsoft.com/ja-jp/aspnet/core/data/ef-mvc/migrations?view=aspnetcore-3.1

チュートリアル: JavaScript を使用して ASP.NET Core Web API を呼び出す
https://docs.microsoft.com/ja-jp/aspnet/core/tutorials/web-api-javascript?view=aspnetcore-3.1

ASP.NET Core を使って Web API を作成する
https://docs.microsoft.com/ja-jp/aspnet/core/web-api/?view=aspnetcore-3.1

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4