C #을 사용하여 서버에 JSON을 게시하는 방법은 무엇입니까?


269

사용중인 코드는 다음과 같습니다.

// create a request
HttpWebRequest request = (HttpWebRequest)
WebRequest.Create(url); request.KeepAlive = false;
request.ProtocolVersion = HttpVersion.Version10;
request.Method = "POST";


// turn our request string into a byte stream
byte[] postBytes = Encoding.UTF8.GetBytes(json);

// this is important - make sure you specify type this way
request.ContentType = "application/json; charset=UTF-8";
request.Accept = "application/json";
request.ContentLength = postBytes.Length;
request.CookieContainer = Cookies;
request.UserAgent = currentUserAgent;
Stream requestStream = request.GetRequestStream();

// now send it
requestStream.Write(postBytes, 0, postBytes.Length);
requestStream.Close();

// grab te response and print it out to the console along with the status code
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
string result;
using (StreamReader rdr = new StreamReader(response.GetResponseStream()))
{
    result = rdr.ReadToEnd();
}

return result;

이것을 실행할 때 항상 500 내부 서버 오류가 발생합니다.

내가 뭘 잘못하고 있죠?


1
먼저, 게시하는 데이터가 서버가 기대하는 것이어야합니다.
LB

실제로 잘못된 데이터를 게시 한 것 같습니다 ...
Arsen Zahray

작업의 편의 를 위해 비주얼 스튜디오에 json 라이브러리를 추가 할 수 있습니다
Alireza Tabatabaeian

@Arsen-서버가 잘못된 데이터로 인해 충돌하지 않아야합니다. 버그 보고서를 제출하십시오.
jww

답변:


396

내가하고 일하는 방식은 다음과 같습니다.

var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://url");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";

using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
    string json = "{\"user\":\"test\"," +
                  "\"password\":\"bla\"}";

    streamWriter.Write(json);
}

var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
    var result = streamReader.ReadToEnd();
}

이 작업을보다 간단한 방법으로 수행하기 위해 라이브러리를 작성했습니다. https://github.com/ademargomes/JsonRequest

도움이 되길 바랍니다.


3
json 문자열 줄은 다음과 같아야합니다. string json = "{\"user \ ": \"test \ ","+ "\"password \ ": \"bla \ "}"; \
Dream Lane

3
항상 "application / json"을 사용하십시오 (다른 이유로 text / json이 필요하지 않은 경우 (예 : entwicklungsgedanken.de/2008/06/06/… )). 크 레딩은 stackoverflow.com/questions/477816/…으로 이동합니다 .
Yaniv

34
streamWriter.Flush (); 그리고 streamWriter.Close (); using 블록 안에 있으므로 필요하지 않습니다. using 블록의 끝에서 스트림 작성기는 어쨌든 닫힙니다.
Ruchira

1
JSON을 수동으로 빌드하지 마십시오. JSON 삽입을 허용하는 실수는 쉽습니다.
Florian Winter

5
@ user3772108 stackoverflow.com/a/16380064/2279059를 참조하십시오 . Newtonsoft JSON.Net과 같은 JSON 라이브러리를 사용하고 객체에서 JSON 문자열을 렌더링하거나 직렬화를 사용하십시오. 나는 단순화를 위해 여기에서 생략되었지만 (단순 이득은 최소이지만) 구조화 된 데이터 문자열 (JSON, XML 등 ...)의 포맷은 사소한 시나리오에서도 그렇게하고 사람들이 그러한 코드를 복사하도록 장려하기에는 너무 위험합니다 .
Florian Winter

149

Ademar의 솔루션은 JavaScriptSerializerSerialize메소드를 활용 하여 객체를 JSON으로 암시 적으로 변환하여 제공 할 수 있습니다 .

또한,이 활용할 수 있습니다 using호출 명시 적으로 생략하기 위해 문장의 기본 기능을 Flush하고 Close.

var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://url");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";

using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
    string json = new JavaScriptSerializer().Serialize(new
                {
                    user = "Foo",
                    password = "Baz"
                });

    streamWriter.Write(json);
}

var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
    var result = streamReader.ReadToEnd();
}

1
이 코드와 위의 코드의 차이점은 무엇입니까?
JMK

16
JavaScriptSerializer의 Serialize 메서드를 사용하여 수작업 대신 유효한 JSON을 만듭니다.
Sean Anderson

아래의 Jean F의 답변을 참조하십시오-의견이어야합니다. 내용 유형 application/json이 올바른지 주의 하십시오.
Lucas

@SeanAnderson "원격 서버에 연결할 수 없습니다"오류가 계속 발생합니다.
ralphgabb

3
@LuzanBaral 당신은 단지 어셈블리가 필요합니다 : System.Web.Extensions
Norbrecht

60

HttpClient유형은보다 새로운 구현 WebClient하고 HttpWebRequest.

다음 줄을 사용하면됩니다.

