C #에서 POST를 통해 JSON을 보내고 반환 된 JSON을 받습니까?


86

이것은 내 첫 번째뿐만 아니라 어느 JSON을 사용하여 시간 System.NetWebRequest내 모든 응용 프로그램에. 내 응용 프로그램은 아래의 것과 유사한 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 응답을 어떻게받을 수 있습니까?

고마워요, 엘리트.

업데이트 된 코드

// 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
완벽하지만 await Task.run (()은 무엇입니까?
Hunter Mitchell

24
동기식 CPU 바운드 메서드에서 Task.Run을 사용하면 안됩니다. 새로운 스레드를 아무 이득없이 실행하는 것입니다!
Stephen Foster 17

2
JsonProperty모든 속성에 대해 를 입력 할 필요는 없습니다 . 그냥 Json.Net의 내장 사용 CamelCasePropertyNamesContractResolver 또는 사용자 정의NamingStrategy 직렬화 프로세스를 사용자 정의 할 수
Seafish

6
참고 : using와 함께 사용하지 마십시오 HttpClient. 참조 : aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
maxshuty

4
System.Net.Http.Formatting을 사용하면 "await 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

HttpClient ()에서 사용할 수있는 PostAsJsonAsync () 메서드를 사용할 수도 있습니다.

   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 19
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.