前言

今天我们介绍多种客户端调用WebApi的方式,可以是原生写的,也可以借助.NET 框架下的其他HTTP库。我们一起来看看它们之间的一些异同吧~

RestSharp

首先要介绍的就是这款REST 客户端,我们先来一起看看它的简介:

RestSharp 是一个基于 .NET 框架的 REST 客户端,RestSharp 是一个轻量的,不依赖任何第三方的组件或者类库的 HTTP 组件,RestSharp具有以下的优点:

01、支持.NET4.5.2+ 和 .NET Standard 2.0 平台
02、使用NuGet轻松安装开发包
03、自动 XML 和 JSON 反序列化
04、通过 ISerializer 和 IDeserializer 自定义序列化和反序列化为
05、模糊匹配元素名称 (例如:XML或JSON中的product_id将匹配名为ProductId的C#属性)
06、自动检测返回内容的类型
07、指出 GET, POST, PUT, PATCH, HEAD, OPTIONS, DELETE 和 COPY 请求,支持其它非标准 HTTP 方法
08、OAuth 1.0、OAuth 2.0、Basic、NTLM 和基于参数的身份认证
09、通过 IAuthenticator 接口自定义身份验证方案
10、支持异步操作

官方示例:

  1. var client = new RestClient("https://www.xcode.me");
  2. // client.Authenticator = new HttpBasicAuthenticator(username, password);
  3.  
  4. var request = new RestRequest("resource/{id}", Method.POST);
  5. request.AddParameter("name", "value"); // adds to POST or URL querystring based on Method
  6. request.AddUrlSegment("id", ""); // replaces matching token in request.Resource
  7.  
  8. // add parameters for all properties on an object
  9. request.AddObject(object);
  10.  
  11. // or just whitelisted properties
  12. request.AddObject(object, "PersonId", "Name", ...);
  13.  
  14. // easily add HTTP Headers
  15. request.AddHeader("header", "value");
  16.  
  17. // add files to upload (works with compatible verbs)
  18. request.AddFile("file", path);
  19.  
  20. // execute the request
  21. IRestResponse response = client.Execute(request);
  22. var content = response.Content; // raw content as string
  23.  
  24. // or automatically deserialize result
  25. // return content type is sniffed but can be explicitly set via RestClient.AddHandler();
  26. IRestResponse<Person> response2 = client.Execute<Person>(request);
  27. var name = response2.Data.Name;
  28.  
  29. // or download and save file to disk
  30. client.DownloadData(request).SaveAs(path);
  31.  
  32. // easy async support
  33. await client.ExecuteAsync(request);
  34.  
  35. // async with deserialization
  36. var asyncHandle = client.ExecuteAsync<Person>(request, response => {
  37. Console.WriteLine(response.Data.Name);
  38. });
  39.  
  40. // abort the request on demand
  41. asyncHandle.Abort();

使用案例:

Setp 1

引入RestSharp包

Setp 2

新建一个API请求执行者的接口IRestSharp:

  1. /// <summary>
  2. /// API请求执行者接口
  3. /// </summary>
  4. public interface IRestSharp
  5. {
  6. /// <summary>
  7. /// 同步执行方法
  8. /// </summary>
  9. /// <param name="request"></param>
  10. /// <returns></returns>
  11. IRestResponse Execute(IRestRequest request);
  12.  
  13. /// <summary>
  14. /// 同步执行方法
  15. /// </summary>
  16. /// <typeparam name="T">返回值</typeparam>
  17. /// <param name="request">请求参数</param>
  18. /// <returns></returns>
  19. T Execute<T>(IRestRequest request) where T : new();
  20.  
  21. /// <summary>
  22. /// 异步执行方法
  23. /// </summary>
  24. /// <param name="request">请求参数</param>
  25. /// <param name="callback"></param>
  26. /// <returns></returns>
  27. RestRequestAsyncHandle ExecuteAsync(IRestRequest request, Action<IRestResponse> callback);
  28.  
  29. /// <summary>
  30. /// 异步执行方法
  31. /// </summary>
  32. /// <typeparam name="T"></typeparam>
  33. /// <param name="request"></param>
  34. /// <param name="callback"></param>
  35. /// <returns></returns>
  36. RestRequestAsyncHandle ExecuteAsync<T>(IRestRequest request, Action<IRestResponse<T>> callback) where T : new();
  37. }

Setp 3

新建一个实现类RestSharpClient,实现上述接口

  1. /// <summary>
  2. /// Rest接口执行者
  3. /// </summary>
  4. public class RestSharpClient : IRestSharp
  5. {
  6. /// <summary>
  7. /// 请求客户端
  8. /// </summary>
  9. private RestClient client;
  10.  
  11. /// <summary>
  12. /// 接口基地址 格式:http://www.xxx.com/
  13. /// </summary>
  14. private string BaseUrl { get; set; }
  15.  
  16. /// <summary>
  17. /// 默认的时间参数格式
  18. /// </summary>
  19. private string DefaultDateParameterFormat { get; set; }
  20.  
  21. /// <summary>
  22. /// 默认验证器
  23. /// </summary>
  24. private IAuthenticator DefaultAuthenticator { get; set; }
  25.  
  26. /// <summary>
  27. /// 构造函数
  28. /// </summary>
  29. /// <param name="baseUrl"></param>
  30. /// <param name="authenticator"></param>
  31. public RestSharpClient(string baseUrl, IAuthenticator authenticator = null)
  32. {
  33. BaseUrl = baseUrl;
  34. client = new RestClient(BaseUrl);
  35. DefaultAuthenticator = authenticator;
  36.  
  37. //默认时间显示格式
  38. DefaultDateParameterFormat = "yyyy-MM-dd HH:mm:ss";
  39.  
  40. //默认校验器
  41. if (DefaultAuthenticator != null)
  42. {
  43. client.Authenticator = DefaultAuthenticator;
  44. }
  45. }
  46.  
  47. /// <summary>
  48. /// 通用执行方法
  49. /// </summary>
  50. /// <param name="request">请求参数</param>
  51. /// <remarks>
  52. /// 调用实例:
  53. /// var client = new RestSharpClient("http://localhost:82/");
  54. /// var result = client.Execute(new RestRequest("api/values", Method.GET));
  55. /// var content = result.Content;//返回的字符串数据
  56. /// </remarks>
  57. /// <returns></returns>
  58. public IRestResponse Execute(IRestRequest request)
  59. {
  60. request.DateFormat = string.IsNullOrEmpty(request.DateFormat) ? DefaultDateParameterFormat : request.DateFormat;
  61. var response = client.Execute(request);
  62. return response;
  63. }
  64.  
  65. /// <summary>
  66. /// 同步执行方法
  67. /// </summary>
  68. /// <typeparam name="T">返回的泛型对象</typeparam>
  69. /// <param name="request">请求参数</param>
  70. /// <remarks>
  71. /// var client = new RestSharpClient("http://localhost:82/");
  72. /// var result = client.Execute<List<string>>(new RestRequest("api/values", Method.GET));
  73. /// </remarks>
  74. /// <returns></returns>
  75. public T Execute<T>(IRestRequest request) where T : new()
  76. {
  77. request.DateFormat = string.IsNullOrEmpty(request.DateFormat) ? DefaultDateParameterFormat : request.DateFormat;
  78. var response = client.Execute<T>(request);
  79. return response.Data;
  80. }
  81.  
  82. /// <summary>
  83. /// 异步执行方法
  84. /// </summary>
  85. /// <param name="request">请求参数</param>
  86. /// <param name="callback">回调函数</param>
  87. /// <remarks>
  88. /// 调用实例:
  89. /// var client = new RestSharpClient("http://localhost:62981/");
  90. /// client.ExecuteAsync<List<string>>(new RestRequest("api/values", Method.GET), result =>
  91. /// {
  92. /// var content = result.Content;//返回的字符串数据
  93. /// });
  94. /// </remarks>
  95. /// <returns></returns>
  96. public RestRequestAsyncHandle ExecuteAsync(IRestRequest request, Action<IRestResponse> callback)
  97. {
  98. request.DateFormat = string.IsNullOrEmpty(request.DateFormat) ? DefaultDateParameterFormat : request.DateFormat;
  99. return client.ExecuteAsync(request, callback);
  100. }
  101.  
  102. /// <summary>
  103. /// 异步执行方法
  104. /// </summary>
  105. /// <typeparam name="T">返回的泛型对象</typeparam>
  106. /// <param name="request">请求参数</param>
  107. /// <param name="callback">回调函数</param>
  108. /// <remarks>
  109. /// 调用实例:
  110. /// var client = new RestSharpClient("http://localhost:62981/");
  111. /// client.ExecuteAsync<List<string>>(new RestRequest("api/values", Method.GET), result =>
  112. /// {
  113. /// if (result.StatusCode != HttpStatusCode.OK)
  114. /// {
  115. /// return;
  116. /// }
  117. /// var data = result.Data;//返回数据
  118. /// });
  119. /// </remarks>
  120. /// <returns></returns>
  121.  
  122. public RestRequestAsyncHandle ExecuteAsync<T>(IRestRequest request, Action<IRestResponse<T>> callback) where T : new()
  123. {
  124. request.DateFormat = string.IsNullOrEmpty(request.DateFormat) ? DefaultDateParameterFormat : request.DateFormat;
  125. return client.ExecuteAsync<T>(request, callback);
  126. }
  127. }

Setp 4

新建一个HttpHelper帮助类

  1. public static class HttpHelper
  2. {
  3. public static T GetApi<T>(int regattaId, string apiName, string pragm = "")
  4. {
  5. var client = new RestSharpClient($"{SiteConfig.GetSite("Url")}");
  6. var apiNameStr = string.Format($"{SiteConfig.GetSite($"{apiName}")}", regattaId);
  7.  
  8. var request = client.Execute(string.IsNullOrEmpty(pragm)
  9. ? new RestRequest(apiNameStr, Method.GET)
  10. : new RestRequest($"{apiNameStr}/{pragm}", Method.GET));
  11.  
  12. if (request.StatusCode != HttpStatusCode.OK)
  13. {
  14. return (T)Convert.ChangeType(request.ErrorMessage, typeof(T));
  15. }
  16.  
  17. T result = (T)Convert.ChangeType(request.Content, typeof(T));
  18.  
  19. return result;
  20. }
  21.  
  22. public static T PostApi<T>(int regattaId, int id, string url, string alias)
  23. {var client = new RestClient($"{url}");
  24. IRestRequest queest = new RestRequest();
  25. queest.Method = Method.POST;
  26. queest.AddHeader("Accept", "application/json");
  27. queest.RequestFormat = DataFormat.Json;
  28. queest.AddBody(new { userid = id, Url = url, alias = alias, count = }); // uses JsonSerializer
  29. var result = client.Execute(queest);
  30. if (result.StatusCode != HttpStatusCode.OK)
  31. {
  32. return (T)Convert.ChangeType(result.ErrorMessage, typeof(T));
  33. }
  34.  
  35. T request = (T)Convert.ChangeType(result.Content, typeof(T));
  36. return request;
  37. }
  38. }

Setp 5

调用

  1. //Get
  2. var notificationlist = HttpHelper.GetApi<string>(regattaId, "notification");//第二个参数是配置文件中的API地址
  3. //Post
  4. Task.FromResult(HttpHelper.PostApi<string>(regattaId, id, url, alias))

在API端接收上述两个请求:

  1. [Route("{regattaId}/[controller]")]
  2. [HttpGet]
  3. public async Task<IList<NotificationDto>> GetNotifications(int regattaId)
  4. {
  5. return await _notificationServices.GetNotifications(regattaId);
  6. }
  7.  
  8. [Route("{regattaId}/pageviews")]
  9. [HttpPost]
  10. // GET: /<controller>/
  11. public async Task PostInfo(int regattaId, [FromBody]PageViewsDto pageViewsDto)
  12. {
  13. await _pageviewServices.InsertPostInfo(regattaId, pageViewsDto);
  14. }

伤处PageViewDto的定义如下:

  1. public class PageViewsDto
  2. {
  3. public int Id { get; set; }
  4.  
  5. public string Url { get; set; }
  6.  
  7. public string Alias { get; set; }
  8.  
  9. public string UserId { get; set; }
  10.  
  11. public int Count { get; set; }
  12.  
  13. public PageViewsDto()
  14. {
  15. Id = ;
  16. Count = ;
  17. }
  18. }

更多详情可访问github:https://github.com/restsharp/RestSharp

携带实体参数发送Post请求

假设现在我们需要修改用户的一些基本信息,这些信息需要通过前端 发送到API端,那么该如何实现呢?

  1. public async Task<int> UpdateUser(PersonModel model)
  2. {
  3. var url = $"{SiteConfig.GetSite("Url")}{SiteConfig.GetSite("updateUserByAccount")}";
  4. var resultDetil = await HttpUtil.PostResultAsync<int>(model, url);
  5. return resultDetil;
  6. }

前端请求大概如上,地址URL和API名称都再配置文件中获取,下面我们看看PostResultAsync中是如何实现Post请求携带Post参数的吧

  1. /// <summary>
  2. /// 发起POST请求,并获取请求返回值
  3. /// </summary>
  4. /// <typeparam name="T">返回值类型</typeparam>
  5. /// <param name="obj">数据实体</param>
  6. /// <param name="url">接口地址</param>
  7. public static async Task<T> PostResultAsync<T>(object obj, string url)
  8. {
  9. //序列化设置
  10. var setting = new JsonSerializerSettings();
  11. //解决枚举类型序列化时,被转换成数字的问题
  12. setting.Converters.Add(new StringEnumConverter());
  13. setting.NullValueHandling = NullValueHandling.Ignore;
  14. var retdata = await HttpPostAsync(url, JsonConvert.SerializeObject(obj, setting));
  15. return JsonConvert.DeserializeObject<T>(retdata);
  16. }

从上面我们可以看出,首先定义了一个泛型方法,其中接收一个参数类型是Object。另一个是url,在这个异步方法体重,我们去call了另一个请求方法

  1. public static async Task<string> HttpPostAsync(string url, string postData, string certPath = "", string certPwd = "")
  2. {
  3. var request = CreateJsonRequest(url, HttpMethod.POST, postData, certPath, certPwd);
  4. return await GetResponseStringAsync(request);
  5. }
  1. private static HttpWebRequest CreateJsonRequest(string url, HttpMethod method, string postData = "", string certpath = "", string certpwd = "")
  2. {
  3. var request = (HttpWebRequest)WebRequest.Create(url);
  4. request.Method = method.ToString();
  5. request.ContentType = "application/json; charset=utf-8";
  6. request.Accept = "*/*";
  7. request.Timeout = ;
  8. request.AllowAutoRedirect = false;
  9. ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback((a, b, c, d) => true);
  10. if (!string.IsNullOrEmpty(certpath) && !string.IsNullOrEmpty(certpwd))
  11. {
  12. X509Certificate2 cer = new X509Certificate2(certpath, certpwd,
  13. X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet);
  14. request.ClientCertificates.Add(cer);
  15. }
  16. if (method == HttpMethod.POST)
  17. {
  18. using (var sw = new StreamWriter(request.GetRequestStream()))
  19. {
  20. sw.Write(postData);
  21. }
  22. }
  23. return request;
  24. }
  25.  
  26. private static async Task<string> GetResponseStringAsync(HttpWebRequest request)
  27. {
  28. using (var response = await request.GetResponseAsync() as HttpWebResponse)
  29. {
  30. using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
  31. {
  32. return reader.ReadToEnd();//获取响应
  33. }
  34. }
  35. }

上述中的HttpMethod.post为枚举,此枚举中列举了http请求常用格式

  1. public enum HttpMethod
  2. {
  3. GET,
  4. POST
  5. }

让我们看看上面提到的在Api端是如何接收的吧

  1. [Route("[controller]/UpdateUserByAccount")]
  2. [HttpPost]
  3. public async Task<int> UpdateUserByAccount([FromBody]PersonDto model)
  4. {
  5. return await _authenticationService.UpdateUserByAccount(model);
  6. }

这样,我们就实现了Post请求API时携带实体参数

.NET Core 下调用WebAPI的更多相关文章

  1. .net core 下调用.net framework框架的WCF方法写法

    通过添加服务引用后生成的代码,可以得知首先要设置Basic连接写法的属性,并且设置WCF服务的地址: 我在这里建立工厂类如下: using System; using System.ServiceMo ...

  2. Core下简易WebApi

    代码很粗糙~ 粘贴github地址 https://github.com/htrlq/MiniAspNetCoreMini demo public class Startup { public Sta ...

  3. .net core下简单构建高可用服务集群

    一说到集群服务相信对普通开发者来说肯定想到很复杂的事情,如zeekeeper ,反向代理服务网关等一系列的搭建和配置等等:总得来说需要有一定经验和规划的团队才能应用起来.在这文章里你能看到在.net ...

  4. ASP.NET Core 3.0 WebApi中使用Swagger生成API文档简介

    参考地址,官网:https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/getting-started-with-swashbuckle?view ...

  5. WebApi接口 - 如何在应用中调用webapi接口

    很高兴能再次和大家分享webapi接口的相关文章,本篇将要讲解的是如何在应用中调用webapi接口:对于大部分做内部管理系统及类似系统的朋友来说很少会去调用别人的接口,因此可能在这方面存在一些困惑,希 ...

  6. 跨域调用webapi

    web端跨域调用webapi   在做Web开发中,常常会遇到跨域的问题,到目前为止,已经有非常多的跨域解决方案. 通过自己的研究以及在网上看了一些大神的博客,写了一个Demo 首先新建一个webap ...

  7. .NET Core下使用gRpc公开服务(SSL/TLS)

    一.前言 前一阵子关于.NET的各大公众号都发表了关于gRpc的消息,而随之而来的就是一波关于.NET Core下如何使用的教程,但是在这众多的教程中基本都是泛泛而谈,难以实际在实际环境中使用,而该篇 ...

  8. .Net Core下如何管理配置文件

    一.前言 根据该issues来看,System.Configuration在.net core中已经不存在了,那么取而代之的是由Microsoft.Extensions.Cnfiguration.XX ...

  9. Web API应用架构在Winform混合框架中的应用(3)--Winfrom界面调用WebAPI的过程分解

    最近一直在整合WebAPI.Winform界面.手机短信.微信公众号.企业号等功能,希望把它构建成一个大的应用平台,把我所有的产品线完美连接起来,同时也在探索.攻克更多的技术问题,并抽空写写博客,把相 ...

随机推荐

  1. HDU1213:How Many Tables(并查集入门)

    -----------刷点水题练习java------------- 题意:给定N点,M边的无向图,问有多少个连通块. 思路:可以搜索;  可以并查集.这里用并查集练习java的数组使用,ans=N, ...

  2. 【使用篇二】SpringBoot单元测试(10)

    SpringCloud单元测试:https://www.cnblogs.com/myitnews/p/11796321.html 1. 创建项目Maven Project,修改pom.xml < ...

  3. VUE小练习(按钮颜色,数组映射)

    VUE小练习(按钮颜色,数组映射) ## 1.有红.黄.蓝三个按钮,以及一个200x200矩形框box, 点击不同的按钮,box的颜色会被切换成指定的颜色 ''' 解法一:我本来的思路,把三个按钮绑定 ...

  4. 深度学习的encoder和decoder

    所谓编码,就是将输入序列转化成一个固定长度的向量:解码,就是将之前生成的固定向量再转化成输出序列.

  5. 使用Python获取图片的物理尺寸(KB)

    如何获取图片的物理尺寸,而非(width, height)? #! -*- coding: utf-8 -*- import requests import io url = "https: ...

  6. RHEL7 安装Docker-CE

    rhel7官方有源可以直接使用,前提是需要订阅, 参考地址 通过添加CentOS7 源,进行安装: 通过添加CentOS7 源,进行安装 参考博客 安装container-selinux依赖(Requ ...

  7. koa2+mysql+vue实现用户注册、登录、token验证

    说明: node.js提供接口,vue展现页面,前后端分离,出于编辑器功能和编辑习惯,vue用HbuilderX,node.js用VScode.(PS:仅作为学习笔记,如有不当之处欢迎指出,在此先谢为 ...

  8. [LeetCode] 883. Projection Area of 3D Shapes 三维物体的投影面积

    On a N * N grid, we place some 1 * 1 * 1 cubes that are axis-aligned with the x, y, and z axes. Each ...

  9. [LeetCode] 190. Reverse Bits 颠倒二进制位

    Reverse bits of a given 32 bits unsigned integer. Example 1: Input: 00000010100101000001111010011100 ...

  10. [LeetCode] 98. Validate Binary Search Tree 验证二叉搜索树

    Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as ...