ایجاد اولین endpoint از نوع Get مبتنی بر Minimal API
برای افزودن اولین endpoint برنامه، به فایل Program.cs برنامه مراجعه کرده و آنرا به صورت زیر تکمیل میکنیم:
// ... app.UseHttpsRedirection(); app.MapGet("/api/authors", async (MinimalBlogDbContext ctx) => { var authors = await ctx.Authors.ToListAsync(); return authors; }); app.Run();
همانطور که مشاهده میکنید میتوان در اینجا، این Delegate را از نوع Lambda expressions تعریف کرد و با ذکر MinimalBlogDbContext به صورت یک پارامتر آن، کار تزریق وابستگیهای خودکار آن نیز صورت میگیرد. شبیه به حالتی که میتوان یک سرویس را به عنوان پارامتر یک اکشن متد، با ذکر ویژگی [FromServices] در کنترلرهای MVC معرفی کرد؛ البته در اینجا بدون نیاز به ذکر این ویژگی (هرچند هنوز هم قابل ذکر است). مزیت آن این است که هر endpoint، تنها سرویسهای مورد نیاز خودش را دریافت میکند و نه یک لیست قابل توجه از تمام سرویسهایی که قرار است در قسمتهای مختلف یک کنترلر استفاده شوند.
پس از آن میتوان با Context ای که در اختیار داریم، عملیات مدنظر را پیاده سازی کرده و یک خروجی را ارائه دهیم. در اینجا دیگر نیازی به تعریف IActionResultها و امثال آن نیست و همه چیز ساده شدهاست.
ایجاد اولین endpoint از نوع Post مبتنی بر Minimal API
app.MapPost، معادل یک اکشن متد کنترلرهای MVC را که از نوع HttpPost هستند، ارائه میدهد:
//... app.UseHttpsRedirection(); //... app.MapPost("/api/authors", async (MinimalBlogDbContext ctx, AuthorDto authorDto) => { var author = new Author(); author.FirstName = authorDto.FirstName; author.LastName = authorDto.LastName; author.Bio = authorDto.Bio; author.DateOfBirth = authorDto.DateOfBirth; ctx.Authors.Add(author); await ctx.SaveChangesAsync(); return author; }); app.Run(); internal record AuthorDto(string FirstName, string LastName, DateTime DateOfBirth, string? Bio);
سعی شدهاست تا این مثال در سادهترین شکل ممکن خودش ارائه شود. در ادامه کار نگاشت خواص Dto را به مدل دومین برنامه، توسط AutoMapper انجام خواهیم داد.
مابقی نکات متد app.MapPost نیز مانند متد app.MapGet است؛ برای مثال در اینجا نیز تعریف مسیر endpoint، توسط اولین پارامتر این متد صورت میگیرد و نحوهی تزریق سرویس DbContext برنامه نیز یکی است.
آزمایش برنامهی Minimal API's
برنامهی Minimal API's تهیه شده، به همراه یک Swagger از پیش تنظیم شده نیز هست. به همین جهت برای کار با این API الزاما نیازی به استفادهی از مثلا برنامهی Postman یا راه حلهای مشابه نیست. بنابراین فقط کافی است تا برنامهی API را اجرا کرده و در رابط کاربری ظاهر شده در آدرس https://localhost:7085/swagger/index.html، بر روی دکمهی Try it out هر کدام از endpointها کلیک کنیم. برای مثال اگر چنین کاری را در قسمت Post انجام دهیم، به تصویر زیر میرسیم:
در اینجا پس از ویرایش اطلاعات شیء JSON ای که برای ما تدارک دیدهاست، فقط کافی است بر روی دکمهی execute ذیل آن کلیک کنیم تا اطلاعات این Dto را به app.MapPost متناظر فوق ارسال کند و برای نمونه خروجی بازگشتی از سرور را نیز در همینجا نمایش میدهد که در آن، Id رکورد نیز پس از ثبت در بانک اطلاعاتی، مشخص است:
شروع به Refactoring و خلوت کردن فایل Program.cs
اگر بخواهیم به همین نحو تمام endpoints و dtoها را داخل فایل Program.cs اضافه کنیم، پس از مدتی به یک فایل بسیار حجیم و غیرقابل نگهداری خواهیم رسید. بنابراین در مرحلهی اول، تنظیمات سرویسها و میان افزارها را به خارج از آن منتقل میکنیم. برای این منظور پوشهی جدید Extensions را به همراه دو کلاس زیر ایجاد میکنیم:
using Microsoft.EntityFrameworkCore; using MinimalBlog.Dal; namespace MinimalBlog.Api.Extensions; public static class ServiceCollectionExtensions { public static IServiceCollection AddApplicationServices(this IServiceCollection services, WebApplicationBuilder builder) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var connectionString = builder.Configuration.GetConnectionString("Default"); builder.Services.AddDbContext<MinimalBlogDbContext>(opt => opt.UseSqlServer(connectionString)); return services; } }
همچنین نیاز به متد الحاقی دیگری برای خارج کردن تنظیمات میانافزارها داریم:
namespace MinimalBlog.Api.Extensions; public static class WebApplicationExtensions { public static WebApplication ConfigureApplication(this WebApplication app) { if (app == null) { throw new ArgumentNullException(nameof(app)); } if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); return app; } }
var builder = WebApplication.CreateBuilder(args); builder.Services.AddApplicationServices(builder); var app = builder.Build(); app.ConfigureApplication();
در قسمت بعد، endpoints را از این کلاس آغازین برنامه خارج میکنیم.