string myJson = "{'Username': 'myusername','Password':'pass'}";
using (var client = new HttpClient())
{
    var response = await client.PostAsync(
        "http://yourUrl", 
         new StringContent(myJson, Encoding.UTF8, "application/json"));
}

여기에 이미지 설명을 입력하십시오

HttpClient두 번 이상 필요한 경우 하나의 인스턴스 만 만들어 재사용하거나 new를 사용하는 것이 좋습니다 HttpClientFactory.


5
HttpClient에 대한 약간의 메모, 일반적인 합의는 그것을 폐기해서는 안된다는 것입니다. IDisposable을 구현하더라도 객체는 스레드로부터 안전하며 재사용 할 수 있습니다. stackoverflow.com/questions/15705092/…
Jean F.

1
@JeanF. 입력 주셔서 감사합니다. 이미 언급했듯이 인스턴스를 하나만 만들거나을 사용해야합니다 HttpClientFactory. 관련 문제의 모든 답변을 읽지는 않았지만 공장을 언급하지 않으므로 업데이트해야한다고 생각합니다.
NtFreX

33

Sean의 게시물 외에도 using 문을 중첩 할 필요는 없습니다. 에 의해 using명시 적으로 할 필요가 호출하지 않도록 StreamWriter는이 플러시되고 블록의 끝에서 폐쇄 Flush()Close()방법 :

var request = (HttpWebRequest)WebRequest.Create("http://url");
request.ContentType = "application/json";
request.Method = "POST";

using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
    string json = new JavaScriptSerializer().Serialize(new
                {
                    user = "Foo",
                    password = "Baz"
                });

    streamWriter.Write(json);
}

var response = (HttpWebResponse)request.GetResponse();
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
        var result = streamReader.ReadToEnd();
}

1
이제이 답변과 Sean Anderson의 답변은 Sean이 자신의 게시물을 수정 한 것과 정확히 동일합니다.
faza

이봐, 정말 대단해. 고맙지 만 json에 자식 노드가 있다면 어떻게 데이터를 전달할 것인가?
user2728409 2016 년

1
시리얼 라이저는 json에서 자식 노드를 처리 할 수 ​​있습니다. 유효한 json 객체 만 제공하면됩니다.
David Clarke

14

비동기식으로 호출 해야하는 경우

var request = HttpWebRequest.Create("http://www.maplegraphservices.com/tokkri/webservices/updateProfile.php?oldEmailID=" + App.currentUser.email) as HttpWebRequest;
            request.Method = "POST";
            request.ContentType = "text/json";
            request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);

private void GetRequestStreamCallback(IAsyncResult asynchronousResult)
    {
        HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
        // End the stream request operation

        Stream postStream = request.EndGetRequestStream(asynchronousResult);


        // Create the post data
        string postData = JsonConvert.SerializeObject(edit).ToString();

        byte[] byteArray = Encoding.UTF8.GetBytes(postData);


        postStream.Write(byteArray, 0, byteArray.Length);
        postStream.Close();

        //Start the web request
        request.BeginGetResponse(new AsyncCallback(GetResponceStreamCallback), request);
    }

    void GetResponceStreamCallback(IAsyncResult callbackResult)
    {
        HttpWebRequest request = (HttpWebRequest)callbackResult.AsyncState;
        HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(callbackResult);
        using (StreamReader httpWebStreamReader = new StreamReader(response.GetResponseStream()))
        {
            string result = httpWebStreamReader.ReadToEnd();
            stat.Text = result;
        }

    }

3
이 솔루션을 게시 해 주셔서 감사합니다. Vivek. 이 시나리오에서 우리는이 게시물에서 다른 솔루션을 시도하고 동기 게시물이 스레드를 차단한다고 가정했기 때문에 응용 프로그램에서 System.Threading 예외를 보았습니다. 귀하의 코드는 우리의 문제를 해결했습니다.
Ken Palmer

바이트로 변환 할 필요는 없습니다. 할 수 있어야하며 postStream.Write(postData);API에 따라 request.ContentType = "application/json";대신 을 사용해야 할 수도 있습니다 text/json.
vapcguy


11

최근에 앱에 모델에서 변환하는 추가 단계와 함께 JSON을 게시하는 훨씬 간단한 방법을 생각해 냈습니다. 컨트롤러가 값을 가져 와서 변환하려면 모델 [JsonObject]를 만들어야합니다.

의뢰:

 var model = new MyModel(); 

 using (var client = new HttpClient())
 {
     var uri = new Uri("XXXXXXXXX"); 
     var json = new JavaScriptSerializer().Serialize(model);
     var stringContent = new StringContent(json, Encoding.UTF8, "application/json");
     var response = await Client.PutAsync(uri,stringContent).Result;
     ...
     ...
  }

모델:

[JsonObject]
[Serializable]
public class MyModel
{
    public Decimal Value { get; set; }
    public string Project { get; set; }
    public string FilePath { get; set; }
    public string FileName { get; set; }
}

서버 측:

[HttpPut]     
public async Task<HttpResponseMessage> PutApi([FromBody]MyModel model)
{
    ...
    ... 
}

