So stellen Sie eine HTTP-POST-Webanforderung


1133

Canonical
Wie kann ich mit der Methode eine HTTP-Anfrage stellen und einige Daten senden POST ?

Ich kann eine GETAnfrage stellen, habe aber keine Ahnung, wie ich eine POSTAnfrage stellen soll.

Antworten:


2165

Es gibt verschiedene Möglichkeiten, HTTP GETund POSTAnforderungen auszuführen :


Methode A: HttpClient (bevorzugt)

Erhältlich in: .NET Framework 4.5+, .NET Standard 1.1+, .NET Core 1.0+.

Dies ist derzeit der bevorzugte Ansatz und ist asynchron und leistungsstark. Verwenden Sie in den meisten Fällen die integrierte Version, aber für sehr alte Plattformen gibt es ein NuGet-Paket .

using System.Net.Http;

Installieren

Es wird empfohlen , eine HttpClientfür die Lebensdauer Ihrer Anwendung zu instanziieren und zu teilen, es sei denn, Sie haben einen bestimmten Grund, dies nicht zu tun.

private static readonly HttpClient client = new HttpClient();

Siehe HttpClientFactoryfür eine Abhängigkeitsinjektionslösung .


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

Methode B: Bibliotheken von Drittanbietern

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

Es handelt sich um eine neuere Bibliothek mit einer fließenden API, die Testhilfen testet, HttpClient unter der Haube verwendet und portabel ist. Es ist über NuGet erhältlich .

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

Methode C: HttpWebRequest (nicht empfohlen für neue Arbeiten)

Erhältlich in: .NET Framework 1.1+, .NET Standard 2.0+, .NET Core 1.0+. In .NET Core dient dies hauptsächlich der Kompatibilität - es wird umbrochen HttpClient, ist weniger leistungsfähig und erhält keine neuen Funktionen.

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

Methode D: WebClient (Nicht empfohlen für neue Arbeiten)

Dies ist ein Wrapper herum HttpWebRequest. Vergleiche mitHttpClient .

Erhältlich in: .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
Warum verwenden Sie überhaupt ASCII? Was ist, wenn jemand eine XML mit UTF-8 benötigt?
Gero

8
Ich hasse es, ein totes Pferd zu schlagen, aber du solltest es tunresponse.Result.Content.ReadAsStringAsync()
David S.

13
Warum haben Sie gesagt, dass WebRequest und WebClient Legacy sind? MSDN sagt nicht, dass sie veraltet sind oder so. Vermisse ich etwas
Hiep

23
@Hiep: Sie sind nicht veraltet, es gibt nur neuere (und in den meisten Fällen bessere und flexiblere) Möglichkeiten, Webanfragen zu stellen. Meiner Meinung nach sind für einfache, unkritische Operationen die alten Methoden in Ordnung - aber es liegt an Ihnen und dem, was Sie am besten können.
Evan Mulawski

384

Einfache GET-Anfrage

using System.Net;

...

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

Einfache POST-Anfrage

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 Für normale POST-Inhalte ist es großartig, einen so kurzen Code zu haben.
user_v

3
Tim - Wenn Sie mit der rechten Maustaste auf das Literal klicken, das nicht aufgelöst werden kann, finden Sie ein Kontextmenü zum Auflösen, das Aktionen zum Hinzufügen der Using-Anweisungen für Sie enthält. Wenn das Kontextmenü "Auflösen" nicht angezeigt wird, müssen Sie zuerst Referenzen hinzufügen.
Cameron Wilby

Ich habe Ihre Antwort als gut akzeptiert, weil sie viel einfacher und klarer ist.
Hooch

13
Ich möchte hinzufügen, dass die Antwortvariable für die POST-Anforderung ein Byte-Array ist. Um die Zeichenfolgenantwort zu erhalten, führen Sie einfach Encoding.ASCII.GetString (Antwort) aus. (mit System.Text)
Sindre

1
Außerdem können Sie ein etwas komplexes Array $ _POST ['user'] senden als: data ["user [username]"] = "myUsername"; data ["user [password]"] = "myPassword";
Bimal Poudel

68

MSDN hat eine Probe.

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

