HTTP POST 웹 요청을하는 방법


1132

정식
방법을 사용하여 HTTP 요청을하고 데이터를 보내려면 어떻게 POST 해야합니까?

GET요청을 할 수는 있지만 요청하는 방법을 모릅니다 POST.

답변:


2164

HTTP GETPOST요청 을 수행하는 몇 가지 방법이 있습니다 .


방법 A : HttpClient (권장)

가능 : .NET Framework 4.5+, .NET Standard 1.1+, .NET Core 1.0+.

현재 선호되는 방식이며 비동기식 및 고성능입니다. 대부분의 경우 내장 버전을 사용하지만 아주 오래된 플랫폼에는 NuGet 패키지가 있습니다.

using System.Net.Http;

설정

HttpClient특별한 이유가없는 한 응용 프로그램 수명 동안 인스턴스를 생성 하고 공유하는 것이 좋습니다 .

private static readonly HttpClient client = new HttpClient();

참조 HttpClientFactoryA에 대한 의존성 주입 솔루션입니다.


  • POST

    var values = new Dictionary<string, string>
    {
        { "thing1", "hello" },
        { "thing2", "world" }
    };
    
    var content = new FormUrlEncodedContent(values);
    
    var response = await client.PostAsync("http://www.example.com/recepticle.aspx", content);
    
    var responseString = await response.Content.ReadAsStringAsync();
    
  • GET

    var responseString = await client.GetStringAsync("http://www.example.com/recepticle.aspx");

방법 B : 타사 라이브러리

RestSharp

  • POST

     var client = new RestClient("http://example.com");
     // client.Authenticator = new HttpBasicAuthenticator(username, password);
     var request = new RestRequest("resource/{id}");
     request.AddParameter("thing1", "Hello");
     request.AddParameter("thing2", "world");
     request.AddHeader("header", "value");
     request.AddFile("file", path);
     var response = client.Post(request);
     var content = response.Content; // Raw content as string
     var response2 = client.Post<Person>(request);
     var name = response2.Data.Name;
    

Flurl.Http

유창한 API를 사용하고, 도우미를 테스트하고, HttpClient를 사용하며, 이식성이 뛰어난 최신 라이브러리입니다. NuGet을 통해 사용할 수 있습니다 .

    using Flurl.Http;

  • POST

    var responseString = await "http://www.example.com/recepticle.aspx"
        .PostUrlEncodedAsync(new { thing1 = "hello", thing2 = "world" })
        .ReceiveString();
    
  • GET

    var responseString = await "http://www.example.com/recepticle.aspx"
        .GetStringAsync();
    

방법 C : HttpWebRequest (새 작업에는 권장되지 않음)

가능 : .NET Framework 1.1+, .NET Standard 2.0+, .NET Core 1.0+. .NET Core에서는 대부분 호환성을 위해 랩핑 HttpClient하고 성능이 떨어지며 새로운 기능을 얻지 못합니다.

using System.Net;
using System.Text;  // For class Encoding
using System.IO;    // For StreamReader

  • POST

    var request = (HttpWebRequest)WebRequest.Create("http://www.example.com/recepticle.aspx");
    
    var postData = "thing1=" + Uri.EscapeDataString("hello");
        postData += "&thing2=" + Uri.EscapeDataString("world");
    var data = Encoding.ASCII.GetBytes(postData);
    
    request.Method = "POST";
    request.ContentType = "application/x-www-form-urlencoded";
    request.ContentLength = data.Length;
    
    using (var stream = request.GetRequestStream())
    {
        stream.Write(data, 0, data.Length);
    }
    
    var response = (HttpWebResponse)request.GetResponse();
    
    var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
    
  • GET

    var request = (HttpWebRequest)WebRequest.Create("http://www.example.com/recepticle.aspx");
    
    var response = (HttpWebResponse)request.GetResponse();
    
    var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
    

방법 D : WebClient (새 작업에 권장되지 않음)

이 래퍼 HttpWebRequest입니다. 와 비교하십시오HttpClient .

가능 : .NET Framework 1.1+, NET Standard 2.0+,.NET Core 2.0+

