RestSharp进行POST请求时如何直接发送byte数组或string字符串

POST请求时,RestSharp可以非常简单的实现application/x-www-form-urlencodedform-data等方式的请求,对于application/json其也有着比较好的支持,对于application/xml方式,如果请求实体属性与xml格式定义完全一致那也是没问题的。

通常情况下,上述情况已经可以满足我们大部分的需求,但是,却可能存在这些情况

  • Json序列化不一致
  • Xml序列化不一致
  • 服务端要你传递一段按指定格式组织的字符串(常见的RPC请求
  • 服务端要你传递byte数组(这个数组有可能是经过处理的,比如加密
  • ……

你可以在这里找到RestSharp默认支持的序列化定义。你也可以通过RestClient.UseSerializer来替换对应的序列化类,其内部通过RestSharp.DataFormat来判断如何替换,所以如果默认的JsonXml序列化不满足你的业务需求时,你可以自定义IRestSerializer来实现自己的序列化实现。

当然,自定义IRestSerializer只能解决序列化问题,不能解决指定格式字符串byte数组的问题。对于JsonXml之外的数据,通过源代码Http.WriteRequestBody

            using (var requestStream = webRequest.GetRequestStream())
            {
                if (HasFiles || AlwaysMultipartFormData)
                    WriteMultipartFormData(requestStream);
                else if (RequestBodyBytes != null)
                    requestStream.Write(RequestBodyBytes, 0, RequestBodyBytes.Length);
                else if (RequestBody != null)
                    WriteStringTo(requestStream, RequestBody);
            }

以及RestRequestExtensions.AddBody的关键代码

            if (!http.AlwaysMultipartFormData && !http.Files.Any())
            {
                var val = value;

                if (val is byte[] bytes)
                    http.RequestBodyBytes = bytes;
                else
                    http.RequestBody = value.ToString();
            }

可以发现通过指定当前请求格式为DataFormat.None

            if (body.DataFormat == DataFormat.None)
                http.AddBody(body.ContentType, body.Name, body.Value);

可以解决上述直接传递数据的问题,而这个枚举只能通过Parameter.DataFormat来指定,在之后顺藤摸瓜,可以发现只有RestRequest.AddParameterRestRequest.AddOrUpdateParameter这两个方法才有Parameter参数,所以最终我们只需要通过如下代码来构建RestRequest即可

            var request = new RestRequest(url, Method.POST);
            //这里假设不符合默认的xml序列化情况
            //其它json,数组,自定义格式字符串也只要替换contentType和data即可
            var contentType = "application/xml";
            var data = "<root></root>";
            request.AddParameter(new Parameter
            {
                ContentType = contentType,
                Type = ParameterType.RequestBody,
                DataFormat = DataFormat.None,
                Value = data,
                Name = ""
            });

最后,顺便贴个基于上述内容实现的亿美软通发短信功能代码,你可以通过这里获取亿美软通发短信的Demo及文档,当然这里我只是简单实现了单个短信发送以及批量发送两个功能,方法中用到的AESHelper可见此处

    /// <summary>
    /// 短信接口
    /// </summary>
    public interface ISms
    {
        /// <summary>
        /// 发送单条短信
        /// </summary>
        /// <param name="mobile"></param>
        /// <param name="content"></param>
        /// <param name="bizId"></param>
        /// <param name="sendTime"></param>
        /// <returns></returns>
        bool SendMessage(string mobile, string content, string bizId = null, DateTime? sendTime = null);
        /// <summary>
        /// 发送单条短信
        /// </summary>
        /// <param name="mobile"></param>
        /// <param name="content"></param>
        /// <param name="bizId"></param>
        /// <param name="sendTime"></param>
        /// <returns></returns>
        Task<bool> SendMessageAsync(string mobile, string content, string bizId = null, DateTime? sendTime = null);

        /// <summary>
        /// 批量发送短信
        /// </summary>
        /// <param name="content"></param>
        /// <param name="mobiles"></param>
        /// <param name="bizIds">该值要么为null,要么Count要与mobiles的Count一致,否则会引发异常</param>
        /// <param name="sendTime"></param>
        /// <returns></returns>
        bool SendMessageBatch(string content, IList<string> mobiles, IList<string> bizIds = null, DateTime? sendTime = null);
        /// <summary>
        /// 批量发送短信
        /// </summary>
        /// <param name="content"></param>
        /// <param name="mobiles"></param>
        /// <param name="bizIds">该值要么为null,要么Count要与mobiles的Count一致,否则会引发异常</param>
        /// <param name="sendTime"></param>
        /// <returns></returns>
        Task<bool> SendMessageBatchAsync(string content, IList<string> mobiles, IList<string> bizIds = null, DateTime? sendTime = null);
    }

    /// <summary>
    /// 亿美短信  http://www.emay.cn/
    /// </summary>
    public class EmaySms : ISms
    {
        private string _appId;
        private byte[] _secretKey;
        private IRestClient _client;
        public EmaySms(string host, string appId, string secretKey)
        {
            if (string.IsNullOrWhiteSpace(host) || string.IsNullOrWhiteSpace(appId) || string.IsNullOrWhiteSpace(secretKey))
            {
                throw new ArgumentNullException();
            }
            this._appId = appId;
            var key = new Byte[16];
            Array.Copy(Encoding.UTF8.GetBytes(secretKey.PadRight(key.Length)), key, key.Length);
            this._secretKey = key;
            this._client = new RestClient(string.Format("http://{0}", host));
            this._client.AddDefaultHeader("appId", this._appId);
        }
        /// <summary>
        /// 请求有效期(秒),默认60
        /// </summary>
        public int ValidPeriod { get; set; } = 60;

        / <summary>
        / 请求时是否需要Gzip压缩,默认否
        / </summary>
        //public bool UseGzip { get; set; }

        private const string SendSingleSmsUrl = "/inter/sendSingleSMS";
        private const string SendBatchSmsUrl = "/inter/sendBatchSMS";
        private IRestRequest GetRestRequest(object data,string url)
        {
            var str = JsonConvert.SerializeObject(data);
            var encryptData = AESHelper.Encrypt(Encoding.UTF8.GetBytes(str), this._secretKey, null, CipherMode.ECB, PaddingMode.PKCS7);
            var request = new RestRequest(url, Method.POST);
            request.AddParameter(new Parameter
            {
                Type = ParameterType.RequestBody,
                DataFormat = DataFormat.None,
                Value = encryptData,
                Name = ""
            });
            return request;
        }
        private object GetSingleSmsObj(string mobile, string content, string bizId, DateTime? sendTime)
        {
            var data = new
            {
                mobile,
                content,
                timerTime = sendTime.HasValue ? sendTime.Value.ToString("yyyy-MM-dd HH:mm:ss") : string.Empty,
                customSmsId = bizId,
                requestTime = DateTime.Now.Ticks,
                requestValidPeriod = this.ValidPeriod
            };
            return data;
        }
        private bool IsResponseSuccess(IRestResponse response)
        {
            return response.Headers.FirstOrDefault(p => p.Name == "result")?.Value.ToString() == "SUCCESS";
        }
        private string GetResponseContent(IRestResponse response)
        {
            var data = AESHelper.Decrypt(response.RawBytes, this._secretKey, null, CipherMode.ECB, PaddingMode.PKCS7);
            return Encoding.UTF8.GetString(data);
        }
        public bool SendMessage(string mobile, string content, string bizId = null, DateTime? sendTime = null)
        {
            var data = this.GetSingleSmsObj(mobile, content, bizId, sendTime);
            var request = this.GetRestRequest(data, SendSingleSmsUrl);
            var response = this._client.Execute(request);
            return this.IsResponseSuccess(response);
        }

        public async Task<bool> SendMessageAsync(string mobile, string content, string bizId = null, DateTime? sendTime = null)
        {
            var data = this.GetSingleSmsObj(mobile, content, bizId, sendTime);
            var request = this.GetRestRequest(data, SendSingleSmsUrl);
            var response = await this._client.ExecuteTaskAsync(request).ConfigureAwait(false);
            return this.IsResponseSuccess(response);
        }

        public bool SendMessageBatch(string content, IList<string> mobiles, IList<string> bizIds = null, DateTime? sendTime = null)
        {
            var data = this.GetBatchSMSObj(content, mobiles, bizIds, sendTime);
            var request = this.GetRestRequest(data, SendBatchSmsUrl);
            var response = this._client.Execute(request);
            return this.IsResponseSuccess(response);
        }
        private object GetBatchSMSObj(string content, IList<string> mobiles, IList<string> bizIds, DateTime? sendTime)
        {
            if (bizIds != null && bizIds.Count > 0 && mobiles.Count != bizIds.Count)
            {
                throw new ArgumentException($"{nameof(mobiles)}.Count not equals {nameof(bizIds)}.Count");
            }
            if (bizIds != null && bizIds.Count == 0)
            {
                bizIds = null;
            }
            var items = new ArrayList();
            for (var i = 0; i < mobiles.Count; i++)
            {
                items.Add(new
                {
                    mobile = mobiles[i],
                    customSmsId = bizIds?[i]
                });
            }
            var obj = new
            {
                smses = items,
                content,
                timerTime = sendTime.HasValue ? sendTime.Value.ToString("yyyy-MM-dd HH:mm:ss") : string.Empty,
                requestTime = DateTime.Now.Ticks,
                requestValidPeriod = this.ValidPeriod
            };
            return obj;
        }

        public async Task<bool> SendMessageBatchAsync(string content, IList<string> mobiles, IList<string> bizIds = null, DateTime? sendTime = null)
        {
            var data = this.GetBatchSMSObj(content, mobiles, bizIds, sendTime);
            var request = this.GetRestRequest(data, SendBatchSmsUrl);
            var response = await this._client.ExecuteTaskAsync(request).ConfigureAwait(false);
            return this.IsResponseSuccess(response);
        }
    }
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值