عميل HTTP بلغة C#: إجراء الطلبات بشكل صحيح وفعال

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: لماذا تحتاج إلى عميل HTTP صحيح في C#؟

في التطوير الحديث، لا يكاد أي تطبيق يستغني عن التفاعل مع الخدمات الخارجية. سواء كان إرسال البيانات إلى الخادم، أو الحصول على أسعار العملات، أو العمل مع API سحابي — كل هذا يتطلب تنفيذًا صحيحًا لطلبات HTTP. في نظام C# (.NET)، الأداة الرئيسية لهذه المهمة هي الفئة HttpClient. ومع ذلك، يرتكب العديد من المطورين، خاصة المبتدئين، أخطاء نموذجية: إنشاء مثيل جديد من HttpClient لكل طلب، نسيان معالجة الاستثناءات، أو العمل بشكل غير صحيح مع البرمجة غير المتزامنة.

في هذه المقالة، سنشرح كيفية تنظيم عميل HTTP بشكل صحيح في C#، وسننظر في إرسال طلبات GET و POST، والعمل مع الرؤوس ونص الطلب، بالإضافة إلى أفضل الممارسات لمعالجة الأخطاء. بعد القراءة، ستتمكن من كتابة كود موثوق وفعال للتفاعل مع أي REST API.

أساسيات العمل مع HttpClient في C#

الفئة HttpClient موجودة في مساحة الأسماء System.Net.Http ومتاحة في جميع الإصدارات الحديثة من .NET (Core، 5، 6، 7، 8 وما فوق). ميزتها الرئيسية هي دعم العمليات غير المتزامنة والإدارة التلقائية لمجموعة الاتصالات.

إنشاء HttpClient بشكل صحيح

القاعدة الأهم: لا تنشئ HttpClient جديدًا لكل طلب. هذا قد يؤدي إلى استنفاد المقابس (socket exhaustion). بدلاً من ذلك، استخدم مثيلًا واحدًا طوال عمر التطبيق أو استخدم IHttpClientFactory.

// ❌ سيء: HttpClient جديد لكل طلب
using (var client = new HttpClient())
{
    var response = await client.GetAsync("https://api.example.com");
}

// ✅ جيد: HttpClient واحد لجميع الطلبات
public class MyHttpService
{
    private static readonly HttpClient _client = new HttpClient();
    
    public async Task<string> GetDataAsync(string url)
    {
        return await _client.GetStringAsync(url);
    }
}

الإعدادات الأساسية

عند تهيئة HttpClient، يمكنك تعيين العنوان الأساسي، المهلات، والرؤوس الافتراضية:

public class ApiClient
{
    private readonly HttpClient _httpClient;
    
    public ApiClient()
    {
        _httpClient = new HttpClient
        {
            BaseAddress = new Uri("https://api.pythonlib.ru/"),
            Timeout = TimeSpan.FromSeconds(10)
        };
        
        // الرؤوس التي سيتم إرسالها مع كل طلب
        _httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
        _httpClient.DefaultRequestHeaders.Add("User-Agent", "MyApp/1.0");
    }
}

إرسال طلبات GET و POST

سننظر في أكثر نوعين شيوعًا من طلبات HTTP: الحصول على البيانات (GET) وإرسال البيانات (POST).

طلب GET: الحصول على البيانات

يستخدم طلب GET لقراءة البيانات من الخادم. لا يجب أن يغير حالة المورد ولا يحتوي على نص.

public async Task<string> GetUserAsync(int userId)
{
    try
    {
        var response = await _httpClient.GetAsync($"/api/users/{userId}");
        response.EnsureSuccessStatusCode(); // سيرمي استثناء عند الخطأ
        return await response.Content.ReadAsStringAsync();
    }
    catch (HttpRequestException ex)
    {
        Console.WriteLine($"خطأ في الطلب: {ex.Message}");
        throw;
    }
}

للحالات البسيطة، يمكن استخدام الصيغة المختصرة:

string json = await _httpClient.GetStringAsync("/api/users/42");

طلب POST: إرسال البيانات

يستخدم طلب POST لإنشاء موارد جديدة. يتم إرسال البيانات في نص الطلب، غالبًا بتنسيق JSON.

public async Task<User> CreateUserAsync(User newUser)
{
    // تسلسل الكائن إلى JSON
    var json = JsonSerializer.Serialize(newUser);                

المدونات

توصيات الكتب