在. NET中发送HTTP POST请求

如何发出HTTPPOST请求并在主体中发送数据?

2227690 次浏览

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

有几种方法可以执行HTTPgetPOST请求:


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

#0依赖注入解决方案。


  • 发布

      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();
  • 获取

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

方法B:第三方库

restSharp

  • 发布

       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 stringvar response2 = client.Post<Person>(request);var name = response2.Data.Name;

Flurl. Http

它是一个较新的库,带有FluentAPI,测试助手,在引擎盖下使用HttpClient,并且是可移植的。它可通过NuGet获得。

    using Flurl.Http;

  • 发布

      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 Encodingusing System.IO;    // For StreamReader

  • 发布

      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();
  • 获取

      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.对比一下#1的包装器。

可用于:. NET Framework 1.1+、NET Standard 2.0+和. NET Core 2.0+。

在某些情况下(. NET Framework 4.5-4.8),如果您需要同步执行HTTP请求,仍然可以使用WebClient

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

  • 发布

      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);}
  • 获取

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

简单的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);}

到目前为止我发现的简单(单行代码,没有错误检查,没有等待响应)解决方案:

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

谨慎使用!

这是一个以JSON格式发送/接收数据的完整工作示例,我使用Visual Studio 2013 Express版:

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

当使用Windows. Web. Http文档链接命名空间时,对于POST而不是FormUrlEncodedContent,我们编写HttpFormUrlEncodedContent。响应也是HttpResponse seMessage的类型。其余的是Evan Mulawski写下

这里有一些非常好的答案。让我发布一种使用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 JsonConvertvar 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);

如果你喜欢FluentAPI,你可以使用微小的恢复客户端。它在NuGet可用。

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

此解决方案仅使用标准。NET调用。

测试:

  • 在企业WPF应用程序中使用。使用async/wait来避免阻塞UI。
  • 兼容。NET 4.5+。
  • 在没有参数的情况下进行测试(在幕后需要“GET”)。
  • 使用参数进行测试(在幕后需要“POST”)。
  • 使用标准网页(如Google)进行测试。
  • 使用内部基于Java的Web服务进行测试。

参考:

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

为什么这不是完全微不足道的?执行请求不是,尤其不是处理结果。而且似乎还涉及一些。NET错误-参见HttpClient. GetAsync中的错误应该抛出WebException,而不是Task取消异常

我最终得到了这个代码:

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());}
// https://devblogs.microsoft.com/dotnet/net-5-new-networking-improvements/} catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException) {return (false, ex.ToString(), null, WebExceptionStatus.Timeout);
} catch (TaskCanceledException ex) {return (false, ex.ToString(), null, WebExceptionStatus.RequestCanceled);
} catch (Exception ex) {return (false, WebExceptionStatus.UnknownError, null, ex.ToString());}}

这将执行GET或POST,具体取决于postBuffer是否为null。

如果成功为真,则响应将在ResponseAsString中。

如果成功为假,您可以检查WebExceptionStatusHttpStatusCodeResponseAsString以尝试查看哪里出了问题。

. NET Core中,您可以使用以下代码进行POST调用。在这里,我为此代码添加了一些额外的功能,因此您可以使您的代码在代理后面工作,并使用网络凭据(如果有)。

在这里,我还提到您可以更改消息的编码。

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

这是我在. NET 4.8中使用的HTTP POST请求。使用此代码,可以一次发送多个POST请求异步

在每个请求结束时都会引发一个事件。并且在所有请求结束时都会引发另一个事件。

下面是核心类:

