ส่ง JSON ผ่าน POST ใน C # และรับ JSON ส่งคืนหรือไม่


86

นี่เป็นครั้งแรกของฉันที่ใช้ JSON System.NetและWebRequestในแอปพลิเคชันใด ๆ ของฉัน แอปพลิเคชันของฉันควรจะส่งข้อมูล JSON ซึ่งคล้ายกับที่ระบุไว้ด้านล่างไปยังเซิร์ฟเวอร์การตรวจสอบความถูกต้อง

{
  "agent": {                             
    "name": "Agent Name",                
    "version": 1                                                          
  },
  "username": "Username",                                   
  "password": "User Password",
  "token": "xxxxxx"
}

เพื่อสร้างเพย์โหลดนี้ฉันใช้JSON.NETไลบรารี ฉันจะส่งข้อมูลนี้ไปยังเซิร์ฟเวอร์การตรวจสอบความถูกต้องและรับการตอบกลับ JSON กลับมาได้อย่างไร นี่คือสิ่งที่ฉันเห็นในตัวอย่างบางส่วน แต่ไม่มีเนื้อหา JSON:

var http = (HttpWebRequest)WebRequest.Create(new Uri(baseUrl));
http.Accept = "application/json";
http.ContentType = "application/json";
http.Method = "POST";

string parsedContent = "Parsed JSON Content needs to go here";
ASCIIEncoding encoding = new ASCIIEncoding();
Byte[] bytes = encoding.GetBytes(parsedContent);

Stream newStream = http.GetRequestStream();
newStream.Write(bytes, 0, bytes.Length);
newStream.Close();

var response = http.GetResponse();

var stream = response.GetResponseStream();
var sr = new StreamReader(stream);
var content = sr.ReadToEnd();

อย่างไรก็ตามดูเหมือนว่าจะมีโค้ดจำนวนมากที่เปรียบเทียบกับการใช้ภาษาอื่น ๆ ที่ฉันเคยใช้ในอดีต ฉันทำถูกต้องหรือไม่? และฉันจะได้รับการตอบสนอง JSON กลับมาอย่างไรเพื่อให้ฉันสามารถแยกวิเคราะห์ได้

ขอบคุณ Elite

อัปเดตรหัส

// Send the POST Request to the Authentication Server
// Error Here
string json = await Task.Run(() => JsonConvert.SerializeObject(createLoginPayload(usernameTextBox.Text, password)));
var httpContent = new StringContent(json, Encoding.UTF8, "application/json");
using (var httpClient = new HttpClient())
{
    // Error here
    var httpResponse = await httpClient.PostAsync("URL HERE", httpContent);
    if (httpResponse.Content != null)
    {
        // Error Here
        var responseContent = await httpResponse.Content.ReadAsStringAsync();
    }
}

2
ลองดูWebClient.UploadString(JsonConvert.SerializeObjectobj(yourobj))หรือHttpClient.PostAsJsonAsync
LB

คำตอบ:


136

ฉันพบว่าตัวเองกำลังใช้ไลบรารีHttpClientเพื่อค้นหา RESTful API เนื่องจากโค้ดนั้นตรงไปตรงมามากและไม่มีการซิงค์อย่างสมบูรณ์

(แก้ไข: การเพิ่ม JSON จากคำถามเพื่อความชัดเจน)

{
  "agent": {                             
    "name": "Agent Name",                
    "version": 1                                                          
  },
  "username": "Username",                                   
  "password": "User Password",
  "token": "xxxxxx"
}

ด้วยสองคลาสที่แสดงถึงโครงสร้าง JSON ที่คุณโพสต์อาจมีลักษณะดังนี้:

public class Credentials
{
    [JsonProperty("agent")]
    public Agent Agent { get; set; }

    [JsonProperty("username")]
    public string Username { get; set; }

    [JsonProperty("password")]
    public string Password { get; set; }

    [JsonProperty("token")]
    public string Token { get; set; }
}

public class Agent
{
    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("version")]
    public int Version { get; set; }
}

คุณสามารถมีวิธีการเช่นนี้ซึ่งจะทำตามคำขอ POST ของคุณ:

var payload = new Credentials { 
    Agent = new Agent { 
        Name = "Agent Name",
        Version = 1 
    },
    Username = "Username",
    Password = "User Password",
    Token = "xxxxx"
};

// Serialize our concrete class into a JSON String
var stringPayload = await Task.Run(() => JsonConvert.SerializeObject(payload));

// Wrap our JSON inside a StringContent which then can be used by the HttpClient class
var httpContent = new StringContent(stringPayload, Encoding.UTF8, "application/json");

using (var httpClient = new HttpClient()) {

    // Do the actual request and await the response
    var httpResponse = await httpClient.PostAsync("http://localhost/api/path", httpContent);

    // If the response contains content we want to read it!
    if (httpResponse.Content != null) {
        var responseContent = await httpResponse.Content.ReadAsStringAsync();

        // From here on you could deserialize the ResponseContent back again to a concrete C# type using Json.Net
    }
}