using System.Net;
using System.Collections.Specialized;

  • POST

    using (var client = new WebClient())
    {
        var values = new NameValueCollection();
        values["thing1"] = "hello";
        values["thing2"] = "world";
    
        var response = client.UploadValues("http://www.example.com/recepticle.aspx", values);
    
        var responseString = Encoding.Default.GetString(response);
    }
    
  • GET

    using (var client = new WebClient())
    {
        var responseString = client.DownloadString("http://www.example.com/recepticle.aspx");
    }
    

2
@ 로이드 :HttpWebResponse response = (HttpWebResponse)HttpWReq.GetResponse();
에반 Mulawski

2
왜 ASCII를 사용합니까? UTF-8이 포함 된 XML이 필요한 경우 어떻게합니까?
게로

8
나는 죽은 말을이기는 것을 싫어하지만 당신은해야합니다response.Result.Content.ReadAsStringAsync()
David S.

13
왜 WebRequest와 WebClient가 레거시라고 말했습니까? MSDN은 더 이상 사용되지 않는다고 말하지 않습니다. 뭔가 빠졌습니까?
Hiep

23
@ Hiep : 더 이상 사용되지 않으며 웹 요청을하는 새로운 방법 (대부분의 경우 더 좋고 유연합니다)이 있습니다. 제 생각에는 간단하고 중요하지 않은 작업의 경우 이전 방식은 괜찮습니다.하지만 가장 편한 것은 당신에게 달려 있습니다.
Evan Mulawski

384

간단한 GET 요청

using System.Net;

...

using (var wb = new WebClient())
{
    var response = wb.DownloadString(url);
}

간단한 POST 요청

using System.Net;
using System.Collections.Specialized;

...

using (var wb = new WebClient())
{
    var data = new NameValueCollection();
    data["username"] = "myUser";
    data["password"] = "myPassword";

    var response = wb.UploadValues(url, "POST", data);
    string responseInString = Encoding.UTF8.GetString(response);
}

15
+1 정기적 인 POST의 경우 짧은 코드 조각을 갖는 것이 좋습니다.
user_v

3
Tim-해결할 수없는 리터럴을 마우스 오른쪽 버튼으로 클릭하면 Resolve 상황에 맞는 메뉴가 있으며 여기에는 Using 문을 추가하는 작업이 포함되어 있습니다. 상황에 맞는 해결 메뉴가 표시되지 않으면 먼저 참조를 추가해야합니다.
카메론 윌비

훨씬 더 간단하고 명확하기 때문에 귀하의 답변을 잘 받아 들였습니다.
Hooch

13
POST 요청에 대한 응답 변수가 바이트 배열임을 추가하고 싶습니다. 문자열 응답을 얻으려면 Encoding.ASCII.GetString (response); (System.Text 사용)
Sindre

1
또한 다음과 같이 약간 복잡한 배열 $ _POST [ 'user']를 보낼 수 있습니다. data [ "user [username]"] = "myUsername"; data [ "user [password]"] = "myPassword";
Bimal Poudel

68

MSDN 에는 샘플이 있습니다.

using System;
using System.IO;
using System.Net;
using System.Text;

namespace Examples.System.Net
{
    public class WebRequestPostExample
    {
        public static void Main()
        {
            // Create a request using a URL that can receive a post. 
            WebRequest request = WebRequest.Create("http://www.contoso.com/PostAccepter.aspx");
            // Set the Method property of the request to POST.
            request.Method = "POST";
            // Create POST data and convert it to a byte array.
            string postData = "This is a test that posts this string to a Web server.";
            byte[] byteArray = Encoding.UTF8.GetBytes(postData);
            // Set the ContentType property of the WebRequest.
            request.ContentType = "application/x-www-form-urlencoded";
            // Set the ContentLength property of the WebRequest.
            request.ContentLength = byteArray.Length;
            // Get the request stream.
            Stream dataStream = request.GetRequestStream();
            // Write the data to the request stream.
            dataStream.Write(byteArray, 0, byteArray.Length);
            // Close the Stream object.
            dataStream.Close();
            // Get the response.
            WebResponse response = request.GetResponse();
            // Display the status.
            Console.WriteLine(((HttpWebResponse)response).StatusDescription);
            // Get the stream containing content returned by the server.
            dataStream = response.GetResponseStream();
            // Open the stream using a StreamReader for easy access.
            StreamReader reader = new StreamReader(dataStream);
            // Read the content.
            string responseFromServer = reader.ReadToEnd();
            // Display the content.
            Console.WriteLine(responseFromServer);
            // Clean up the streams.
            reader.Close();
            dataStream.Close();
            response.Close();
        }
    }
}