Imports System.ComponentModelImports System.Text.RegularExpressionsImports System.TimersImports System.Windows.FormsImports AeonLabsImports AeonLabs.EnvironmentImports Newtonsoft.Json
Public Class HttpDataCorePublic Property url As StringPublic Property state As New environmentVarsCorePublic Property errorMessage As String = ""Public Property statusMessage As StringPublic Property threadCount As Integer = 25Public Property numberOfRetryAttempts = 5Public Property queue As List(Of _queue_data_struct)Public Property queueBWorker As Integer() ' has the size of threadCountPublic Property queueLock As New ObjectPublic Property retryAttempts As New _retry_attemptsPublic Property dataStatistics As List(Of _data_statistics)Public Property loadingCounter As IntegerPublic Property CompletionPercentage As Integer ' value range 0-100Public Property IsBusy As Boolean
Public Structure _queue_data_structDim vars As Dictionary(Of String, String)Dim filenameOrSavePath As String                  ' full address file name or full adress folder pathDim misc As Dictionary(Of String, String)Dim status As Integer                             ' -1 - completed; 0- not sent yet; 1-already sent / processingEnd Structure
Public Structure _retry_attemptsDim counter As IntegerDim pattern As IntegerDim previousPattern As IntegerDim errorMessage As StringEnd Structure
Public Structure _data_statisticsDim filesize As DoubleDim bytesSentReceived As DoubleDim speed As DoubleEnd Structure
Public WithEvents RestartQueueTimer As New Timers.TimerPublic bwDataRequest() As BackgroundWorker
Public Event requestCompleted(sender As Object, requestData As String) 'TODO add misc vars
Private sendToQueue As Boolean
Public Sub New(ByVal Optional _state As environmentVarsCore = Nothing, ByVal Optional _url As String = "")queue = New List(Of _queue_data_struct)dataStatistics = New List(Of _data_statistics)loadingCounter = 0sendToQueue = FalseIf _state IsNot Nothing AndAlso _url.Equals("") Thenurl = _state.ServerBaseAddr & _state.ApiServerAddrPathElseIf Not _url.Equals("") Thenurl = _urlElseThrow New System.Exception("Initialization err: state and url cannot be both null at same time")End If
If _state IsNot Nothing Thenstate = _stateEnd IfEnd Sub
Public Sub loadQueue(ByVal vars As Dictionary(Of String, String), ByVal Optional misc As Dictionary(Of String, String) = Nothing, ByVal Optional filenameOrSavePath As String = Nothing)Dim queueItem As New _queue_data_structqueueItem.vars = New Dictionary(Of String, String)queueItem.misc = New Dictionary(Of String, String)
queueItem.vars = varsqueueItem.status = 0queueItem.misc = miscqueueItem.filenameOrSavePath = filenameOrSavePathqueue.Add(queueItem)End Sub
Public Sub clearQueue()loadingCounter = 0queue = New List(Of _queue_data_struct)End Sub
Public Sub startRequest()If bwDataRequest(0) Is Nothing ThenThrow New Exception("You need to call initialze first")Exit SubEnd If
'startSendQueue()IsBusy = True
AddHandler RestartQueueTimer.Elapsed, New ElapsedEventHandler(AddressOf QueueTimerTick)With RestartQueueTimer.Enabled = True.Interval = 500.Start()End WithEnd Sub
Private Sub QueueTimerTick(ByVal sender As Object, ByVal e As ElapsedEventArgs)If QueuesToComplete(queue).Equals(0) And QueuesToSend(queue).Equals(0) ThenRestartQueueTimer.Stop()queue = New List(Of _queue_data_struct)RaiseEvent requestCompleted(Me, Nothing)IsBusy = FalseExit SubEnd If
If retryAttempts.counter >= numberOfRetryAttempts Then 'ToDo a retry number of attempts before quitsThreading.Thread.CurrentThread.CurrentUICulture = Globalization.CultureInfo.GetCultureInfo(state.currentLang)Dim MsgBox As messageBoxFormMsgBox = New messageBoxForm(retryAttempts.errorMessage & ". " & My.Resources.strings.tryAgain & " ?", My.Resources.strings.question, MessageBoxButtons.YesNo, MessageBoxIcon.Question)If MsgBox.ShowDialog() = DialogResult.Yes ThenDim retry As _retry_attemptsWith retry.counter = 0.previousPattern = -1.pattern = 0.errorMessage = ""End WithretryAttempts = retrystartSendQueue()ElseRestartQueueTimer.Stop()queue = New List(Of _queue_data_struct)RaiseEvent requestCompleted(Me, Nothing)IsBusy = FalseExit SubEnd IfExit SubElseIf Not sendToQueue And QueuesToSend(queue) > 0 ThenstartSendQueue()End IfEnd Sub
Private Sub startSendQueue()sendToQueue = TrueWhile QueuesToSend(queue) > 0For shtIndex = 0 To threadCountFor i = 0 To queue.Count - 1If Not bwDataRequest(shtIndex).IsBusy ThenSyncLock queueLockIf queue.ElementAt(i).status.Equals(0) ThenDim data As New _queue_data_structdata.vars = queue.ElementAt(i).varsdata.status = 1data.misc = queue.ElementAt(i).miscdata.filenameOrSavePath = queue.ElementAt(i).filenameOrSavePathqueue(i) = dataqueueBWorker(shtIndex) = idataStatistics(shtIndex) = (New _data_statistics)
bwDataRequest(shtIndex).RunWorkerAsync(queue(i))Threading.Thread.Sleep(50)End IfEnd SyncLockEnd IfNext iNext shtIndexEnd WhilesendToQueue = FalseEnd Sub
Public Function QueuesToSend(queue As List(Of _queue_data_struct)) As IntegerDim counter As Integer = 0For i = 0 To queue.Count - 1If queue(i).status.Equals(0) Thencounter += 1End IfNext iReturn counterEnd Function
Public Function QueuesToComplete(queue As List(Of _queue_data_struct)) As IntegerDim counter As Integer = 0For i = 0 To queue.Count - 1If queue(i).status.Equals(1) Thencounter += 1End IfNext iReturn counterEnd Function
Public Function QueuesMultiHash(queue As List(Of _queue_data_struct)) As IntegerDim counter As Integer = 0For i = 0 To queue.Count - 1If queue(i).status.Equals(1) Thencounter += iEnd IfNext iReturn counterEnd Function
Public Function IsBase64String(ByVal s As String) As Booleans = s.Trim()Return (s.Length Mod 4 = 0) AndAlso Regex.IsMatch(s, "^[a-zA-Z0-9\+/]*={0,3}$", RegexOptions.None)End Function
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++Public Function ConvertDataToArray(key As String, fields As String(), response As String) As Dictionary(Of String, List(Of String))If GetMessage(response).Equals("1001") ThenThreading.Thread.CurrentThread.CurrentUICulture = Globalization.CultureInfo.GetCultureInfo(state.currentLang)errorMessage = "{'error':true,'message':'" & My.Resources.strings.errorNoRecordsFound & "'}"Return NothingEnd IfTryDim jsonResult = JsonConvert.DeserializeObject(Of Dictionary(Of String, Object))(response)If jsonResult.ContainsKey(key) ThenIf Not jsonResult.Item(key).item(0).Count.Equals(fields.Length) ThenThreading.Thread.CurrentThread.CurrentUICulture = Globalization.CultureInfo.GetCultureInfo(state.currentLang)errorMessage = "{'error':true,'message':'" & My.Resources.strings.JsonFieldsMismatch & ". table(" & key & "'}"Return NothingElseDim results = New Dictionary(Of String, List(Of String))For k = 0 To fields.Length - 1Dim fieldValues As List(Of String) = New List(Of String)For i = 0 To jsonResult.Item(key).Count - 1fieldValues.Add(jsonResult.Item(key).item(i).item(k).ToString)Next iresults.Add(fields(k), fieldValues)
Next kReturn resultsEnd IfElseThreading.Thread.CurrentThread.CurrentUICulture = Globalization.CultureInfo.GetCultureInfo(state.currentLang)errorMessage = "{'error':true,'message':'" & My.Resources.strings.JsonkeyNotFound & " (" & key & "'}"Return NothingEnd IfCatch ex As ExceptionerrorMessage = "{'error':true,'message':'" & ex.ToString & "'}"errorMessage = ex.ToStringReturn NothingEnd TryEnd FunctionEnd Class