5
สมบูรณ์แบบ แต่สิ่งที่รอคอยคือ Task.run (()?
Hunter Mitchell

24
คุณไม่ควรใช้งานเรียกใช้วิธีการเชื่อมต่อ CPU แบบซิงโครนัสเนื่องจากคุณเพิ่งเริ่มเธรดใหม่โดยไม่เกิดประโยชน์!
Stephen Foster

2
คุณไม่จำเป็นต้องพิมพ์JsonPropertyสำหรับทุกคุณสมบัติ เพียงใช้ Json.Net ที่สร้างขึ้นในCamelCasePropertyNamesContractResolverหรือกำหนดเองNamingStrategyเพื่อปรับแต่งกระบวนการทำให้เป็นอนุกรม
Seafish

6
หมายเหตุด้านข้าง: อย่าใช้usingกับHttpClient. ดู: aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
maxshuty

4
ด้วย System.Net.Http.Formatting คุณมีวิธีการขยายที่กำหนดไว้: "รอ httpClient.PostAsJsonAsync (" api / v1 / domain ", csObjRequest)"
hB0

15

ด้วยการใช้แพ็คเกจ JSON.NET NuGet และประเภทที่ไม่ระบุตัวตนคุณสามารถลดความซับซ้อนของสิ่งที่ผู้โพสต์อื่นแนะนำ:

// ...

string payload = JsonConvert.SerializeObject(new
{
    agent = new
    {
        name    = "Agent Name",
        version = 1,
    },

    username = "username",
    password = "password",
    token    = "xxxxx",
});

var client = new HttpClient();
var content = new StringContent(payload, Encoding.UTF8, "application/json");

HttpResponseMessage response = await client.PostAsync(uri, content);

// ...

6

คุณสามารถสร้างของคุณHttpContentโดยใช้การรวมกันของJObjectเพื่อหลีกเลี่ยงJPropertyแล้วเรียกToString()ใช้เมื่อสร้างStringContent:

        /*{
          "agent": {                             
            "name": "Agent Name",                
            "version": 1                                                          
          },
          "username": "Username",                                   
          "password": "User Password",
          "token": "xxxxxx"
        }*/

        JObject payLoad = new JObject(
            new JProperty("agent", 
                new JObject(
                    new JProperty("name", "Agent Name"),
                    new JProperty("version", 1)
                    ),
                new JProperty("username", "Username"),
                new JProperty("password", "User Password"),
                new JProperty("token", "xxxxxx")    
                )
            );

        using (HttpClient client = new HttpClient())
        {
            var httpContent = new StringContent(payLoad.ToString(), Encoding.UTF8, "application/json");

            using (HttpResponseMessage response = await client.PostAsync(requestUri, httpContent))
            {
                response.EnsureSuccessStatusCode();
                string responseBody = await response.Content.ReadAsStringAsync();
                return JObject.Parse(responseBody);
            }
        }

คุณจะหลีกเลี่ยงException while executing function. Newtonsoft.Json: Can not add Newtonsoft.Json.Linq.JProperty to Newtonsoft.Json.Linq.JArrayข้อผิดพลาดได้อย่างไร?
Jari Turkia

1
ไม่ควรสร้างอินสแตนซ์ HttpClient โดยใช้โครงสร้าง ควรสร้างอินสแตนซ์เพียงครั้งเดียวและใช้ตลอดทั้งแอปพลิเคชัน เนื่องจากใช้พูลการเชื่อมต่อของตัวเอง โค้ดของคุณมักจะโยน SocketException docs.microsoft.com/en-us/dotnet/api/…
Harun Diluka Heshan

2

คุณยังสามารถใช้ PostAsJsonAsync () วิธีการที่มีอยู่ใน HttpClient ()

   var requestObj= JsonConvert.SerializeObject(obj);
   HttpResponseMessage response = await    client.PostAsJsonAsync($"endpoint",requestObj).ConfigureAwait(false);


1
คุณช่วยเพิ่มคำอธิบายได้ไหมว่าโค้ดของคุณใช้ทำอะไรและแก้ปัญหาได้อย่างไร
Nilambar Sharma

คุณสามารถนำวัตถุใด ๆ ที่คุณต้องการโพสต์และทำให้เป็นอนุกรมโดยใช้ SerializeObject (); var obj= new Credentials { Agent = new Agent { Name = "Agent Name", Version = 1 }, Username = "Username", Password = "User Password", Token = "xxxxx" }; จากนั้นโดยไม่ต้องแปลงเป็น httpContent คุณสามารถใช้ PostAsJsonAsync () ส่งผ่าน URL ปลายทางและออบเจ็กต์ JSON ที่แปลงแล้วเอง
Rukshala Weerasinghe
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.