我如何能使一个HTTP POST请求和发送数据的主体?


当前回答

到目前为止,我找到了简单的解决方案(一行程序,没有错误检查,没有等待响应):

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

请谨慎使用!

其他回答

这个解决方案只使用标准的. net调用。

测试:

在企业WPF应用程序中使用。使用async/await来避免阻塞UI。 兼容。net 4.5+。 在没有参数的情况下进行测试(在幕后需要一个“GET”)。 使用参数进行测试(需要幕后的“POST”)。 使用标准的网页(如谷歌)进行测试。 使用内部基于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.
 }

这是一个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服务器端:

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

结果将是“Yes, hi Ali”。

这是为Xamarin形式。对于一个c# .NET应用程序,将DisplayAlert替换为:

MessageBox.show(responseContent);

还有另一种做法:

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

通过这种方式,您可以轻松地发布一个流。

如果需要POST JSON消息体,可以使用以下方法。假设您有一个名为m的类实例。

string jsonMessage = JsonConvert.SerializeObject(m);

// Make POST call
using (HttpClient client = new HttpClient())
{
    HttpRequestMessage requestMessage = new
    HttpRequestMessage(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
    }
}

这是一个完整的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);
        }
    }
}