ฉันจะส่งออบเจ็กต์ไปยัง HttpClient.PostAsync และทำให้เป็นอนุกรมเป็นเนื้อความ JSON ได้อย่างไร


94

ฉันใช้อยู่System.Net.Httpฉันพบตัวอย่างมากมายบนเว็บ ฉันจัดการสร้างรหัสนี้เพื่อPOSTส่งคำขอ:

public static string POST(string resource, string token)
{
    using (var client = new HttpClient())
    {
        client.BaseAddress = new Uri(baseUri);
        client.DefaultRequestHeaders.Add("token", token);

        var content = new FormUrlEncodedContent(new[]
        {
             new KeyValuePair<string, string>("", "")
        });

        var result = client.PostAsync("", content).Result;
        string resultContent = result.Content.ReadAsStringAsync().Result;
        return resultContent;
    }
 }

ทำงานได้ดีทั้งหมด แต่คิดว่าฉันต้องการผ่านพระรามสามกับวิธีการที่เรียกว่าพารามิเตอร์POST dataพารามิเตอร์ข้อมูลเป็นวัตถุเช่นนี้:

object data = new
{
    name = "Foo",
    category = "article"
};

ฉันจะทำได้อย่างไรโดยไม่ต้องสร้างKeyValuePair? php ของฉันRestAPIรออินพุต json ดังนั้นFormUrlEncodedContentควรส่งrawjson ให้ถูกต้อง แต่ฉันจะทำเช่นนี้ได้Microsoft.Net.Httpอย่างไร? ขอบคุณ.


หากฉันเข้าใจคำถามของคุณคุณต้องการส่งเนื้อหา JSON แทนเนื้อหาที่เข้ารหัสในรูปแบบถูกต้อง (และโดยส่วนขยายคุณต้องการให้ประเภทที่ไม่ระบุตัวตนของคุณถูกทำให้เป็นอนุกรมเป็น JSON ในเนื้อหานั้น)?
CodingGorilla

@CodingGorilla ใช่เป็นประเภทนิรนาม
IlDrugo

3
เพื่อเป็นหมายเหตุด้านข้างสำหรับผู้อ่านในอนาคตอย่าใช้usingไฟล์HttpClient. aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
maxshuty

2
หมายเหตุจาก Microsoft เหตุใดจึงusingไม่ควรใช้: HttpClient is intended to be instantiated once and reused throughout the life of an application. The following conditions can result in SocketException errors: Creating a new HttpClient instance per request. Server under heavy load. Creating a new HttpClient instance per request can exhaust the available sockets. docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/…
Ogglas

คำตอบ:


155

คำตอบที่ตรงไปตรงมาสำหรับคำถามของคุณคือไม่ลายเซ็นสำหรับPostAsyncวิธีการมีดังต่อไปนี้:

งานสาธารณะ PostAsync (Uri requestUri เนื้อหา HttpContent)

ดังนั้นในขณะที่คุณสามารถส่งผ่านobjectไปPostAsyncได้ต้องเป็นประเภทHttpContentและประเภทที่ไม่ระบุตัวตนของคุณไม่ตรงตามเกณฑ์นั้น

อย่างไรก็ตามมีหลายวิธีในการทำสิ่งที่คุณต้องการให้สำเร็จ ครั้งแรกที่คุณจะต้องเป็นอันดับประเภทที่ไม่ระบุชื่อของคุณเพื่อ JSON เครื่องมือที่พบมากที่สุดสำหรับเรื่องนี้คือJson.NET และรหัสสำหรับสิ่งนี้ค่อนข้างไม่สำคัญ:

var myContent = JsonConvert.SerializeObject(data);

จากนั้นคุณจะต้องสร้างวัตถุเนื้อหาเพื่อส่งข้อมูลนี้ฉันจะใช้ByteArrayContentวัตถุ แต่คุณสามารถใช้หรือสร้างประเภทอื่นได้หากต้องการ

