0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ASP.NET Core Minimal API で EntityFramework を使った PostgreSQL Restful API

Last updated at Posted at 2022-07-28

.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パッケージ。

webapiminimal1.csproj
<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接続文字列を追加。
以下先頭に記述したパターン。

appsettings.json
{
  "ConnectionStrings": {
    "DefaultConnection": "Host=IPもしくはサーバ名;Port=ポート番号;Database=データベース名;User Id=ユーザ名;Password=パスワード"
  },
  "//":"以下省略"
}
appsettings.Development.json
{
  "ConnectionStrings": {
    "DefaultConnection": "Host=IPもしくはサーバ名;Port=ポート番号;Database=データベース名;User Id=ユーザ名;Password=パスワード"
  },
  "//":"以下省略"
}

モデル作成

Modelフォルダを作ってからファイル作成してもいいし、プロジェクトルートでも良い。
モデルを作成しつつ、DbContextも同一ファイルで定義して問題ない。

ファイル名はPostgreSQLでのテーブル名称(大文字小文字含め)に合わせると管理がラク。

recordでスキーマを定義する場合、DbSetで定義するオブジェクトとテーブル名称の一致が必要(コメントアウト箇所)。DataAnnotationsでスキーマ属性を使用すれば、制約解除できる。

member.cs
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 に記述する。

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別の一覧、下部はモデル定義したスキーマ一覧。
swagger1.png

POSTメソッドであれば、 Try it out を押下してで内容を展開する。
swagger2.png

モデルに従ってJSON形式で内容を記述して、Excute を押下。
swagger4.png

バックグラウンドでの curl 実行内容やサーバレスポンスが確認できる。
swagger5.png

関連ページ

jQuery AJAXでJSON取得

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?