HTTP POST web isteği nasıl yapılır


1133

Kurallı Yöntemi
kullanarak nasıl HTTP isteği yapabilir ve bazı verileri gönderebilirim POST ?

Bir GETtalepte bulunabilirim, ancak nasıl POSTtalepte bulunacağım hakkında hiçbir fikrim yok .

Yanıtlar:


2165

HTTP GETve POSTistekleri gerçekleştirmenin birkaç yolu vardır :


Yöntem A: HttpClient (Tercih Edilen)

Mevcut: .NET Framework 4.5+, .NET Standard 1.1+, .NET Core 1.0+.

Şu anda tercih edilen yaklaşımdır ve asenkron ve yüksek performanstır. Çoğu durumda yerleşik sürümü kullanın, ancak çok eski platformlar için bir NuGet paketi vardır .

using System.Net.Http;

Kurmak

HttpClientUygulamanızın ömrü boyunca bir tane oluşturmanız ve bunu yapmamanız için belirli bir nedeniniz yoksa paylaşmanız önerilir .

private static readonly HttpClient client = new HttpClient();

Bağımlılık enjeksiyon çözeltisi HttpClientFactoryiçin bakınız .


  • 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");

Yöntem B: Üçüncü Taraf Kütüphaneleri

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

Akıcı bir API sporu yapan yeni bir kütüphane, yardımcıları test ediyor, kaputun altında HttpClient kullanıyor ve taşınabilir. NuGet aracılığıyla edinilebilir .

    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();
    

Yöntem C: HttpWebRequest (yeni çalışma için önerilmez)

Mevcut: .NET Framework 1.1+, .NET Standard 2.0+, .NET Core 1.0+. .NET Core'da çoğunlukla uyumluluk içindir - sarar HttpClient, daha az performans gösterir ve yeni özellikler elde etmez.

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();
    

Yöntem D: WebClient (Yeni iş için önerilmez)

Bu bir sargı HttpWebRequest. İle karşılaştırınHttpClient .

Mevcut: .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
@Lloyd:HttpWebResponse response = (HttpWebResponse)HttpWReq.GetResponse();
Evan Mulawski

2
Neden ASCII kullanıyorsunuz? Birisi UTF-8 ile bir xml'ye ihtiyaç duyarsa ne olur?
Gero

8
Ölü bir atı response.Result.Content.ReadAsStringAsync()
David S.

13
neden WebRequest ve WebClient'ın eski olduğunu söylediniz? MSDN, kullanımdan kaldırıldığını veya başka bir şey olduğunu söylemez. Bir şey mi kaçırıyorum?
Hiep

23
@Hiep: Kullanımdan kaldırılmadı, web istekleri yapmanın sadece daha yeni (ve çoğu durumda, daha iyi ve daha esnek) yolları var. Bence, basit, kritik olmayan operasyonlar için eski yollar gayet iyi - ama size ve en rahat olduğunuz şey size kalmış.
Evan Mulawski

384

Basit GET isteği

using System.Net;

...

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

Basit POST isteği

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 normal şeyler için böyle kısa bir kod parçasına sahip olmak harika.
user_v

3
Tim - Çözülemeyen bir değişmez değeri sağ tıklarsanız, Sizin için Kullanma ifadelerini eklemek üzere eylemler içeren Bağlamı çöz menüsünü bulacaksınız. Bağlamı çöz menüsü görünmüyorsa, önce referans eklemeniz gerektiği anlamına gelir.
Cameron Wilby

Cevabınızı iyi olarak kabul ettim çünkü çok daha basit ve net.
Hooch

13
POST isteği için yanıt değişkeni bir bayt dizisi olduğunu eklemek istiyorum. Dize yanıtını almak için sadece Encoding.ASCII.GetString (response); (System.Text kullanarak)
Sindre

1
Ayrıca, biraz karmaşık bir dizi $ _POST ['user'] şu şekilde gönderebilirsiniz: data ["user [kullanıcı adı]"] = "myUsername"; data ["kullanıcı [şifre]"] = "Parolam";
Bimal Poudel

