.NET CLI を使用したプロジェクトの初期設定から、ミドルウェア、コントローラー、サービスの構成まで、堅牢な API を構築するためのすべての手順を学びます。スケーラブルで効率的な Web アプリケーションを作成するための、依存関係の挿入、非同期アクション、例外処理のベスト プラクティスを発見します。
.NET CLI を使用して、新しい Web API プロジェクトを作成します。これにより、例として起動用の Program.cs と WeatherForecast コントローラーを含む基本的なプロジェクト構造がセットアップされます。
dotnet new webapi -n MyWebApi
.NET 8 では、API を最小限にする傾向が続いており、Program.cs ファイルで直接、簡略化された簡潔な方法でサービスとエンドポイントを構成できるようになります。
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet("/", () => "Hello, World!"); app.Run();
コントローラーは受信した HTTP リクエストを処理し、クライアントに応答します。これらは、ControllerBase を継承し、[ApiController] でアノテーションを付けることによって定義されます。
[ApiController] [Route("[controller]")] public class MyController : ControllerBase { [HttpGet] public IActionResult Get() => Ok("Hello from MyController"); }
.NET Core の組み込みの依存関係注入 (DI) により、依存関係の管理が簡単になります。コンストラクターを通じてコントローラーにサービスを注入できます。
public class MyService { public string GetMessage() => "Injected message"; } public class MyController : ControllerBase { private readonly MyService _myService; public MyController(MyService myService) { _myService = myService; } [HttpGet] public IActionResult Get() => Ok(_myService.GetMessage()); }
サービス (データベース コンテキスト、カスタム サービスなど) は Program.cs ファイルで構成され、アプリケーション全体で依存関係の注入に使用できるようになります。
builder.Services.AddScoped<MyService>();
.NET は環境固有の構成ファイル (appsettings.json、appsettings.Development.json など) をサポートしており、アプリケーションの環境に基づいてさまざまな設定が可能です。
// appsettings.Development.json { "Logging": { "LogLevel": { "Default": "Debug" } } }
ミドルウェア コンポーネントは、リクエストと応答を処理するパイプラインを形成します。カスタム ミドルウェアは、ロギングやエラー処理などの横断的な問題に対応して作成できます。
app.Use(async (context, next) => { // Custom logic before passing to the next middleware await next(); // Custom logic after executing the next middleware });
.NET Web API のルーティングは、コントローラーとアクション メソッドの属性ルーティングによって実現されます。これにより、URL をコントローラーのアクションに直接マッピングできるようになります。
[HttpGet("myaction/{id}")] public IActionResult GetAction(int id) => Ok($"Action with ID = {id}");
モデル バインディングは、HTTP リクエストのデータをアクション メソッドのパラメーターに自動的にマッピングします。 JSON 本文やクエリ文字列パラメーターを含む複合型をサポートします。
public class MyModel { public int Id { get; set; } public string Name { get; set; } } [HttpPost] public IActionResult PostAction([FromBody] MyModel model) => Ok(model);
データ アノテーションを使用してモデル データを検証できます。 [ApiController] 属性は検証を自動的に実施し、モデルが無効な場合は 400 で応答します。
public class MyModel { [Required] public int Id { get; set; } [StringLength(100)] public string Name { get; set; } }
非同期アクションは、I/O 操作が完了するまで待機している間にスレッドを解放することにより、スケーラビリティを向上させます。 async キーワードを使用し、Task または Task<IActionResult> を返します。
[HttpGet("{id}")] public async Task<IActionResult> GetAsync(int id) { var result = await _service.GetByIdAsync(id); return Ok(result); }
グローバル例外処理により、一元的なエラー処理、ログ記録、および未処理の例外に対する標準化された API 応答が可能になります。
app.UseExceptionHandler(a => a.Run(async context => { var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>(); var exception = exceptionHandlerPathFeature.Error; // Log the exception, generate a custom response, etc. context.Response.StatusCode = 500; await context.Response.WriteAsJsonAsync(new { Error = "An unexpected error occurred" }); }));
API のバージョン管理は、時間の経過に伴う API への変更を管理するのに役立ちます。 .NET プラットフォームは、クエリ文字列、URL パス、または要求ヘッダーによるバージョン管理をサポートしています。
builder.Services.AddApiVersioning(options => { options.AssumeDefaultVersionWhenUnspecified = true; options.DefaultApiVersion = new ApiVersion(1, 0); options.ReportApiVersions = true; });
コンテンツ ネゴシエーションにより、API はリクエスト内の Accept ヘッダーに基づいてさまざまな形式の応答を提供できるようになり、JSON、XML などの形式のサポートが可能になります。
builder.Services.AddControllers() .AddXmlDataContractSerializerFormatters();
JSON シリアライザー設定を構成して、キャメルケースの名前付けや null 値の無視など、JSON 応答の形式をカスタマイズします。
builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; options.JsonSerializerOptions.IgnoreNullValues = true; });
Cross-Origin Resource Sharing (CORS) を使用すると、異なるドメインでホストされている Web アプリケーションから API を呼び出すことができます。要件に従って CORS ポリシーを構成します。
builder.Services.AddCors(options => { options.AddPolicy("AllowSpecificOrigin", builder => builder.WithOrigins("http://example.com")); }); app.UseCors("AllowSpecificOrigin");
認証を有効にして API を保護します。これにより、リクエストを行うユーザーまたはサービスの ID が検証されます。
builder.Services.AddAuthentication("Bearer") .AddJwtBearer(options => { options.Authority = "https://your-auth-server"; options.Audience = "your-api"; });
認証後、認可によって、認証されたユーザーにアクションを実行する権限またはリソースにアクセスする権限があるかどうかが判断されます。
[Authorize] public class SecureController : ControllerBase { // Action methods here }
Swagger (OpenAPI) は API のインタラクティブなドキュメントを提供し、開発者が API を簡単に理解して使用できるようにします。
builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); app.UseSwagger(); app.UseSwaggerUI();
.NET Core は、さまざまな出力 (コンソール、デバッグ ウィンドウ、外部サービスなど) にメッセージを記録できる組み込みのログ フレームワークを提供します。
logger.LogInformation("This is an informational message"); app.Use(async (context, next) => { logger.LogError("This is an error message before the next middleware"); await next.Invoke(); // Log after calling the next middleware });
Entity Framework Core は、.NET アプリケーションでのデータ アクセスに使用される ORM です。これにより、厳密に型指定されたオブジェクトを使用してデータのクエリと操作が可能になります。
public class MyDbContext : DbContext { public MyDbContext(DbContextOptions<MyDbContext> options) : base(options) {} public DbSet<MyModel> MyModels { get; set; } }
移行により、データ モデルの変更を追跡することで、データベース スキーマにバージョン管理を適用できます。
dotnet ef migrations add InitialCreate dotnet ef database update
リポジトリ パターンはデータ層を抽象化し、アプリケーションをよりモジュール化して保守しやすくします。
public interface IRepository<T> { Task<IEnumerable<T>> GetAllAsync(); Task<T> GetByIdAsync(int id); // Other methods... } public class MyRepository<T> : IRepository<T> where T : class { private readonly MyDbContext _context; public MyRepository(MyDbContext context) { _context = context; } // Implement methods... }
単体テストでは、コードの個々のユニットを分離してテストすることで、Web API が正しく機能することを確認します。
public class MyControllerTests { [Fact] public async Task Get_ReturnsExpectedValue() { // Arrange var serviceMock = new Mock<IMyService>(); serviceMock.Setup(service => service.GetAsync()).ReturnsAsync("test"); var controller = new MyController(serviceMock.Object); // Act var result = await controller.Get(); // Assert Assert.Equal("test", result.Value); } }
.NET Web API は、フロントエンド アプリケーションのバックエンドとして機能し、RESTful サービスを提供できます。
fetch('https://localhost:5001/mycontroller') .then(response => response.json()) .then(data => console.log(data));
ヘルスチェックは、アプリケーションとその依存関係のステータスを監視する方法を提供し、マイクロサービス アーキテクチャに役立ちます。
builder.Services.AddHealthChecks(); app.MapHealthChecks("/health");
SignalR はリアルタイム Web 機能を有効にし、サーバー側コードがクライアント側 Web アプリケーションに非同期通知を送信できるようにします。
public class MyHub : Hub { public async Task SendMessage(string user, string message) { await Clients.All.SendAsync("ReceiveMessage", user, message); } }
応答キャッシュは、以前に要求されたリソースのコピーを保存することにより、サーバーが処理する必要がある要求の数を減らします。
[HttpGet("{id}")] [ResponseCache(Duration = 60)] public IActionResult GetById(int id) { // Retrieve and return your resource }
静的ファイル (HTML、CSS、JavaScript など) の提供は、.NET Web API を使用してフロントエンド アプリケーションをサポートするために不可欠です。
app.UseStaticFiles(); // Enable static file serving
オプション パターンは、クラスを使用して関連する設定のグループを表します。 IOptions<T> を使用すると、アプリケーション内のどこからでもこれらの設定にアクセスできます。
public class MySettings { public string Setting1 { get; set; } // Other settings } builder.Services.Configure<MySettings>(builder.Configuration.GetSection("MySettings")); public class MyService { private readonly MySettings _settings; public MyService(IOptions<MySettings> settings) { _settings = settings.Value; } // Use _settings.Setting1 }
ミドルウェアは、リクエストと応答を処理するためにアプリケーション パイプラインに組み込まれるソフトウェアです。特定のタスクを実行するためにカスタム ミドルウェアを作成できます。
public class MyCustomMiddleware { private readonly RequestDelegate _next; public MyCustomMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext httpContext) { // Pre-processing logic here await _next(httpContext); // Call the next middleware in the pipeline // Post-processing logic here } } // Extension method for easy middleware registration public static class MyCustomMiddlewareExtensions { public static IApplicationBuilder UseMyCustomMiddleware(this IApplicationBuilder builder) { return builder.UseMiddleware<MyCustomMiddleware>(); } }
レート制限は、ユーザーが特定の時間枠内でリクエストを実行できる頻度を制限することで、API の過剰使用を防ぎます。
// Assume using a third-party library like AspNetCoreRateLimit builder.Services.AddInMemoryRateLimiting(); builder.Services.Configure<IpRateLimitOptions>(options => { options.GeneralRules = new List<RateLimitRule> { new RateLimitRule { Endpoint = "*", Limit = 100, Period = "1h" } }; });
API キーは、API 呼び出しを認証および認可するための簡単な方法です。これらは、クエリ文字列またはヘッダーのいずれかでクライアントからサーバーに渡されます。
public class ApiKeyMiddleware { private readonly RequestDelegate _next; private const string APIKEYNAME = "x-api-key"; public ApiKeyMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext context) { if (!context.Request.Headers.TryGetValue(APIKEYNAME, out var extractedApiKey)) { context.Response.StatusCode = 401; await context.Response.WriteAsync("API Key was not provided."); return; } // Validate the extracted API Key here... await _next(context); } }
出力キャッシュを使用すると、リクエストに対する応答を保存できます。後続のリクエストはキャッシュから処理できるため、パフォーマンスが大幅に向上します。
[HttpGet] [ResponseCache(Duration = 120, Location = ResponseCacheLocation.Client, NoStore = false)] public IActionResult Get() { // Your logic here }
バックグラウンド タスクを使用すると、電子メールの送信や長時間実行されるジョブの処理など、ユーザーのリクエストに関係なく操作をバックグラウンドで実行できます。
public class MyBackgroundService : BackgroundService { protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { // Your background task logic here await Task.Delay(TimeSpan.FromHours(1), stoppingToken); } } }
WebSocket は、単一の長時間接続を介して全二重通信チャネルを提供し、リアルタイム アプリケーションに最適です。
app.UseWebSockets(); app.Use(async (context, next) => { if (context.WebSockets.IsWebSocketRequest) { WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync(); // Handle the WebSocket request here } else { await next(); } });
リクエストのローカリゼーションは、リクエストの情報に基づいて、コンテンツをさまざまな文化や言語にローカライズする方法を提供します。
var supportedCultures = new[] { "en-US", "fr-FR" }; var localizationOptions = new RequestLocalizationOptions() .SetDefaultCulture(supportedCultures[0]) .AddSupportedCultures(supportedCultures) .AddSupportedUICultures(supportedCultures); app.UseRequestLocalization(localizationOptions);
GraphQL は API 用のクエリ言語です。 .NET Web API を GraphQL と統合すると、より効率的なデータ取得が可能になります。
// Assume using a library like HotChocolate builder.Services .AddGraphQLServer() .AddQueryType<Query>(); app.MapGraphQL();
監視とテレメトリには、アプリケーションのパフォーマンスと使用状況に関するデータの収集、分析、およびそれに基づく操作が含まれます。
// Assume using Application Insights builder.Services.AddApplicationInsightsTelemetry("YOUR_INSTRUMENTATION_KEY");
SignalR は、アプリへのリアルタイム Web 機能の追加を簡素化するライブラリです。リアルタイム Web 機能とは、サーバー コードが、クライアントが新しいデータを要求するのを待つことなく、接続されているクライアントにコンテンツを即座にプッシュできるようにする機能です。 SignalR は、チャット アプリケーション、リアルタイム ダッシュボード、およびよりインタラクティブな Web アプリケーションの開発に最適です。
public class ChatHub : Hub { public async Task SendMessage(string user, string message) { // Call the broadcastMessage method to update clients. await Clients.All.SendAsync("broadcastMessage", user, message); } } // Startup or Program.cs app.MapHub<ChatHub>("/chathub");
Program.cs への統合:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // Other configurations... app.UseEndpoints(endpoints => { endpoints.MapHub<ChatHub>("/chathub"); }); }
Entity Framework Core を使用すると、1 対 1、1 対多、多対多など、エンティティ間の複雑な関係のマッピングが可能になります。
public class Author { public int AuthorId { get; set; } public string Name { get; set; } public ICollection<Book> Books { get; set; } } public class Book { public int BookId { get; set; } public string Title { get; set; } public int AuthorId { get; set; } public Author Author { get; set; } }
カスタム検証属性を使用すると、データ モデルの検証ロジックを定義し、組み込みの検証属性を拡張できます。
public class MyCustomValidationAttribute : ValidationAttribute { protected override ValidationResult IsValid(object value, ValidationContext validationContext) { // Your custom validation logic here if (value is int intValue && intValue > 0) { return ValidationResult.Success; } return new ValidationResult("Value must be positive"); } } public class MyModel { [MyCustomValidationAttribute] public int MyProperty { get; set; } }
.NET のオプション パターンは、ネストされたオブジェクト、リスト、検証などの複雑な構成シナリオをサポートします。
public class MyOptions { public MyNestedOptions Nested { get; set; } public List<string> Items { get; set; } } public class MyNestedOptions { public string Key { get; set; } } // In Program.cs or Startup.cs builder.Services.Configure<MyOptions>(builder.Configuration.GetSection("MyOptions"));
アプリケーションの監視とプロファイリングにより、パフォーマンスの最適化に不可欠なボトルネックと非効率性を特定できます。
app.UseMiniProfiler();
XML コメントを Swagger UI に統合することで API ドキュメントを強化し、API を使用する開発者により豊かなエクスペリエンスを提供します。
builder.Services.AddSwaggerGen(c => { var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); c.IncludeXmlComments(xmlPath); });
グローバリゼーションとローカリゼーションにより、アプリケーションは複数の言語と文化をサポートできるようになり、世界中のユーザーがアクセスできるようになります。
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources"); app.UseRequestLocalization(app.Services.GetRequiredService<IOptions<RequestLocalizationOptions>>().Value);
さまざまな HTTP ヘッダーを追加して Web アプリケーションのセキュリティを向上させると、一般的な攻撃や脆弱性から保護できます。
app.UseHsts(); app.UseXContentTypeOptions(); app.UseReferrerPolicy(opts => opts.NoReferrer()); app.UseXXssProtection(options => options.EnabledWithBlockMode()); app.UseXfo(options => options.Deny());
機能フラグを使用すると、新しいコードをデプロイすることなくアプリケーションの機能のオンとオフを切り替えることができるため、テストとロールアウトが容易になります。
// Using a library like Microsoft.FeatureManagement builder.Services.AddFeatureManagement();
Blazor を使用すると、JavaScript の代わりに C# を使用して対話型 Web UI を構築できます。 Blazor を Web API と統合すると、シームレスなフルスタック開発エクスペリエンスが提供されます。
// In a Blazor Server app @code { private IEnumerable<WeatherForecast> forecasts; protected override async Task OnInitializedAsync() { forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast"); } }
応答圧縮により API 応答のサイズが削減され、低速ネットワーク上のクライアントの読み込み時間が短縮されます。
builder.Services.AddResponseCompression(options => { options.Providers.Add<GzipCompressionProvider>(); options.EnableForHttps = true; }); app.UseResponseCompression();
C# コミュニティにご参加いただきありがとうございます。出発する前に:
フォローしてください: X |リンクトイン|開発者|ハッシュノード|ニュースレター|タンブラー
他のプラットフォームにアクセスしてください: GitHub |インスタグラム|ティックトック|クオラ| Daily.dev
ここでも公開されています