var buffer = System.Text.Encoding.UTF8.GetBytes(myContent);
var byteContent = new ByteArrayContent(buffer);

ถัดไปคุณต้องการตั้งค่าประเภทเนื้อหาเพื่อให้ API รู้ว่านี่คือ JSON

byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");

จากนั้นคุณสามารถส่งคำขอของคุณที่คล้ายกับตัวอย่างก่อนหน้าของคุณด้วยเนื้อหาแบบฟอร์ม:

var result = client.PostAsync("", byteContent).Result

โปรดทราบว่าการโทรหา.Resultสถานที่ให้บริการเช่นที่คุณทำที่นี่อาจมีผลข้างเคียงที่ไม่ดีเช่นการล็อกที่ตายแล้วดังนั้นคุณควรระมัดระวังเรื่องนี้


โอเคมันชัดเจนมาก ขอบคุณสำหรับคำตอบนี้ เพียงแค่คำถาม: เมื่อPOST, PUT, DELETEดำเนินการa โดยปกติแล้ว API จะส่งคืนTRUEฉันได้ประกาศเมธอดเป็นstringแต่เมื่อฉันทำ: return result;ฉันได้รับ: Can't Convert HttpResponseMessage in stringฉันควรเปลี่ยนวิธีการประกาศหรือไม่ ฉันต้องการการตอบสนองของสตริง 'ทำให้ฉันต้อง deserialize หลังจากนั้นในวิธีการคลาสอื่น
IlDrugo

2
หากคุณต้องการกำหนดค่าเริ่มต้นเนื้อหาของการตอบกลับการส่งคืนสตริงตามที่คุณมีในคำถามของคุณ (โดยใช้result.Content.ReadAsStringAsync()) อาจใช้ได้ดี ขึ้นอยู่กับโครงสร้างแอปพลิเคชันของคุณอาจเป็นการดีกว่าที่จะส่งคืนContentอ็อบเจ็กต์โดยตรงหากคุณต้องการตรวจสอบส่วนหัวเพื่อพิจารณาว่าประเภทคอนเทนต์คืออะไร (เช่น XML หรือ JSON) แต่ถ้าคุณรู้ว่ามันจะส่งคืน JSON เสมอ (หรือรูปแบบอื่น ๆ ) เพียงแค่ส่งคืนเนื้อหาตอบกลับเป็นสตริงก็น่าจะโอเค
CodingGorilla

ขออภัยที่ถาม แต่ถ้าคุณจำเป็นต้องทำเช่นนี้ถ้าข้อมูลเป็นประเภทStringContent?
MyDaftQuestions

1
@MyDaftQuestions ฉันไม่แน่ใจว่าสิ่งที่คุณขอ แต่คุณสามารถส่งStringContentโดยตรงไปยังเพราะมันมาจากPostAsync HttpContent
CodingGorilla

@CodingGorilla นั่นคือสิ่งที่ฉันถาม ขอบคุณ :)
MyDaftQuestions

67

FormUrlEncodedContentคุณจำเป็นต้องส่งผ่านข้อมูลของคุณในร่างกายคำขอเป็นสตริงดิบมากกว่า วิธีหนึ่งในการทำเช่นนี้คือการทำให้เป็นอนุกรมเป็นสตริง JSON:

var json = JsonConvert.SerializeObject(data); // or JsonSerializer.Serialize if using System.Text.Json

ตอนนี้สิ่งที่คุณต้องทำคือส่งสตริงไปยังวิธีการโพสต์

var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); // use MediaTypeNames.Application.Json in Core 3.0+ and Standard 2.1+

var client = new HttpClient();
var response = await client.PostAsync(uri, stringContent);

คืออะไรstringContent? ในกรณีของฉันstringContentคือ"\"\"". ค่านี้ถูกต้องหรือไม่?
R15

