APIへのバリデーション統合
わかりやすいバリデーションエラーレスポンスを返します。
「APIへのバリデーション統合」はCoddyKit上の無料C# Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC# Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C# Academyコースには全4レッスンが含まれています。
FluentValidation の ASP.NET Core への組み込み
リクエストを自動的に検証するには、依存性注入にバリデーターを登録します。AddValidatorsFromAssembly ヘルパーはアセンブリをスキャンし、見つかったすべてのバリデーターを登録します。
using FluentValidation;
builder.Services
.AddValidatorsFromAssemblyContaining<CustomerValidator>();自動検証ミドルウェア
最近の FluentValidation では明示的な検証が推奨されますが、モデルバインディングにフックする自動検証を有効にして、アクションが実行される前に無効なリクエストを拒否することもできます。
dotnet add package FluentValidation.AspNetCore
builder.Services.AddFluentValidationAutoValidation();DI から解決されるバリデーター
バリデーターは DI に登録されるため、リポジトリなどのサービスを注入できます。これにより、データベースを利用する非同期ルールを API でシームレスに動作させられます。
public class UserValidator : AbstractValidator<UserRequest>
{
public UserValidator(IUserRepository repo)
{
RuleFor(u => u.Email)
.MustAsync(async (e, ct) => !await repo.ExistsAsync(e));
}
}エンドポイントでの明示的な検証
明確さを重視して、明示的な検証を好むチームは少なくありません。IValidator<T> を注入し、ハンドラーの先頭で呼び出します。
app.MapPost("/users", async (
UserRequest request,
IValidator<UserRequest> validator) =>
{
var result = await validator.ValidateAsync(request);
if (!result.IsValid)
return Results.ValidationProblem(result.ToDictionary());
return Results.Ok();
});ProblemDetails とは
ProblemDetails(RFC 7807)は、HTTP エラーレスポンス用の標準 JSON 形式です。type、title、status、detail などのフィールドを持ち、クライアントが予測しやすいエラー形式を提供します。
{
"type": "https://tools.ietf.org/html/rfc7231",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": { "Email": ["Email is required."] }
}ValidationProblemDetails
検証に失敗した場合、ASP.NET Core は ValidationProblemDetails を使用します。これは ProblemDetails を拡張し、各フィールドとそのメッセージを対応付ける errors ディクショナリを追加したものです。
return Results.ValidationProblem(result.ToDictionary());
// Produces a 400 ValidationProblemDetails responseFluentValidation の結果の変換
ToDictionary() 拡張メソッドは、ValidationResult を ValidationProblem が想定する field -> messages ディクショナリに変換します。
var result = await validator.ValidateAsync(request);
if (!result.IsValid)
{
IDictionary<string, string[]> errors = result.ToDictionary();
return Results.ValidationProblem(errors);
}ProblemDetails 出力のカスタマイズ
AddProblemDetails とカスタマイザーを使うと、すべてのエラーレスポンスを拡張できます。たとえば、デバッグ用のトレース ID を追加できます。
builder.Services.AddProblemDetails(options =>
{
options.CustomizeProblemDetails = ctx =>
ctx.ProblemDetails.Extensions["traceId"] =
ctx.HttpContext.TraceIdentifier;
});MVC コントローラーでのバリデーション
自動バリデーションを有効にし、[ApiController]を使用すると、リクエストが無効な場合にコントローラーアクションも自動的に ValidationProblemDetails を返すため、すべてのエンドポイントで形式を統一できます。
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
[HttpPost]
public IActionResult Create(UserRequest request) => Ok();
}Minimal API 用のバリデーションフィルター
エンドポイントフィルターを使うと明示的なバリデーションを一元化できるため、各ハンドラーをすっきり保てます。
app.MapPost("/users", (UserRequest r) => Results.Ok())
.AddEndpointFilter<ValidationFilter<UserRequest>>();自動バリデーションと明示的なバリデーションの選択
自動バリデーションは便利ですが、バリデーションの手順が見えにくくなります。明示的なバリデーションは冗長ですが、処理が明確でテストもしやすくなります。両方の利点を得るために、明示的なバリデーションと共有フィルターを組み合わせるチームも多くあります。
確認テスト
API のバリデーション統合をテストします。
まとめ
バリデーションを統合するには、AddValidatorsFromAssemblyでバリデーターを登録し、必要に応じて自動バリデーションを有効にして、Results.ValidationProblem(result.ToDictionary())を使ってエラーをValidationProblemDetailsとして返します。DI によってバリデーターで非同期ルールにリポジトリを利用でき、ProblemDetails をカスタマイズしたり、エンドポイントフィルターを使ってハンドラーをすっきり保ったりすることもできます。
よくある質問
「APIへのバリデーション統合」レッスンは無料ですか?
はい。「APIへのバリデーション統合」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C# Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C# Academyコースには全4レッスンが含まれています。
「APIへのバリデーション統合」で何を学びますか?
わかりやすいバリデーションエラーレスポンスを返します。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C# Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC# Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「APIへのバリデーション統合」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC# Academyレッスンでコードを書いて実行できますか?
はい。すべてのC# Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。