代码示例

using System;
using System.IO;
using System.Net;
using System.Text;
using System.Reflection;
using System.Threading.Tasks;
using System.Collections.Generic;

namespace Common
{
    public sealed class HttpUtil
    {
        private static readonly HttpUtil httpUtility = new HttpUtil();

        private HttpUtil()
        { }

        public static HttpUtil GetInstance { get => httpUtility; }

        #region 异步请求

        /// <summary>异步请求</summary>
        /// <param name="requestParameters"></param>
        /// <returns></returns>
        public async Task<ResponseResult> HttpRequestAsync(RequestParameters requestParameters)
        {
            //string result = string.Empty;
            ResponseResult result = new ResponseResult();
            try
            {
                if (requestParameters.Query?.Count > 0)
                    requestParameters.Url += BuildQuery(requestParameters.Query);
                HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(requestParameters.Url);
                httpWebRequest.Method = requestParameters.Method.ToString();
                httpWebRequest.ContentType = requestParameters.ContentType;
                httpWebRequest.Timeout = requestParameters.TimeOut;
                httpWebRequest.KeepAlive = true;
                httpWebRequest.Accept = "*/*";

                if (requestParameters.Headers?.Count > 0)
                {
                    foreach (var item in requestParameters.Headers)
                        httpWebRequest.Headers.Add(item.Key, item.Value.ToString());
                }
                if (!string.IsNullOrEmpty(requestParameters.PostData))
                {
                    byte[] data = Encoding.UTF8.GetBytes(requestParameters.PostData);
                    httpWebRequest.ContentLength = data.Length;
                    using (Stream stream = await httpWebRequest.GetRequestStreamAsync())
                    {
                        stream.Write(data, 0, data.Length);
                    }
                }
                using (HttpWebResponse httpWebResponse = (HttpWebResponse)await httpWebRequest.GetResponseAsync())
                {
                    for (int i = 0; i < httpWebResponse.Headers.Count; i++)
                        result.Headers.Add(httpWebResponse.Headers.Keys[i], httpWebResponse.Headers[i]);
                    using (StreamReader reader = new StreamReader(httpWebResponse.GetResponseStream(), Encoding.UTF8))
                        result.Body = await reader.ReadToEndAsync();
                }
            }
            catch (Exception ex)
            {
                throw;
            }
            return result;
        }

        #endregion 异步请求

        #region 同步请求

        public ResponseResult HttpRequest(RequestParameters requestParameters)
        {
            //string result = string.Empty;
            ResponseResult result = new ResponseResult();
            try
            {
                if (requestParameters.Query?.Count > 0)
                    requestParameters.Url += BuildQuery(requestParameters.Query);
                HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(requestParameters.Url);
                httpWebRequest.Method = requestParameters.Method.ToString();
                httpWebRequest.ContentType = requestParameters.ContentType;
                httpWebRequest.Timeout = requestParameters.TimeOut;
                if (requestParameters.Headers?.Count > 0)
                {
                    foreach (var item in requestParameters.Headers)
                        httpWebRequest.Headers.Add(item.Key, item.Value.ToString());
                }
                if (!string.IsNullOrEmpty(requestParameters.PostData))
                {
                    byte[] data = Encoding.UTF8.GetBytes(requestParameters.PostData);
                    httpWebRequest.ContentLength = data.Length;
                    using (Stream stream = httpWebRequest.GetRequestStream())
                        stream.Write(data, 0, data.Length);
                }
                using (HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse())
                {
                    using (StreamReader reader = new StreamReader(httpWebResponse.GetResponseStream(), Encoding.UTF8))
                        result.Body = reader.ReadToEnd();
                    foreach (var key in httpWebResponse.Headers.AllKeys)
                        result.Headers.Add(key, httpWebResponse.Headers[key]);
                }
            }
            catch (Exception ex)
            {
                throw;
            }
            return result;
        }

        #endregion 同步请求

        /// <summary>拼接参数</summary>
        /// <param name="parameters"></param>
        /// <param name="encode"></param>
        /// <returns></returns>
        private string BuildQuery(Dictionary<string, object> parameters, string encode = "utf8")
        {
            StringBuilder postData = new StringBuilder("?");
            bool hasParam = false;
            foreach (var item in parameters)
            {
                string key = item.Key;
                string value = item.Value.ToString();
                if (!string.IsNullOrEmpty(key))
                {
                    if (hasParam)
                        postData.Append("&");
                    postData.Append($"{key}=");
                    if (encode == "gb2312")
                        postData.Append(System.Web.HttpUtility.UrlEncode(value, Encoding.GetEncoding("gb2312")));
                    else if (encode == "utf8")
                        postData.Append(System.Web.HttpUtility.UrlEncode(value, Encoding.UTF8));
                    else
                        postData.Append(value);
                    hasParam = true;
                }
            }
            return postData.ToString();
        }
    }

    #region 请求参数

    /// <summary>请求方式类型</summary>
    public enum MethodType
    {
        GET,

        POST,

        PUT,

        DELETE
    }

    /// <summary>请求参数</summary>
    public class RequestParameters
    {
        #region 字段

        private const string nonce = "nonc";

        private const string timestamp = "timestamp";

        private Dictionary<string, object> _headers = new Dictionary<string, object>();

        #endregion 字段

        #region 属性

        /// <summary>地址</summary>
        public string Url { get; set; }

        /// <summary>请求方式</summary>
        public MethodType Method { get; set; }

        /// <summary>内容格式</summary>
        public string ContentType { get; set; }

        /// <summary>请求头</summary>
        //public Dictionary<string, object> Headers
        //{
        //    get => new Dictionary<string, object>
        //    {
        //        { nonce, RandomStringBuilderUtility.Create(10) },
        //        { timestamp, DateTimeOffset.UtcNow.ToUnixTimeSeconds() }
        //    };
        //    set => _headers = value;
        //}

        /// <summary>请求头</summary>
        public Dictionary<string, object> Headers { get; set; } = new Dictionary<string, object>
        {
            { nonce, RandomStringBuilderUtil.Create(10) },
            { timestamp, DateTimeOffset.UtcNow.ToUnixTimeSeconds() }
         };

        /// <summary>请求参数</summary>
        public Dictionary<string, object> Query { get; set; }

        /// <summary>请求数据</summary>
        public string PostData { get; set; }

        /// <summary>超时时间</summary>
        public int TimeOut { get; set; } = 1000 * 60;

        #endregion 属性
    }

    /// <summary>响应结果</summary>
    public class ResponseResult
    {
        /// <summary>响应体</summary>
        public string Body { get; set; }

        /// <summary>响应头</summary>
        public Dictionary<string, object> Headers { get; set; } = new Dictionary<string, object>();
    }

    /// <summary>内容格式类型</summary>
    public class ContentType
    {
        public static readonly string Text = "text/plain";

        public static readonly string JSON = "application/json";

        public static readonly string JavaScript = "application/javascript";

        public static readonly string XML = "application/xml";

        public static readonly string TextXML = "text/xml";

        public static readonly string HTML = "text/html";

        public static readonly string FormData = "multipart/form-data";

        public static readonly string UrlEncoded = "x-www-form-urlencoded";
    }

    #endregion 请求参数
}

在上述代码中,HttpUtil 类使用了单例模式来确保只有一个实例被创建。通过私有的构造函数,防止外部直接实例化该类。通过静态属性 GetInstance 来获取类的唯一实例,如果实例不存在,则在多线程环境下使用双重检查锁定来创建实例。