개체를 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 입력을 기다리므로 json을 올바르게 FormUrlEncodedContent보내야 raw합니다. 그러나 어떻게 이것을 할 수 Microsoft.Net.Http있습니까? 감사.


귀하의 질문을 이해하면 형식 인코딩 된 콘텐츠 대신 JSON 콘텐츠를 전송하고 싶습니까 (확장하면 익명 유형을 해당 콘텐츠에 JSON으로 직렬화하려는 경우)?
CodingGorilla

@CodingGorilla yes는 익명 유형입니다.
IlDrugo 2014

3
미래의 리더를위한 보조 노트로서, 사용하지 않는 using를 들어 HttpClient. aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
maxshuty

2
using사용해서는 안되는 Microsoft의 참고 사항 : 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 콘텐츠)

당신이 통과 할 수있는 동안 따라서, objectPostAsync이 유형이어야 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여기서하는 것처럼 속성을 호출하면 데드락과 같은 나쁜 부작용 이 발생할 수 있으므로주의해야합니다.


좋아요 아주 명확합니다. 이 답변에 감사드립니다. 질문 : a POST, PUT, DELETE가 수행 될 때 일반적으로 API return TRUE, 메서드를으로 선언 string했지만 할 때 : return result;I get : Can't Convert HttpResponseMessage in string, 메서드 선언을 변경해야합니까? 다른 클래스 메서드에서 나중에 역 직렬화해야하므로 문자열 응답이 필요합니다.
IlDrugo

2
응답 본문을 역 직렬화해야하는 경우 질문에있는 방식 (사용 result.Content.ReadAsStringAsync()) 으로 문자열을 반환하는 것이 좋습니다 . 애플리케이션 구조에 따라 Content헤더를 검사하여 conent 유형 (예 : 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

이제해야 할 일은 문자열을 post 메소드에 전달하는 것입니다.

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

C # 코드에서 vb의 문자열 결과를 얻을 수 있습니까? 나는 그것이 매우 유사하다는 것을 알았다 ....
gumuruh

42

간단한 해결책은 NuGet 에서 사용하는 Microsoft ASP.NET Web API 2.2 Client것 입니다.

그런 다음 간단하게 수행 할 수 있으며 객체를 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

25

이제 .NET Standard또는 사용 하는 더 간단한 방법이 있습니다 .NET Core.

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

참고 :JsonMediaTypeFormatter 클래스 를 사용 하려면 Microsoft.AspNet.WebApi.ClientNuGet 패키지 를 설치해야합니다. NuGet 패키지는 직접 설치하거나 Microsoft.AspNetCore.App.

이 서명을 사용하면 HttpClient.PostAsync모든 객체를 전달할 수 있으며은 JsonMediaTypeFormatter자동으로 직렬화 등을 처리합니다.

응답을 사용 HttpContent.ReadAsAsync<T>하면 응답 콘텐츠를 예상하는 유형으로 역 직렬화하는 데 사용할 수 있습니다 .

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

1
어떤 버전의 .net을 사용하고 있습니까? 내 버전이 System.Net.Http 네임 스페이스에서 "Formatting"을 찾을 수 없습니다
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.