首先创建了一个单元测试,如下项目视图:
分页结果映射类PageResult的编写:


using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ReuqestDemo { ////// 分页结果 /// /// public class PageResult where T : class { public PageResult() { this.Results = new List (); } /// /// 页码 /// public int PageNo { get; set; } /// /// 页量 /// public int PageSize { get; set; } /// /// 条数 /// public int RecordCount { get; set; } /// /// 页数 /// public int PageCount { get; set; } public List Results { get; set; } } /// /// 原始的返回结果 /// public class StartReturnResult where T : class { /// /// 分页结果 /// public StartPageResult Result { get; set; } /// /// 总页数 /// public int TotalPageCount { get; set; } } /// /// 原始的分页结果 /// public class StartPageResult where T : class { public StartPageResult() { this.Results = new List (); } /// /// 开始位置 /// 值始终为0 /// public int Start { get; set; } /// /// 每页数量 /// public int PageSize { get; set; } /// /// 数据总数 /// public int TotalCount { get; set; } /// /// 数据集合 /// public List Results { get; set; } /// /// 页码 /// 值始终为1 /// public int Page { get; set; } /// /// 页码 /// 值始终为1 /// public int CurrentPageNo { get; set; } /// /// 总页数 /// public int TotalPageCount { get; set; } } }
检索条件SearchCondition如下:


using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ReuqestDemo { ////// 检索条件 /// public class SearchCondition { /// /// 检索关键字 /// public string Keyword { get; set; } /// /// 检索的页码 /// public int PageNo { get; set; } } }
Helper文件夹下的DataSerializer类如下:


using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace ReuqestDemo.Helpers { ////// 数据序列化器 /// public static class DataSerializer { /// /// json 序列号 /// /// 要序列化的对象 /// 是否忽略空值,true为不忽略 /// public static string SerizlizeToJSON(object source,bool b=true) { var setting = new JsonSerializerSettings(); setting.ContractResolver = new SortedContractResolver(); if (!b) { setting.NullValueHandling = NullValueHandling.Ignore; //忽略空对象 } var jsonString = JsonConvert.SerializeObject(source, setting); return jsonString; } public static TData DeserializeFromJSON (string jsonString) { var data = JsonConvert.DeserializeObject (jsonString); return data; } } public class SortedContractResolver : DefaultContractResolver { protected override List GetSerializableMembers(Type objectType) { var members = base.GetSerializableMembers(objectType); return members.OrderBy(m => m.Name).ToList(); } } }
Helper文件夹下的HttpRequester类如下:


using System; using System.Collections.Generic; using System.Net.Http; using System.Net.Http.Headers; using System.Text; using System.Threading.Tasks; using System.Web; namespace ReuqestDemo.Helpers { public static class HttpRequester { public const string CONTENT_TYPE_JSON = "application/json"; public const string CONTENT_TYPE_FORM = "application/x-www-form-urlencoded"; public static async TaskPostAsync (HttpClient client, string url, string dataString, IDictionary<string, string> headers = null) { var rsp = await PostAsync(client, url, dataString, CONTENT_TYPE_FORM, headers); var res = DataSerializer.DeserializeFromJSON (rsp); return res; } public static async Task<string> PostAsync(HttpClient client, string url, string dataString, string contentType, IDictionary<string, string> headers = null) { using (HttpContent content = new StringContent(dataString)) { var mt = new MediaTypeHeaderValue(contentType) { CharSet = "UTF-8" }; content.Headers.ContentType = mt; if (headers != null) { foreach (var item in headers) { content.Headers.Add(item.Key, item.Value); } } var rsp = await client.PostAsync(url, content); rsp.EnsureSuccessStatusCode(); var text = await rsp.Content.ReadAsStringAsync(); return text; } } public static string CombinParametersUrlEncode(IEnumerable string, string>> parameters) { return CombinParameters(parameters, true); } private static string CombinParameters(IEnumerable string, string>> parameters, bool isUrlEncode) { var pStr = string.Empty; if (parameters != null) { var pSB = new StringBuilder(); if (isUrlEncode) { foreach (var p in parameters) { pSB.Append(HttpUtility.UrlEncode(p.Key)).Append("=").Append(HttpUtility.UrlEncode(p.Value)).Append("&"); } } else { foreach (var p in parameters) { pSB.Append(p.Key).Append("=").Append(p.Value).Append("&"); } } pStr = pSB.ToString(); } if (string.IsNullOrEmpty(pStr)) return pStr; return pStr.Substring(0, pStr.Length - 1); } } }
Helper文件夹下的TimeHelper类如下:


using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ReuqestDemo.Helpers { public static class TimeHelper { ////// 返回时间戳 /// /// 时间戳 public static long GetTimeStamp() { TimeSpan tSpan = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); return Convert.ToInt64(tSpan.TotalMilliseconds); } /// /// 返回时间戳 /// /// 时间戳 public static string GetTStamp() { return GetTimeStamp().ToString(); } } }
Models文件夹下的ResultModel类如下:


using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ReuqestDemo.Models { ////// 请求结果图示 /// public class ResultModel { /// /// 唯一标识 /// public string Id { get; set; } /// /// 公司名称 /// public string EntName { get; set; } } }
Models文件夹下的SearchArgument类如下:


using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ReuqestDemo.Models { ////// 检索参数 /// public class SearchArgument { /// /// 检索关键字 /// public string Keyword { get; set; } /// /// 检索的页码 /// public int Page { get; set; } public int SearchType { get; set; } } }
CompanyData,用于接口的的实现


using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net.Http; using System.Threading.Tasks; using ReuqestDemo.Models; using ReuqestDemo.Helpers; namespace ReuqestDemo { public class CompanyData { #region 保护属性 protected HttpClient _client = new HttpClient() { Timeout = new TimeSpan(0, 0, 3) }; #endregion #region 公共方法 ////// 分页获取数据 /// /// 分页检索条件 /// public async Task > GetDataByPage(SearchCondition condition) { #region 参数转换 var arg = new SearchArgument() { Keyword = condition.Keyword, //查询条件 SearchType = 1, Page = condition.PageNo //查询页数,即第几页 }; #endregion var res = await this.GetByPage(arg); return res; } #endregion #region 保护方法 protected async Task > GetByPage(SearchArgument ccsa) { string url = $"。。。。。。"; //发送请求 var data = await HttpRequester.PostAsync >(_client, url, this.getReuestBody(ccsa), this.getRequestHeaders()); //映射结果 var res = this.mappingResult (data.Result); res.PageNo = ccsa.Page; return res; } #endregion #region 私有方法 private string getReuestBody(SearchArgument ccsa) { var parameters = new Dictionary<string, string>(); parameters.Add("keyword", ccsa.Keyword); parameters.Add("searchtype", ccsa.SearchType.ToString()); parameters.Add("page", ccsa.Page.ToString()); var body = HttpRequester.CombinParametersUrlEncode(parameters); return body; } private IDictionary<string, string> getRequestHeaders() { var headers = new Dictionary<string, string>(); return headers; } /// /// 映射结果的分页情况 /// /// /// /// private PageResult mappingResult (StartPageResult source) where T : class { var target = new PageResult (); target.PageCount = source.TotalPageCount; target.RecordCount = source.TotalCount; target.Results = source.Results; target.PageSize = source.PageSize; target.PageNo = source.CurrentPageNo; return target; } #endregion } }
单元测试得调用如下:
public void TestMethod1() { var i = new CompanyData(); var res = i.GetDataByPage(new SearchCondition() { Keyword = "一", PageNo = 1 }); Assert.IsNotNull(res); }
如上就是实现了请求的分页获取,上面主要是对比了我写的请求(在之前的对比中有篇”单元测试以文件流的形势传参调用api进行测试“写的请求太过简单),做一个对比,所以需要自己学习的地方,就做了一个demo简单的抽离了出来总结。