6

이 옵션 은 언급되지 않았습니다 :

using (var client = new HttpClient())
{
    client.BaseAddress = new Uri("http://localhost:9000/");
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    var foo = new User
    {
        user = "Foo",
        password = "Baz"
    }

    await client.PostAsJsonAsync("users/add", foo);
}

2
이 옵션은 .Net 4.5.2부터 더 이상 사용할 수 없습니다. 여기를 참조하십시오 stackoverflow.com/a/40525794/2161568
Downhillski

위의 의견에 따라 공감대를 사용할 수 없으므로 답변을 제거해야합니다.
NovaDev

1
모든 사람이 최신 버전의 .net을 사용하는 것은 아니므로 올바른 답변이므로이 답변을 공감할만한 좋은 이유는 아닙니다.
Ellisan

4

이것을 달성하기위한 몇 가지 다른 깨끗한 방법은 다음과 같이 HttpClient를 사용하는 것입니다.

public async Task<HttpResponseMessage> PostResult(string url, ResultObject resultObject)
{
    using (var client = new HttpClient())
    {
        HttpResponseMessage response = new HttpResponseMessage();
        try
        {
            response = await client.PostAsJsonAsync(url, resultObject);
        }
        catch (Exception ex)
        {
            throw ex
        }
        return response;
     }
}

4
그러나 PostAsJsonAsync.NET 4.5.2 이후에는 더 이상 사용할 수 없습니다. PostAsync대신 사용하십시오 . 더 많은
Zachary Keener

HttpClient는 일반적으로 다음 using과 같은 문장 에서 사용되어서는 안됩니다
p3tch

나는 그것이 IDisposable이유 때문에 인터페이스를 구현하는 것 같아요
Dima Daron

4

경고! 나는이 주제에 대해 매우 강한 견해를 가지고 있습니다.

.NET의 기존 웹 클라이언트는 개발자에게 친숙하지 않습니다! WebRequest & WebClient 는 "개발자를 좌절시키는 방법"의 대표적인 예입니다. 그것들은 작업하기에 장황하고 복잡합니다. C #의 간단한 Post 요청 만하면됩니다. HttpClient 는 이러한 문제를 해결하는 데 도움이되지만 여전히 부족합니다. 그 위에 마이크로 소프트의 문서는 나쁘다… 정말로 나쁘다. 기술적 인 내용이 담긴 페이지와 페이지를 탐색하고 싶지 않다면.

구조에 오픈 소스. 대안으로 훌륭한 오픈 소스 무료 NuGet 라이브러리가 3 가지 있습니다. 감사합니다! 이것들은 모두 잘 지원되고 문서화되어 있으며 그렇습니다. 쉬운-수정 ... 슈퍼 쉬운-작업하기 쉽습니다.

  • ServiceStack.Text 빠르고 가볍고 탄력적입니다.
  • RestSharp 간단한 REST 및 HTTP API 클라이언트
  • Flurl- 유창하고 이식 가능하며 테스트 가능한 HTTP 클라이언트 라이브러리

그들 사이에는 많지 않지만 ServiceStack.Text에 약간의 가장자리를 줄 것입니다 ...

  • Github의 별 은 거의 같습니다.
  • 미결 문제 및 중요한 문제가 얼마나 빨리 종료 되었습니까? ServiceStack은 가장 빠른 문제 해결 및 공개 된 문제가없는 상을 수상했습니다.
  • 선적 서류 비치? 모두 훌륭한 문서를 가지고 있습니다. 그러나 ServiceStack은 다음 단계로 나아가며 문서화를위한 '황금 표준'으로 유명합니다.

Ok-JSON의 Post Request는 ServiceStack.Text 내에서 어떻게 생겼습니까?

var response = "http://example.org/login"
    .PostJsonToUrl(new Login { Username="admin", Password="mypassword" });

그것은 한 줄의 코드입니다. 간결하고 쉬운! 위의 내용을 .NET의 Http 라이브러리와 비교하십시오.


3

마침내 .Result 를 포함시켜 동기화 모드에서 호출했습니다.

HttpResponseMessage response = null;
try
{
    using (var client = new HttpClient())
    {
       response = client.PostAsync(
        "http://localhost:8000/....",
         new StringContent(myJson,Encoding.UTF8,"application/json")).Result;
    if (response.IsSuccessStatusCode)
        {
            MessageBox.Show("OK");              
        }
        else
        {
            MessageBox.Show("NOK");
        }
    }
}
catch (Exception ex)
{
    MessageBox.Show("ERROR");
}

1

var data = Encoding.ASCII.GetBytes(json);

byte[] postBytes = Encoding.UTF8.GetBytes(json);

UFT8 대신 ASCII 사용


2
꽤 나쁜 생각처럼 들리는데 뭔가 빠졌습니까?
CyberFox

JSON에는 UTF8 문자가 포함될 수 있습니다. 이것은 끔찍한 생각처럼 보입니다.
Adrian Smith
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.