เป็นไปได้ไหมที่จะได้รับผลลัพธ์สตริงใน vb จากรหัส c # ของคุณ ฉันพบว่ามันค่อนข้างคล้ายกัน ....
gumuruh

42

วิธีการแก้ปัญหาที่ง่ายคือการใช้งานMicrosoft ASP.NET Web API 2.2 ClientจากNuGet

จากนั้นคุณสามารถทำได้ง่ายๆและมันจะทำให้วัตถุเป็นอนุกรมเป็น JSON และตั้งค่าContent-Typeส่วนหัวเป็นapplication/json; charset=utf-8:

var data = new
{
    name = "Foo",
    category = "article"
};

var client = new HttpClient();
client.BaseAddress = new Uri(baseUri);
client.DefaultRequestHeaders.Add("token", token);
var response = await client.PostAsJsonAsync("", data);

2
PostAsJsonAsync มีให้ใช้แน่นอน
Kat Lim Ruiz

26

ตอนนี้มีวิธีที่ง่ายกว่านี้ด้วย.NET Standardหรือ.NET Core:

var client = new HttpClient();
var response = await client.PostAsync(uri, myRequestObject, new JsonMediaTypeFormatter());

หมายเหตุ:ในการใช้JsonMediaTypeFormatterคลาสคุณจะต้องติดตั้งMicrosoft.AspNet.WebApi.Clientแพ็คเกจ NuGet ซึ่งสามารถติดตั้งได้โดยตรงหรือผ่านทางอื่นเช่นMicrosoft.AspNetCore.App.

การใช้ลายเซ็นนี้HttpClient.PostAsyncคุณสามารถส่งผ่านในวัตถุใด ๆ และJsonMediaTypeFormatterจะดูแลการทำให้เป็นอนุกรมโดยอัตโนมัติเป็นต้น

ด้วยการตอบกลับคุณสามารถใช้HttpContent.ReadAsAsync<T>เพื่อยกเลิกการกำหนดค่าเนื้อหาตอบกลับเป็นประเภทที่คุณคาดหวัง:

var responseObject = await response.Content.ReadAsAsync<MyResponseType>();

1
รุ่นนี้ใช้. net รุ่นอะไร เวอร์ชันของฉันไม่พบ "การจัดรูปแบบ" ในเนมสเปซ System.Net.Http
TemporaryFix

1
@Programmatic คุณต้องใช้.NET Standardหรือ.NET Coreตามที่ฉันพูดถึง บางทีคุณกำลังใช้.NET Framework? ในโครงการของฉัน JsonMediaTypeFormatter กำลังโหลดจากที่นี่: C: \ Program Files \ dotnet \ sdk \ NuGetFallbackFolder \ microsoft.aspnet.webapi.client \ 5.2.6 \ lib \ netstandard2.0 \ System.Net.Http.Formatting dll
Ken Lyon

1
@Programmatic หากคุณใช้โปรเจ็กต์ประเภทใดประเภทหนึ่งอยู่แล้วอาจเป็นไปได้ว่าคุณต้องเพิ่มแพ็คเกจ NuGet เพิ่มเติม ฉันลืมสิ่งที่รวมไว้โดยอัตโนมัติสำหรับฉัน ในกรณีของฉันมันรวมอยู่ในแพ็คเกจ Microsoft.AspNetCore.App NuGet
Ken Lyon

1
ฉันใช้. NET Core แต่ฉันไม่คิดว่าโซลูชันของฉันถูกตั้งค่าให้ใช้ภาษา c # เวอร์ชันล่าสุด ฉันอัปเดตและใช้งานได้ ขอบคุณ
TemporaryFix

1
@Programmatic ยินดีต้อนรับ ฉันดีใจที่ได้ยินว่าคุณใช้งานได้จริง! ฉันได้เพิ่มหมายเหตุในคำตอบของฉันเกี่ยวกับแพ็คเกจ NuGet
Ken Lyon
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.