Aus irgendeinem Grund hat es nicht funktioniert, als ich große Datenmengen
gesendet habe

26

Dies ist ein vollständiges Arbeitsbeispiel für das Senden / Empfangen von Daten im JSON-Format. Ich habe Visual Studio 2013 Express Edition verwendet:

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

Hier gibt es einige wirklich gute Antworten. Lassen Sie mich eine andere Methode zum Festlegen Ihrer Header mit dem WebClient () veröffentlichen. Ich werde Ihnen auch zeigen, wie Sie einen API-Schlüssel festlegen.

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

Nützlich, danke. Übrigens: Die oben beschriebene Technik zum Festlegen von Header-Eigenschaften funktioniert auch für den älteren (veralteten?) HttpWebRequest-Ansatz. zB myReq.Headers [HttpRequestHeader.Authorization] = $ "Basic {credentials}";
Zeek2

6

Diese Lösung verwendet nur Standard-.NET-Aufrufe.

Geprüft:

  • Wird in einer WPF-Unternehmensanwendung verwendet. Verwendet async / await, um ein Blockieren der Benutzeroberfläche zu vermeiden.
  • Kompatibel mit .NET 4.5+.
  • Ohne Parameter getestet (erfordert ein "GET" hinter den Kulissen).
  • Getestet mit Parametern (erfordert einen "POST" hinter den Kulissen).
  • Getestet mit einer Standardwebseite wie Google.
  • Getestet mit einem internen Java-basierten Webservice.

Referenz:

// Add a Reference to the assembly System.Web

Code:

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

So rufen Sie ohne Parameter auf (verwendet ein "GET" hinter den Kulissen):

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

So rufen Sie mit Parametern auf (verwendet einen "POST" hinter den Kulissen):

 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

Einfache Lösung (einzeilig, keine Fehlerprüfung, kein Warten auf Antwort), die ich bisher gefunden habe:

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

Mit Vorsicht verwenden!


5
Das ist ziemlich schlimm Ich empfehle es nicht, da es keinerlei Fehlerbehandlung gibt und das Debuggen schmerzhaft ist. Zusätzlich gibt es bereits eine gute Antwort auf diese Frage.
Hooch

1
@ Hooch andere könnten an dieser Art von Antworten interessiert sein, auch wenn es nicht die beste ist.
Mitulát báti

Einverstanden, der einzige Kontext, in dem dies nützlich wäre, ist Code-Golf und wer spielt in C #;)
Extragorey

4

Wenn Sie den Windows.Web.Http- Namespace verwenden, schreiben wir für POST anstelle von FormUrlEncodedContent HttpFormUrlEncodedContent. Die Antwort ist auch der Typ HttpResponseMessage. Der Rest ist, wie Evan Mulawski niedergeschrieben hat.


4

Wenn Sie eine fließende API mögen, können Sie Tiny.RestClient verwenden . Es ist bei NuGet erhältlich .

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

Warum ist das nicht ganz trivial? Das Ausführen der Anforderung ist nicht und insbesondere nicht mit den Ergebnissen verbunden und es scheint, dass auch einige .NET-Fehler beteiligt sind - siehe Fehler in HttpClient.GetAsync sollte WebException auslösen, nicht TaskCanceledException

Am Ende hatte ich diesen Code:

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

Dies führt dazu, dass ein GET oder POST davon abhängt, ob postBuffernull ist oder nicht

Wenn Erfolg wahr ist, wird die Antwort in sein ResponseAsString

wenn Erfolg falsch ist , können Sie zu überprüfen WebExceptionStatus, HttpStatusCodeund ResponseAsStringzu versuchen , um zu sehen , was falsch gelaufen ist .


0

In .net Core können Sie nach dem Anruf folgenden Code verwenden. Hier habe ich diesem Code einige zusätzliche Funktionen hinzugefügt, damit Ihr Code hinter einem Proxy und gegebenenfalls mit Netzwerkanmeldeinformationen funktioniert. Auch hier erwähne ich, dass Sie die Codierung von ändern können deine Nachricht. Ich hoffe das erklärt alles und hilft dir beim Codieren.

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;
        }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.