어떤 이유로 많은 양의 데이터를 보낼 때 작동하지
않았습니다.

26

이것은 JSON 형식으로 데이터를 송수신하는 완전한 작동 예입니다. Visual Studio 2013 Express Edition을 사용했습니다.

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web.Script.Serialization;

namespace ConsoleApplication1
{
    class Customer
    {
        public string Name { get; set; }
        public string Address { get; set; }
        public string Phone { get; set; }
    }

    public class Program
    {
        private static readonly HttpClient _Client = new HttpClient();
        private static JavaScriptSerializer _Serializer = new JavaScriptSerializer();

        static void Main(string[] args)
        {
            Run().Wait();
        }

        static async Task Run()
        {
            string url = "http://www.example.com/api/Customer";
            Customer cust = new Customer() { Name = "Example Customer", Address = "Some example address", Phone = "Some phone number" };
            var json = _Serializer.Serialize(cust);
            var response = await Request(HttpMethod.Post, url, json, new Dictionary<string, string>());
            string responseText = await response.Content.ReadAsStringAsync();

            List<YourCustomClassModel> serializedResult = _Serializer.Deserialize<List<YourCustomClassModel>>(responseText);

            Console.WriteLine(responseText);
            Console.ReadLine();
        }

        /// <summary>
        /// Makes an async HTTP Request
        /// </summary>
        /// <param name="pMethod">Those methods you know: GET, POST, HEAD, etc...</param>
        /// <param name="pUrl">Very predictable...</param>
        /// <param name="pJsonContent">String data to POST on the server</param>
        /// <param name="pHeaders">If you use some kind of Authorization you should use this</param>
        /// <returns></returns>
        static async Task<HttpResponseMessage> Request(HttpMethod pMethod, string pUrl, string pJsonContent, Dictionary<string, string> pHeaders)
        {
            var httpRequestMessage = new HttpRequestMessage();
            httpRequestMessage.Method = pMethod;
            httpRequestMessage.RequestUri = new Uri(pUrl);
            foreach (var head in pHeaders)
            {
                httpRequestMessage.Headers.Add(head.Key, head.Value);
            }
            switch (pMethod.Method)
            {
                case "POST":
                    HttpContent httpContent = new StringContent(pJsonContent, Encoding.UTF8, "application/json");
                    httpRequestMessage.Content = httpContent;
                    break;

            }

            return await _Client.SendAsync(httpRequestMessage);
        }
    }
}

8