68

MSDN'de bir örnek var.

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();
        }
    }
}

Nedense büyük miktarda veri gönderirken işe yaramadı
AnKing

26

Bu, JSON biçiminde veri gönderme / alma işleminin tam bir örneğidir, Visual Studio 2013 Express Edition'ı kullandım:

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

Burada gerçekten iyi cevaplar var. WebClient () ile başlıklarınızı ayarlamak için farklı bir yol yayınlayayım. Bir API anahtarının nasıl ayarlanacağını da göstereceğim.

        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);

Yararlı, teşekkürler. BTW Üstbilgi özelliklerini ayarlamak için yukarıdaki teknik, daha eski (kullanımdan kaldırılmış?), HttpWebRequest yaklaşımı için de işe yarar. örneğin myReq.Headers [HttpRequestHeader.Authorization] = $ "Temel {kimlik bilgileri}";
Zeek2

6

Bu çözüm, standart .NET çağrılarından başka bir şey kullanmaz.

Test:

  • Bir kurumsal WPF uygulamasında kullanımda. Kullanıcı arayüzünü engellememek için zaman uyumsuz / beklemede kullanır.
  • .NET 4.5+ ile uyumludur.
  • Herhangi bir parametre olmadan test edilmiştir (perde arkasında bir "GET" gerektirir).
  • Parametrelerle test edildi (perde arkasında bir "POST" gerektirir).
  • Google gibi standart bir web sayfasıyla test edilmiştir.
  • Dahili Java tabanlı bir web servisiyle test edilmiştir.

Referans:

// Add a Reference to the assembly System.Web

Kod:

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; }
}

Parametresiz aramak için (perde arkasında "GET" kullanır):

 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.
 }

Parametrelerle aramak için (sahnelerin arkasında bir "POST" kullanır):

 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

Şimdiye kadar bulduğum basit (tek katmanlı, hata kontrolü yok, yanıt beklemek yok) çözümü:

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

Dikkatle kullanın!


5
Bu oldukça kötü. Herhangi bir hata işleme ve hata ayıklama ağrı olduğu için tavsiye etmiyorum. Ayrıca bu soruya zaten büyük bir cevap var.
Hooch

1
@Hooch diğerleri en iyi cevap olmasa bile bu tür cevaplarla ilgilenebilir.
Mitulát báti

Kabul, bu yararlı olacağını tek bağlam kod golf ve kim C # çoraplar;)
Extragorey

4

Kullanırken Windows.Web.Http ad, POST yerine FormUrlEncodedContent için biz HttpFormUrlEncodedContent yazın. Ayrıca yanıt HttpResponseMessage türüdür. Gerisi Evan Mulawski'nin yazdığı gibi.


4

Eğer akıcı bir API istiyorsanız Tiny.RestClient kullanabilirsiniz . NuGet'te mevcut .

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

Bu neden tamamen önemsiz değil? İsteği yapmak ve özellikle sonuçlarla uğraşmıyor ve bazı .NET hataları da var gibi görünüyor - HttpClient'teki Bug'a bakın.

Bu kod ile sona erdi:

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());
    }
}

Bu bir GET veya POST yapacak postBuffernull olup olmadığına bağlıdır

Başarı doğruysa cevap o zaman ResponseAsString

Başarı sahte olup olmadığını kontrol edebilirsiniz WebExceptionStatus, HttpStatusCodeve ResponseAsStringneyin yanlış gittiğini görmeye çalışmak.


0

.Net çekirdeğinde aşağıdaki kodla arama sonrası yapabilirsiniz, burada kodun bir proxy arkasında çalışmasını ve varsa ağ kimlik bilgileriyle çalışmasını sağlamak için bu koda bazı ekstra özellikler ekledim, ayrıca burada kodlamayı değiştirebileceğinizi de belirtiyorum Mesajın. Umarım bu her şeyi açıklar ve kodlamaya yardımcı olur.

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;
        }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.