AeonLabs.Envoriment是一个具有集合或字段和属性的类。

下面的一个是用于发出POST请求:

Imports System.ComponentModelImports System.IOImports System.NetImports System.TextImports System.WebImports System.Web.Script.SerializationImports System.Windows.FormsImports AeonLabs.EnvironmentImports AeonLabs.Security
Public Class HttpDataPostDataInherits HttpDataCore
Public Event updateProgress(sender As Object, misc As Dictionary(Of String, String))
Public Event dataArrived(sender As Object, requestData As String, misc As Dictionary(Of String, String))
Public Sub New(ByVal Optional _state As environmentVarsCore = Nothing, ByVal Optional _url As String = "")MyBase.New(_state, _url)End Sub
Public Sub initialize(ByVal Optional _threadCount As Integer = 0)If Not _threadCount.Equals(0) ThenthreadCount = _threadCountEnd If
ReDim bwDataRequest(threadCount)ReDim queueBWorker(threadCount)
For shtIndex = 0 To threadCountdataStatistics.Add(New _data_statistics)
bwDataRequest(shtIndex) = New System.ComponentModel.BackgroundWorkerbwDataRequest(shtIndex).WorkerReportsProgress = TruebwDataRequest(shtIndex).WorkerSupportsCancellation = True
AddHandler bwDataRequest(shtIndex).DoWork, AddressOf bwDataRequest_DoWorkAddHandler bwDataRequest(shtIndex).RunWorkerCompleted, AddressOf bwDataRequest_RunWorkerCompletedNext shtIndexDim retry As _retry_attemptsWith retry.counter = 0.previousPattern = -1.pattern = 0.errorMessage = ""End WithretryAttempts = retryEnd Sub
Private Sub bwDataRequest_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs)
' Find out the Index of the bWorker that called this DoWork (could be cleaner, I know)Dim Y As IntegerDim Index As Integer = NothingFor Y = 0 To UBound(bwDataRequest)If sender.Equals(bwDataRequest(Y)) ThenIndex = YExit ForEnd IfNext Y
Dim queue As _queue_data_structqueue = e.Argument
Dim vars As New Dictionary(Of String, String)vars = queue.vars
'TODO translation need to be localIf Not System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable() ThenThreading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo(state.currentLang)e.Result = "{'error':true,'message':'" & My.Resources.strings.errorNoNetwork & "'}"Exit SubEnd IfIf vars Is Nothing Thene.Result = "{'error':true,'message':'missconfiguration vars'}"Exit SubEnd If
If Not vars.ContainsKey("id") Thenvars.Add("id", state.userId)End IfIf Not vars.ContainsKey("pid") ThenDim appId As New FingerPrintvars.Add("pid", appId.Value)End IfIf Not vars.ContainsKey("language") Thenvars.Add("language", state.currentLang)End IfIf Not vars.ContainsKey("origin") Thenvars.Add("origin", state.softwareAccessMode)End If
Dim serializer As New JavaScriptSerializer()Dim json As String = serializer.Serialize(vars)Dim encryption As New AesCipher(state)Dim encrypted As String = HttpUtility.UrlEncode(encryption.encrypt(json))Dim PostData = "origin=" & state.softwareAccessMode & "&data=" & encryptedDim request As WebRequest = WebRequest.Create(url)Dim responseFromServer As String = ""Dim decrypted As String = ""
request.Method = "POST"Dim byteArray As Byte() = Encoding.UTF8.GetBytes(PostData)request.ContentType = "application/x-www-form-urlencoded"request.Headers.Add("Authorization", state.ApiHttpHeaderToken & "-" & state.softwareAccessMode)request.ContentLength = byteArray.LengthTryDim dataStream As Stream = request.GetRequestStream()dataStream.Write(byteArray, 0, byteArray.Length)dataStream.Close()Dim response As HttpWebResponse = CType(request.GetResponse(), HttpWebResponse)dataStream = response.GetResponseStream()Dim reader As New StreamReader(dataStream)responseFromServer = reader.ReadToEnd()reader.Close()dataStream.Close()response.Close()
If response.StatusCode = HttpStatusCode.Accepted Or response.StatusCode = 200 ThenIf IsBase64String(responseFromServer) And Not responseFromServer.Equals("") Thendecrypted = encryption.decrypt((responseFromServer)).Replace("\'", "'")ElseThreading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo(state.currentLang)decrypted = "{'error':true,'encrypted':false,'message':'" & My.Resources.strings.contactingCommServer & " |" & responseFromServer & "|'}"End IfElseThreading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo(state.currentLang)decrypted = "{'error':true,'message':'" & My.Resources.strings.contactingCommServer & " (" & response.StatusCode & ")', 'statuscode':'" & response.StatusCode & "'}"End IfCatch ex As ExceptionThreading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo(state.currentLang)decrypted = "{'error':true,'message':'" & My.Resources.strings.contactingCommServer & " (" & ex.Message.ToString.Replace("'", "\'") & ")'}"End Try
e.Result = decrypted.Replace("\'", "'")End Sub
Private Sub bwDataRequest_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs)' Find out the Index of the bWorker that called this DoWork (could be cleaner, I know)Dim Y As IntegerDim Index As Integer = NothingDim data As New _queue_data_struct
For Y = 0 To UBound(bwDataRequest)If sender.Equals(bwDataRequest(Y)) ThenIndex = YExit ForEnd IfNext Y
If IsResponseOk(e.Result, "statuscode") Thendata = New _queue_data_structdata = queue(queueBWorker(Index))data.status = 0 're queue the fileSyncLock queueLockqueue(queueBWorker(Index)) = dataEnd SyncLockDim errorMsg As String = GetMessage(e.Result)Dim retry As _retry_attemptsWith retry.counter = retryAttempts.counter.previousPattern = retryAttempts.previousPattern.pattern = retryAttempts.pattern.errorMessage = retryAttempts.errorMessageEnd Withretry.errorMessage = If(retryAttempts.errorMessage.IndexOf(errorMsg) > -1, retryAttempts.errorMessage, retryAttempts.errorMessage & System.Environment.NewLine & errorMsg)
retry.pattern = QueuesMultiHash(queue)If retry.previousPattern.Equals(retry.pattern) Thenretry.counter += 1Elseretry.counter = 1retry.previousPattern = retryAttempts.patternEnd If
retryAttempts = retryExit SubEnd If
data = New _queue_data_structdata = queue(queueBWorker(Index))data.status = -1 'completed sucessfully statusSyncLock queueLockqueue(queueBWorker(Index)) = dataEnd SyncLock
loadingCounter += 1CompletionPercentage = (loadingCounter / queue.Count) * 100statusMessage = "Loading data from the cloud..."RaiseEvent updateProgress(Me, queue(queueBWorker(Index)).misc)RaiseEvent dataArrived(Me, e.Result, queue(queueBWorker(Index)).misc)End SubEnd Class