여기에 정말 좋은 답변이 있습니다. WebClient ()를 사용하여 헤더를 설정하는 다른 방법을 게시하겠습니다. 또한 API 키를 설정하는 방법을 보여줄 것입니다.

        var client = new WebClient();
        string credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes(userName + ":" + passWord));
        client.Headers[HttpRequestHeader.Authorization] = $"Basic {credentials}";
        //If you have your data stored in an object serialize it into json to pass to the webclient with Newtonsoft's JsonConvert
        var encodedJson = JsonConvert.SerializeObject(newAccount);

        client.Headers.Add($"x-api-key:{ApiKey}");
        client.Headers.Add("Content-Type:application/json");
        try
        {
            var response = client.UploadString($"{apiurl}", encodedJson);
            //if you have a model to deserialize the json into Newtonsoft will help bind the data to the model, this is an extremely useful trick for GET calls when you have a lot of data, you can strongly type a model and dump it into an instance of that class.
            Response response1 = JsonConvert.DeserializeObject<Response>(response);

감사합니다 BTW 위의 헤더 속성 설정 기술은 이전 (더 이상 사용되지 않습니까?) HttpWebRequest 접근 방식에서도 작동합니다. 예 : myReq.Headers [HttpRequestHeader.Authorization] = $ "기본 {신임 정보}";
Zeek2

6

이 솔루션은 표준 .NET 호출 만 사용합니다.

테스트 :

  • 엔터프라이즈 WPF 응용 프로그램에서 사용 중입니다. UI 차단을 피하기 위해 async / await를 사용합니다.
  • .NET 4.5 이상과 호환됩니다.
  • 매개 변수없이 테스트되었습니다 (장면 뒤에 "GET"필요).
  • 매개 변수로 테스트했습니다 (장면 뒤의 "POST"필요).
  • Google과 같은 표준 웹 페이지에서 테스트했습니다.
  • 내부 Java 기반 웹 서비스로 테스트되었습니다.

참고:

// Add a Reference to the assembly System.Web

암호:

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;

private async Task<WebResponse> CallUri(string url, TimeSpan timeout)
{
    var uri = new Uri(url);
    NameValueCollection rawParameters = HttpUtility.ParseQueryString(uri.Query);
    var parameters = new Dictionary<string, string>();
    foreach (string p in rawParameters.Keys)
    {
        parameters[p] = rawParameters[p];
    }

    var client = new HttpClient { Timeout = timeout };
    HttpResponseMessage response;
    if (parameters.Count == 0)
    {
        response = await client.GetAsync(url);
    }
    else
    {
        var content = new FormUrlEncodedContent(parameters);
        string urlMinusParameters = uri.OriginalString.Split('?')[0]; // Parameters always follow the '?' symbol.
        response = await client.PostAsync(urlMinusParameters, content);
    }
    var responseString = await response.Content.ReadAsStringAsync();

    return new WebResponse(response.StatusCode, responseString);
}

private class WebResponse
{
    public WebResponse(HttpStatusCode httpStatusCode, string response)
    {
        this.HttpStatusCode = httpStatusCode;
        this.Response = response;
    }
    public HttpStatusCode HttpStatusCode { get; }
    public string Response { get; }
}

매개 변수없이 호출하려면 (장면 뒤에 "GET"사용) :

 var timeout = TimeSpan.FromSeconds(300);
 WebResponse response = await this.CallUri("http://www.google.com/", timeout);
 if (response.HttpStatusCode == HttpStatusCode.OK)
 {
     Console.Write(response.Response); // Print HTML.
 }

매개 변수를 사용하여 호출하려면 (장면 뒤에 "POST"를 사용) :

 var timeout = TimeSpan.FromSeconds(300);
 WebResponse response = await this.CallUri("http://example.com/path/to/page?name=ferret&color=purple", timeout);
 if (response.HttpStatusCode == HttpStatusCode.OK)
 {
     Console.Write(response.Response); // Print HTML.
 }

6

지금까지 찾은 간단한 (한 줄짜리, 오류 확인, 응답 대기 없음) 솔루션 :

(new WebClient()).UploadStringAsync(new Uri(Address), dataString);‏

주의해서 사용하십시오!


5
꽤 나쁘다. 어떤 종류의 오류 처리가 없으며 디버깅이 어려우므로 권장하지 않습니다. 또한이 질문에 이미 큰 대답이 있습니다.
Hooch

1
@Hooch 다른 사람들은이 유형의 답변에 관심이있을 수도 있습니다.
Mitulát báti

합의, 이것이 유일하게 유용한 문맥은 코드 골프와 누가 C #에서 골프를 하는가입니다.)
Extragorey

4

Windows.Web.Http 네임 스페이스를 사용할 때 FormUrlEncodedContent 대신 POST의 경우 HttpFormUrlEncodedContent를 작성합니다. 또한 응답은 HttpResponseMessage 유형입니다. 나머지는 Evan Mulawski가 기록한대로입니다.


4

유창한 API를 좋아한다면 Tiny.RestClient 를 사용할 수 있습니다 . NuGet 에서 사용할 수 있습니다 .

var client = new TinyRestClient(new HttpClient(), "http://MyAPI.com/api");
// POST
var city = new City() { Name = "Paris", Country = "France" };
// With content
var response = await client.PostRequest("City", city)
                           .ExecuteAsync<bool>();

1

이것이 왜 사소하지 않은가? 요청을 수행하는 것은 특히 결과를 처리하지 않으며 일부 .NET 버그가있는 것처럼 보입니다 -HttpClient의 버그 참조 GetAsync는 TaskCanceledException이 아닌 WebException을 throw해야합니다.

이 코드로 끝났습니다.

static async Task<(bool Success, WebExceptionStatus WebExceptionStatus, HttpStatusCode? HttpStatusCode, string ResponseAsString)> HttpRequestAsync(HttpClient httpClient, string url, string postBuffer = null, CancellationTokenSource cts = null) {
    try {
        HttpResponseMessage resp = null;

        if (postBuffer is null) {
            resp = cts is null ? await httpClient.GetAsync(url) : await httpClient.GetAsync(url, cts.Token);

        } else {
            using (var httpContent = new StringContent(postBuffer)) {
                resp = cts is null ? await httpClient.PostAsync(url, httpContent) : await httpClient.PostAsync(url, httpContent, cts.Token);
            }
        }

        var respString = await resp.Content.ReadAsStringAsync();
        return (resp.IsSuccessStatusCode, WebExceptionStatus.Success, resp.StatusCode, respString);

    } catch (WebException ex) {
        WebExceptionStatus status = ex.Status;
        if (status == WebExceptionStatus.ProtocolError) {
            // Get HttpWebResponse so that you can check the HTTP status code.
            using (HttpWebResponse httpResponse = (HttpWebResponse)ex.Response) {
                return (false, status, httpResponse.StatusCode, httpResponse.StatusDescription);
            }
        } else {
            return (false, status, null, ex.ToString()); 
        }

    } catch (TaskCanceledException ex) {
        if (cts is object && ex.CancellationToken == cts.Token) {
            // a real cancellation, triggered by the caller
            return (false, WebExceptionStatus.RequestCanceled, null, ex.ToString());
        } else {
            // a web request timeout (possibly other things!?)
            return (false, WebExceptionStatus.Timeout, null, ex.ToString());
        }

    } catch (Exception ex) {
        return (false, WebExceptionStatus.UnknownError, null, ex.ToString());
    }
}

이것은 postBuffernull인지 아닌지에 따라 GET 또는 POST를 수행합니다.

성공이 맞다면 응답은 ResponseAsString

성공이 false 인 경우 당신은 확인하실 수 있습니다 WebExceptionStatus, HttpStatusCode그리고 ResponseAsString무엇이 잘못되었는지 확인하려고.


0

.net 코어에서 다음 코드로 포스트 콜을 할 수 있습니다. 여기에서는이 코드에 몇 가지 추가 기능을 추가하여 코드가 프록시 뒤에서 작동하고 네트워크 자격 증명이있는 경우 코드를 변경할 수 있다고 언급했습니다. 당신의 메시지. 이것이 모든 것을 설명하고 코딩에 도움이되기를 바랍니다.

HttpClient client = GetHttpClient(_config);

        if (headers != null)
        {
            foreach (var header in headers)
            {
                client.DefaultRequestHeaders.TryAddWithoutValidation(header.Key, header.Value);
            }
        }

        client.BaseAddress = new Uri(baseAddress);

        Encoding encoding = Encoding.UTF8;


        var result = await client.PostAsync(url, new StringContent(body, encoding, "application/json")).ConfigureAwait(false);
        if (result.IsSuccessStatusCode)
        {
            return new RequestResponse { severity = "Success", httpResponse = result.Content.ReadAsStringAsync().Result, StatusCode = result.StatusCode };
        }
        else
        {
            return new RequestResponse { severity = "failure", httpResponse = result.Content.ReadAsStringAsync().Result, StatusCode = result.StatusCode };
        }


 public HttpClient GetHttpClient(IConfiguration _config)
        {
            bool ProxyEnable = Convert.ToBoolean(_config["GlobalSettings:ProxyEnable"]);

            HttpClient client = null;
            if (!ProxyEnable)
            {
                client = new HttpClient();
            }
            else
            {
                string ProxyURL = _config["GlobalSettings:ProxyURL"];
                string ProxyUserName = _config["GlobalSettings:ProxyUserName"];
                string ProxyPassword = _config["GlobalSettings:ProxyPassword"];
                string[] ExceptionURL = _config["GlobalSettings:ExceptionURL"].Split(';');
                bool BypassProxyOnLocal = Convert.ToBoolean(_config["GlobalSettings:BypassProxyOnLocal"]);
                bool UseDefaultCredentials = Convert.ToBoolean(_config["GlobalSettings:UseDefaultCredentials"]);

                WebProxy proxy = new WebProxy
                {
                    Address = new Uri(ProxyURL),
                    BypassProxyOnLocal = BypassProxyOnLocal,
                    UseDefaultCredentials = UseDefaultCredentials,
                    BypassList = ExceptionURL,
                    Credentials = new NetworkCredential(ProxyUserName, ProxyPassword)

                };

                HttpClientHandler handler = new HttpClientHandler { Proxy = proxy };
                client = new HttpClient(handler,true);
            }
            return client;
        }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.