.NET6 から導入された Minimal APIの資料が少なかったため、海外サイトで調べたものをまとめてみる。
更新履歴
2022/8/1
クロスサイトスクリプティング対応(CORS対応)
各種インストール
.NET6、PostgreSQLのインストール方法は省略
テーブル
小さなテーブルをテスト用に作成
# create table member (id serial, name text, primary key (id));
# \d member
Table "member"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+----------------------------------
id | integer | | not null | nextval('member_id_seq'::regclass)
name | text | | |
Indexes:
"member_pkey" PRIMARY KEY, btree (id)
プロジェクト作成〜パッケージ追加
web
オプションで作成するとSwaggerなし、webapi -minimal
オプションで作成するとSwaggerとWeatherForecastありのテンプレートからプロジェクトが作成される。以下 Web画面からRESTのテストをするため、Swaggerありをベースに WeatherForecastを削除して作成。
Swaggerあり
dotnet new webapi -minimal -o webapiminimal1
Swaggerなし
dotnet new web -o webapiminimal1
続けてプロジェクトフォルダへ移動して、パッケージを追加
cd webapiminimal1
dotnet add package Microsoft.EntityFrameworkCore --version 6.0.7
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL --version 6.0.5
プロジェクトファイル(確認のみ)
パッケージ追加による必要な記述は自動的に行われるため確認のみ。
最終行の Swashbuckle は Swaggerパッケージ。
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.1" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.2" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
</ItemGroup>
</Project>
アプリケーション設定
デバッグとリリース、それぞれの設定ファイルに PostgreSQL接続文字列を追加。
以下先頭に記述したパターン。
{
"ConnectionStrings": {
"DefaultConnection": "Host=IPもしくはサーバ名;Port=ポート番号;Database=データベース名;User Id=ユーザ名;Password=パスワード"
},
"//":"以下省略"
}
{
"ConnectionStrings": {
"DefaultConnection": "Host=IPもしくはサーバ名;Port=ポート番号;Database=データベース名;User Id=ユーザ名;Password=パスワード"
},
"//":"以下省略"
}
モデル作成
Modelフォルダを作ってからファイル作成してもいいし、プロジェクトルートでも良い。
モデルを作成しつつ、DbContextも同一ファイルで定義して問題ない。
ファイル名はPostgreSQLでのテーブル名称(大文字小文字含め)に合わせると管理がラク。
recordでスキーマを定義する場合、DbSetで定義するオブジェクトとテーブル名称の一致が必要(コメントアウト箇所)。DataAnnotationsでスキーマ属性を使用すれば、制約解除できる。
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
public class tblMember : DbContext
{
public tblMember(DbContextOptions<tblMember> options) : base(options) { }
// public DbSet<Member> member => Set<Member>();
public DbSet<Member> members => Set<Member>();
}
// public record Member(int id)
// {
// public string? name { get; set; }
// }
[Table("member", Schema = "スキーマ")]
public class Member
{
[Key]
[Column("id")]
public int id{ get; set; }
[Column("name")]
public string? name{ get; set; }
}
プログラムメイン
Minimal API では、Startup.csを使わず、全て Program.cs に記述する。
using Microsoft.EntityFrameworkCore;
// Webアプリケーションビルダー
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// CORS(Cross-Origin Resource Sharing)対応
var AllowSpecificOrigins = "_allowSpecificOrigins";
builder.Services.AddCors(options =>
{
options.AddPolicy(name: AllowSpecificOrigins, policy =>
{
policy.WithOrigins("https://アクセス元IPもしくはサーバ名:ポート").AllowAnyHeader().AllowAnyMethod();
});
});
// サービス追加(Npgsql, 接続文字列は appsettings.json から読み取り)
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<tblMember>(options => options.UseNpgsql(connectionString));
// Webアプリをビルド
var app = builder.Build();
// 開発用のRESTインターフェース
if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); }
// CORS有効化
app.UseCors(AllowSpecificOrigins);
// ルーティング
// GET(1) ※CORS対応
app.MapGet("/member", async (tblMember tbl) => await tbl.members.ToListAsync()).RequireCors(AllowSpecificOrigins);
// GET(2) ※CORS対応
app.MapGet("/member/{id:int}", async (int id, tblMember tbl) =>
{
return await tbl.members.FindAsync(id) is Member r ? Results.Ok(r) : Results.NotFound();
}).RequireCors(AllowSpecificOrigins);
// GET(3) ※ページング処理用(WhereとSkipとTakeは実際の要件で実装合わせ込みが必要)
app.MapGet("/memberList", async (tblMember tbl) =>
{
return await tbl.members
.Where(a => a.id < 6)
.OrderByDescending(a => a.id)
.Skip(2) // SQLでのOFFSET
.Take(2) // SQLでのLIMIT
.ToListAsync();
}).RequireCors(AllowSpecificOrigins);
// PUT ※CORS非対応(必要ならRequireCorsする)
app.MapPut("/member/{id:int}", async (int id, Member r, tblMember tbl) =>
{
if (r.id != id) return Results.BadRequest();
var record = await tbl.members.FindAsync(id);
if (record is null) return Results.NotFound();
record.name = r.name;
await tbl.SaveChangesAsync();
return Results.Ok(record);
});
// POST ※CORS非対応(必要ならRequireCorsする)
app.MapPost("/member/", async (Member r, tblMember tbl) =>
{
tbl.members.Add(r);
await tbl.SaveChangesAsync();
return Results.Created($"/member/{r.id}", r);
});
// DELETE ※CORS非対応(必要ならRequireCorsする)
app.MapDelete("/member/{id:int}", async (int id, tblMember tbl) =>
{
var record = await tbl.members.FindAsync(id);
if (record is not null)
{
tbl.members.Remove(record);
await tbl.SaveChangesAsync();
}
return Results.NoContent();
});
// GET(3) Webサイトルート ※CORS対応不要
app.MapGet("/", () => "ASP.NET Core Minimal API");
// 起動
app.Run();
デバッグ実行
dotnet watch run
で、ホットリロードありにして、https://IPアドレス:動的ポート/Swagger/ で RESTの動作確認をしながら進めるとラク。
Swagger上部はルーティングで定義したREST別の一覧、下部はモデル定義したスキーマ一覧。
POSTメソッドであれば、 Try it out
を押下してで内容を展開する。
モデルに従ってJSON形式で内容を記述して、Excute
を押下。
バックグラウンドでの curl 実行内容やサーバレスポンスが確認できる。