Aoenlabs. Security是一个用于发送使用标准加密算法加密的POST数据的类。

还有另一种方法:

using (HttpClient httpClient = new HttpClient())using (MultipartFormDataContent form = new MultipartFormDataContent()){form.Add(new StringContent(param1), "param1");form.Add(new StringContent(param2), "param2");using (HttpResponseMessage response = await httpClient.PostAsync(url, form)){response.EnsureSuccessStatusCode();string res = await response.Content.ReadAsStringAsync();return res;}}

这样你就可以很容易地发布一个流。

这是一个HTTPS Web请求的示例。您可以在PHP脚本中回送任何结果。最后,PHP回送字符串将在C#客户端显示为警报。

string url = "https://mydomain.ir/test1.php";StringBuilder postData = new StringBuilder();postData.Append(String.Format("{0}={1}&", HttpUtility.HtmlEncode("username"), HttpUtility.HtmlEncode("ali")));postData.Append(String.Format("{0}={1}", HttpUtility.HtmlEncode("password"), HttpUtility.HtmlEncode("123456789")));StringContent myStringContent = new StringContent(postData.ToString(), Encoding.UTF8, "application/x-www-form-urlencoded");HttpClient client = new HttpClient();HttpResponseMessage message = client.PostAsync(url, myStringContent).GetAwaiter().GetResult();string responseContent = message.Content.ReadAsStringAsync().GetAwaiter().GetResult();
DisplayAlert("Your Feedback", responseContent, "OK");

