Content-Type في C# HttpClient: كيفية ضبطه دون كسر الطلب

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

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

ابدأ الدورة

لماذا يعتبر Content-Type كابوسًا لكل مطور C#؟

\n\n

هل سبق لك أن أرسلت طلب POST عبر HttpClient في C#، فردّ عليك الخادم بخطأ غامض 415 (Unsupported Media Type)؟ مألوف، أليس كذلك؟ غالبًا ما تكمن المشكلة في رأس واحد صغير ولكنه بالغ الأهمية — Content-Type. بدونه، لا يعرف الخادم ببساطة كيف يفسر بياناتك: هل هي JSON، XML، أم نموذج عادي؟

\n\n

في هذه المقالة، سنشرح كيفية تعيين Content-Type لـ HttpClient في C# بشكل صحيح، وسنستعرض الأخطاء الأكثر شيوعًا التي يقع فيها المبتدئون (وليس فقط)، ونتعلم كيفية إرسال الطلبات بحيث يفهمك الخادم من أول كلمة. هيا بنا!

\n\n

ما هو Content-Type ولماذا هو مطلوب؟

\n\n

Content-Type هو رأس HTTP يخبر الخادم بالتنسيق الذي تُرسل به البيانات في جسم الطلب (أو الاستجابة). إذا كنت ترسل JSON، يجب أن تقول: application/json. إذا كان XML — application/xml. إذا كانت بيانات نموذج — application/x-www-form-urlencoded.

\n\n

في C#، HttpClient أداة قوية ولكنها ماكرة. يمكنها تخمين التنسيق بنفسها، وقد لا تفعل. وإذا حاولت ببساطة إضافة الرأس عبر DefaultRequestHeaders، فستفاجأ بمفاجأة غير سارة: Content-Type ليس جزءًا من رؤوس الطلب الافتراضية. إنه ينتمي فقط إلى جسم الطلب.

\n\n

خطأ المبتدئ النموذجي

\n\n
var client = new HttpClient();\nclient.DefaultRequestHeaders.Add("Content-Type", "application/json"); // ❌ خطأ!\n
\n\n

هذا الكود سيؤدي إلى استثناء InvalidOperationException مع رسالة: "Misused header name. Make sure request headers are used with HttpRequestMessage, response ones with HttpResponseMessage, and content ones with HttpContent objects." يبدو مخيفًا، لكن الحل بسيط — تابع القراءة.

\n\n

ثلاث طرق لتعيين Content-Type في C# HttpClient

\n\n

الطريقة 1: استخدام StringContent (الأسهل)

\n\n

الطريقة الأكثر شيوعًا وصحة هي تمرير الرأس مع جسم الطلب عبر الفئة StringContent.

\n\n
using System;\nusing System.Net.Http;\nusing System.Text;\nusing System.Threading.Tasks;\n\nclass Program\n{\n    static async Task Main()\n    {\n        var client = new HttpClient();\n        var json = "{ \\"name\\": \\"PythonLib\\", \\"type\\": \\"education\\" }";\n        \n        // إنشاء المحتوى مع تحديد Content-Type بشكل صريح\n        var content = new StringContent(json, Encoding.UTF8, "application/json");\n        \n        var response = await client.PostAsync("https://api.example.com/data", content);\n        Console.WriteLine(await response.Content.ReadAsStringAsync());\n    }\n}\n
\n\n

في هذا المثال، يتم تعيين Content-Type: application/json; charset=utf-8 تلقائيًا. المعامل الثاني (Encoding.UTF8) يحدد الترميز، والثالث يحدد نوع الوسائط. وهكذا — الخادم راضٍ!

\n\n

الطريقة 2: عبر ByteArrayContent (للمتقدمين)

\n\n

إذا كنت تعمل مع بيانات ثنائية أو تريد تحكمًا كاملاً، استخدم ByteArrayContent.

\n\n
using System.Net.Http;\nusing System.Text;\n\nvar jsonBytes = Encoding.UTF8.GetBytes("{ \\"message\\": \\"Hello\\" }");\nvar content = new ByteArrayContent(jsonBytes);\ncontent.Headers.ContentType = new MediaTypeHeaderValue("application/json");\n\nvar response = await client.PostAsync("https://api.example.com/upload", content);\n
\n\n

هنا نقوم بتعيين ContentType يدويًا عبر الخاصية Headers. هذه الطريقة مفيدة عندما تحتاج إلى إضافة رؤوس إضافية (مثل Content-Encoding).

\n\n

الطريقة 3: HttpRequestMessage + تحكم كامل

\n\n

أحيانًا تحتاج إلى إرسال طلب GET مع جسم (نعم، هذا ممكن أيضًا) أو تجاوز الرؤوس على مستوى الطلب. عندها

المدونات

توصيات الكتب