إنشاء أول Minimal API لكم
أنشئوا مشروع Minimal API، وعرّفوا معالجات المسارات، وأعيدوا نتائج محدّدة النوع بأقل قدر من التعليمات البرمجية.
إنشاء أول Minimal API لكم درس مجاني في C# Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C# Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C# Academy 4 دروس في المجموع.
ما واجهات API الدنيا؟
تتيح واجهات API الدنيا، التي قُدّمت في .NET 6، بناء نقاط نهاية HTTP بأقل قدر من الإجراءات الشكلية — من دون وحدات تحكم أو سمات للإجراءات، بل مجرد معالجات مسارات تُعرَّف مباشرةً في Program.cs. وهي مثالية للخدمات المصغّرة وواجهات API الخفيفة.
أبسط واجهة API دنيا
واجهة HTTP كاملة في بضعة أسطر فقط. تحدد الأساليب MapGet وMapPost وMapPut وMapDelete معالجات المسارات لكل فعل من أفعال HTTP.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello, Minimal API!");
app.MapGet("/ping", () => Results.Ok(new { status = "pong" }));
app.Run();
// That's it — no Startup.cs, no controllersالنتائج المكتوبة لاستجابات HTTP الصحيحة
استخدم Results أو TypedResults للحصول على رموز حالة HTTP وأنواع محتوى صحيحة. ويُفضَّل TypedResults لاستنتاج مخطط OpenAPI.
app.MapGet("/products/{id}", async (int id, AppDbContext db) =>
{
var product = await db.Products.FindAsync(id);
return product is null
? Results.NotFound()
: Results.Ok(product);
});
app.MapPost("/products", async (Product product, AppDbContext db) =>
{
db.Products.Add(product);
await db.SaveChangesAsync();
return Results.Created($"/products/{product.Id}", product);
});معلمات المسار وسلاسل الاستعلام
تُلتقط معلمات المسار من مسار URL، وتُربط معلمات سلسلة الاستعلام تلقائيًا من الاستعلام، ويُفك تسلسل نص الطلب من JSON.
// Route param {id} + query param ?includeDeleted
app.MapGet("/orders/{id}", async (
int id,
bool includeDeleted = false,
AppDbContext db) =>
{
var query = db.Orders.AsQueryable();
if (!includeDeleted) query = query.Where(o => !o.IsDeleted);
var order = await query.FirstOrDefaultAsync(o => o.Id == id);
return order is null ? Results.NotFound() : Results.Ok(order);
});حقن الاعتماديات في معالجات المسارات
يمكن حقن الخدمات المسجلة في حاوية DI مباشرةً باعتبارها معلمات لمعالج المسار. ويحلّ الإطار هذه الخدمات تلقائيًا.
builder.Services.AddScoped<ProductService>();
app.MapGet("/products", async (ProductService svc) =>
{
var products = await svc.GetAllAsync();
return Results.Ok(products);
});
app.MapDelete("/products/{id}", async (int id, ProductService svc) =>
{
var deleted = await svc.DeleteAsync(id);
return deleted ? Results.NoContent() : Results.NotFound();
});ربط نص الطلب
تُحقن المعلمات التي تطابق الخدمات المسجلة؛ وكل ما عدا ذلك يُربط من نص الطلب، ويكون JSON هو التنسيق الافتراضي. استخدم [FromBody] صراحةً عند الحاجة.
record CreateProductRequest(string Name, decimal Price, int Stock);
app.MapPost("/products", async (
CreateProductRequest req,
ProductService svc) =>
{
var product = await svc.CreateAsync(req.Name, req.Price, req.Stock);
return TypedResults.Created($"/products/{product.Id}", product);
});إرجاع رموز حالة مختلفة
توفر Results أساليب إنشاء لجميع استجابات HTTP الشائعة. استخدمها لإنشاء واجهات REST API صحيحة دلاليًا.
app.MapPut("/products/{id}", async (int id, Product update, AppDbContext db) =>
{
var existing = await db.Products.FindAsync(id);
if (existing is null) return Results.NotFound();
existing.Name = update.Name;
existing.Price = update.Price;
await db.SaveChangesAsync();
return Results.Ok(existing);
});
// Other useful Results:
// Results.BadRequest("message")
// Results.Conflict()
// Results.UnprocessableEntity(errors)
// Results.Accepted()إضافة بيانات وصفية باستخدام WithName وWithTags
أرفق بيانات وصفية بنقاط النهاية لتحسين التوثيق والتوجيه. استخدم WithName وWithTags وWithSummary لتنظيم مخرجات OpenAPI.
app.MapGet("/products/{id}", GetProduct)
.WithName("GetProductById")
.WithTags("Products")
.WithSummary("Retrieves a product by its ID")
.Produces<Product>()
.Produces(404);
static async Task<IResult> GetProduct(int id, AppDbContext db)
{
var p = await db.Products.FindAsync(id);
return p is null ? Results.NotFound() : Results.Ok(p);
}التخويل في واجهات API الدنيا
طبّق RequireAuthorization() لحماية نقاط النهاية، أو استخدم AllowAnonymous() للسماح بالوصول المجهول. تعمل السياسات بالطريقة نفسها المستخدمة مع وحدات التحكم.
builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddAuthorization();
app.UseAuthentication();
app.UseAuthorization();
app.MapGet("/profile", (ClaimsPrincipal user) =>
Results.Ok(user.Identity!.Name))
.RequireAuthorization();
app.MapGet("/public", () => "No auth needed")
.AllowAnonymous();التنظيم باستخدام الأساليب static
بالنسبة إلى واجهات API الأكبر حجمًا، انقل معالجات المسارات إلى أساليب static أو أساليب امتداد للحفاظ على نظافة ملف Program.cs وسهولة التنقل فيه.
// Extension method groups endpoints by feature
public static class ProductEndpoints
{
public static void MapProductEndpoints(this WebApplication app)
{
app.MapGet("/products", GetAll);
app.MapGet("/products/{id}", GetById);
app.MapPost("/products", Create);
}
private static async Task<IResult> GetAll(AppDbContext db)
=> Results.Ok(await db.Products.AsNoTracking().ToListAsync());
// ... other handlers
}
// In Program.cs:
app.MapProductEndpoints();من الواقع العملي: Minimal API كاملة لعمليات CRUD
واجهة API كاملة ومختصرة وقابلة للاختبار وجاهزة للإنتاج لتنفيذ عمليات CRUD على مورد Todo.
app.MapGet("/todos", async (AppDbContext db) =>
Results.Ok(await db.Todos.AsNoTracking().ToListAsync()));
app.MapGet("/todos/{id}", async (int id, AppDbContext db) =>
{
var todo = await db.Todos.FindAsync(id);
return todo is null ? Results.NotFound() : Results.Ok(todo);
});
app.MapPost("/todos", async (Todo todo, AppDbContext db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todos/{todo.Id}", todo);
});
app.MapDelete("/todos/{id}", async (int id, AppDbContext db) =>
{
int n = await db.Todos.Where(t => t.Id == id).ExecuteDeleteAsync();
return n > 0 ? Results.NoContent() : Results.NotFound();
});اختبار سريع
كيف يحصل معالج المسار في Minimal API على خدمة DI مسجّلة؟
مراجعة: إنشاء أول Minimal API
أهم النقاط:
- تعرّف MapGet/Post/Put/Delete معالجات المسارات مباشرةً في Program.cs
- استخدم
Results/TypedResultsلإرجاع رموز حالة HTTP الصحيحة - يتم ربط معاملات المسار والاستعلام والجسم وDI تلقائيًا
- استخدم
RequireAuthorization()وAllowAnonymous()للمصادقة - نظّم واجهات API الكبيرة باستخدام أساليب الامتداد أو مجموعات المسارات
الأسئلة الشائعة
هل درس «إنشاء أول Minimal API لكم» مجاني؟
نعم — نص درس «إنشاء أول Minimal API لكم» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C# Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C# Academy 4 دروس في المجموع.
ماذا ستتعلم في «إنشاء أول Minimal API لكم»؟
أنشئوا مشروع Minimal API، وعرّفوا معالجات المسارات، وأعيدوا نتائج محدّدة النوع بأقل قدر من التعليمات البرمجية. تتمرن على C# Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ C# Academy؟
لا تُشترط خبرة سابقة. C# Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.
كم من الوقت يستغرق درس «إنشاء أول Minimal API لكم»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس C# Academy هذا؟
نعم. كل درس في C# Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- إنشاء أول Minimal API لكم
- مجموعات المسارات والمعلمات والتحقق
- Middleware وFilters في Minimal APIs
- OpenAPI وإصدار الواجهات والنشر