PHP服务器端:

<?phpif (isset($_POST["username"]) && $_POST["username"] == "ali") {echo "Yes, hi Ali";}else {echo "No, where is Ali?";}?>

结果将是“是的,你好阿里”。

这适用于Xamarin窗体。对于C#。NET应用程序,将DisplayAlert替换为:

MessageBox.show(responseContent);

如果您需要发布JSON消息正文,您可以使用以下内容。假设您有一个名为m的类实例。

string jsonMessage = JsonConvert.SerializeObject(m);
// Make POST callusing (HttpClient client = new HttpClient()){HttpRequestMessage requestMessage = newHttpRequestMessage(HttpMethod.Post, "<url here>");requestMessage.Content = new StringContent(jsonMessage, Encoding.UTF8, "application/json");HttpResponseMessage response = client.SendAsync(requestMessage).Result;if (response.StatusCode == System.Net.HttpStatusCode.OK){// Do something here}}

c#. Net

    using System.Net.Http;    
private static readonly HttpClient httpClient = new HttpClient();
//POSTvar values = new Object();values[0] = "Value1";values[2] = "Value2";values[n] = "ValueN";
var content = new FormUrlEncodedContent(values);var response = await httpClient.PostAsync("URL", content);var responseString = await response.Content.ReadAsStringAsync();
    

//GETvar response = await httpClient.GetStringAsync("URL");