前言

今天我们介绍多种客户端调用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、支持异步操作

官方示例:

var client = new RestClient("https://www.xcode.me");
// client.Authenticator = new HttpBasicAuthenticator(username, password); var request = new RestRequest("resource/{id}", Method.POST);
request.AddParameter("name", "value"); // adds to POST or URL querystring based on Method
request.AddUrlSegment("id", ""); // replaces matching token in request.Resource // add parameters for all properties on an object
request.AddObject(object); // or just whitelisted properties
request.AddObject(object, "PersonId", "Name", ...); // easily add HTTP Headers
request.AddHeader("header", "value"); // add files to upload (works with compatible verbs)
request.AddFile("file", path); // execute the request
IRestResponse response = client.Execute(request);
var content = response.Content; // raw content as string // or automatically deserialize result
// return content type is sniffed but can be explicitly set via RestClient.AddHandler();
IRestResponse<Person> response2 = client.Execute<Person>(request);
var name = response2.Data.Name; // or download and save file to disk
client.DownloadData(request).SaveAs(path); // easy async support
await client.ExecuteAsync(request); // async with deserialization
var asyncHandle = client.ExecuteAsync<Person>(request, response => {
Console.WriteLine(response.Data.Name);
}); // abort the request on demand
asyncHandle.Abort();

使用案例:

Setp 1

引入RestSharp包

Setp 2

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

/// <summary>
/// API请求执行者接口
/// </summary>
public interface IRestSharp
{
/// <summary>
/// 同步执行方法
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
IRestResponse Execute(IRestRequest request); /// <summary>
/// 同步执行方法
/// </summary>
/// <typeparam name="T">返回值</typeparam>
/// <param name="request">请求参数</param>
/// <returns></returns>
T Execute<T>(IRestRequest request) where T : new(); /// <summary>
/// 异步执行方法
/// </summary>
/// <param name="request">请求参数</param>
/// <param name="callback"></param>
/// <returns></returns>
RestRequestAsyncHandle ExecuteAsync(IRestRequest request, Action<IRestResponse> callback); /// <summary>
/// 异步执行方法
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="request"></param>
/// <param name="callback"></param>
/// <returns></returns>
RestRequestAsyncHandle ExecuteAsync<T>(IRestRequest request, Action<IRestResponse<T>> callback) where T : new();
}

Setp 3

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

/// <summary>
/// Rest接口执行者
/// </summary>
public class RestSharpClient : IRestSharp
{
/// <summary>
/// 请求客户端
/// </summary>
private RestClient client; /// <summary>
/// 接口基地址 格式:http://www.xxx.com/
/// </summary>
private string BaseUrl { get; set; } /// <summary>
/// 默认的时间参数格式
/// </summary>
private string DefaultDateParameterFormat { get; set; } /// <summary>
/// 默认验证器
/// </summary>
private IAuthenticator DefaultAuthenticator { get; set; } /// <summary>
/// 构造函数
/// </summary>
/// <param name="baseUrl"></param>
/// <param name="authenticator"></param>
public RestSharpClient(string baseUrl, IAuthenticator authenticator = null)
{
BaseUrl = baseUrl;
client = new RestClient(BaseUrl);
DefaultAuthenticator = authenticator; //默认时间显示格式
DefaultDateParameterFormat = "yyyy-MM-dd HH:mm:ss"; //默认校验器
if (DefaultAuthenticator != null)
{
client.Authenticator = DefaultAuthenticator;
}
} /// <summary>
/// 通用执行方法
/// </summary>
/// <param name="request">请求参数</param>
/// <remarks>
/// 调用实例:
/// var client = new RestSharpClient("http://localhost:82/");
/// var result = client.Execute(new RestRequest("api/values", Method.GET));
/// var content = result.Content;//返回的字符串数据
/// </remarks>
/// <returns></returns>
public IRestResponse Execute(IRestRequest request)
{
request.DateFormat = string.IsNullOrEmpty(request.DateFormat) ? DefaultDateParameterFormat : request.DateFormat;
var response = client.Execute(request);
return response;
} /// <summary>
/// 同步执行方法
/// </summary>
/// <typeparam name="T">返回的泛型对象</typeparam>
/// <param name="request">请求参数</param>
/// <remarks>
/// var client = new RestSharpClient("http://localhost:82/");
/// var result = client.Execute<List<string>>(new RestRequest("api/values", Method.GET));
/// </remarks>
/// <returns></returns>
public T Execute<T>(IRestRequest request) where T : new()
{
request.DateFormat = string.IsNullOrEmpty(request.DateFormat) ? DefaultDateParameterFormat : request.DateFormat;
var response = client.Execute<T>(request);
return response.Data;
} /// <summary>
/// 异步执行方法
/// </summary>
/// <param name="request">请求参数</param>
/// <param name="callback">回调函数</param>
/// <remarks>
/// 调用实例:
/// var client = new RestSharpClient("http://localhost:62981/");
/// client.ExecuteAsync<List<string>>(new RestRequest("api/values", Method.GET), result =>
/// {
/// var content = result.Content;//返回的字符串数据
/// });
/// </remarks>
/// <returns></returns>
public RestRequestAsyncHandle ExecuteAsync(IRestRequest request, Action<IRestResponse> callback)
{
request.DateFormat = string.IsNullOrEmpty(request.DateFormat) ? DefaultDateParameterFormat : request.DateFormat;
return client.ExecuteAsync(request, callback);
} /// <summary>
/// 异步执行方法
/// </summary>
/// <typeparam name="T">返回的泛型对象</typeparam>
/// <param name="request">请求参数</param>
/// <param name="callback">回调函数</param>
/// <remarks>
/// 调用实例:
/// var client = new RestSharpClient("http://localhost:62981/");
/// client.ExecuteAsync<List<string>>(new RestRequest("api/values", Method.GET), result =>
/// {
/// if (result.StatusCode != HttpStatusCode.OK)
/// {
/// return;
/// }
/// var data = result.Data;//返回数据
/// });
/// </remarks>
/// <returns></returns> public RestRequestAsyncHandle ExecuteAsync<T>(IRestRequest request, Action<IRestResponse<T>> callback) where T : new()
{
request.DateFormat = string.IsNullOrEmpty(request.DateFormat) ? DefaultDateParameterFormat : request.DateFormat;
return client.ExecuteAsync<T>(request, callback);
}
}

Setp 4

新建一个HttpHelper帮助类

public static class HttpHelper
{
public static T GetApi<T>(int regattaId, string apiName, string pragm = "")
{
var client = new RestSharpClient($"{SiteConfig.GetSite("Url")}");
var apiNameStr = string.Format($"{SiteConfig.GetSite($"{apiName}")}", regattaId); var request = client.Execute(string.IsNullOrEmpty(pragm)
? new RestRequest(apiNameStr, Method.GET)
: new RestRequest($"{apiNameStr}/{pragm}", Method.GET)); if (request.StatusCode != HttpStatusCode.OK)
{
return (T)Convert.ChangeType(request.ErrorMessage, typeof(T));
} T result = (T)Convert.ChangeType(request.Content, typeof(T)); return result;
} public static T PostApi<T>(int regattaId, int id, string url, string alias)
{var client = new RestClient($"{url}");
IRestRequest queest = new RestRequest();
queest.Method = Method.POST;
queest.AddHeader("Accept", "application/json");
queest.RequestFormat = DataFormat.Json;
queest.AddBody(new { userid = id, Url = url, alias = alias, count = }); // uses JsonSerializer
var result = client.Execute(queest);
if (result.StatusCode != HttpStatusCode.OK)
{
return (T)Convert.ChangeType(result.ErrorMessage, typeof(T));
} T request = (T)Convert.ChangeType(result.Content, typeof(T));
return request;
}
}

Setp 5

调用

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

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

 [Route("{regattaId}/[controller]")]
[HttpGet]
public async Task<IList<NotificationDto>> GetNotifications(int regattaId)
{
return await _notificationServices.GetNotifications(regattaId);
} [Route("{regattaId}/pageviews")]
[HttpPost]
// GET: /<controller>/
public async Task PostInfo(int regattaId, [FromBody]PageViewsDto pageViewsDto)
{
await _pageviewServices.InsertPostInfo(regattaId, pageViewsDto);
}

伤处PageViewDto的定义如下:

public class PageViewsDto
{
public int Id { get; set; } public string Url { get; set; } public string Alias { get; set; } public string UserId { get; set; } public int Count { get; set; } public PageViewsDto()
{
Id = ;
Count = ;
}
}

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

携带实体参数发送Post请求

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

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

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

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

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

public static async Task<string> HttpPostAsync(string url, string postData, string certPath = "", string certPwd = "")
{
var request = CreateJsonRequest(url, HttpMethod.POST, postData, certPath, certPwd);
return await GetResponseStringAsync(request);
}
private static HttpWebRequest CreateJsonRequest(string url, HttpMethod method, string postData = "", string certpath = "", string certpwd = "")
{
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = method.ToString();
request.ContentType = "application/json; charset=utf-8";
request.Accept = "*/*";
request.Timeout = ;
request.AllowAutoRedirect = false;
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback((a, b, c, d) => true);
if (!string.IsNullOrEmpty(certpath) && !string.IsNullOrEmpty(certpwd))
{
X509Certificate2 cer = new X509Certificate2(certpath, certpwd,
X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet);
request.ClientCertificates.Add(cer);
}
if (method == HttpMethod.POST)
{
using (var sw = new StreamWriter(request.GetRequestStream()))
{
sw.Write(postData);
}
}
return request;
} private static async Task<string> GetResponseStringAsync(HttpWebRequest request)
{
using (var response = await request.GetResponseAsync() as HttpWebResponse)
{
using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
{
return reader.ReadToEnd();//获取响应
}
}
}

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

public enum HttpMethod
{
GET,
POST
}

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

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

这样,我们就实现了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. 201871010131-张兴盼《面向对象程序设计(java)》第八周学习总结

    项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...

  2. XSS-Stored

    存储型XSS (持久性XSS) 将恶意JavaScript代码存储在数据库,当下次用户浏览的时候执行 Low <?php if( isset( $_POST[ 'btnSign' ] ) ) { ...

  3. 测试脚本中的等待方法 alter对话框处理

    测试脚本中的等待方法 等待是为了使脚本执行更加稳定 1. 常用的休眠方式:time模块的sleep方法 2. selenium模块中的等待方法 等待查找5s 查找不到就报错 对登录测试py进行修改 a ...

  4. JDOJ 1946 求最长不下降子序列个数

    Description 设有一个整数的序列:b1,b2,…,bn,对于下标i1<i2<…<im,若有bi1≤bi2≤…≤bim 则称存在一个长度为m的不下降序列. 现在有n个数,请你 ...

  5. CloudCompare打开pcd文件

    Ubuntu下CloudCompare稳定版本无法打开pcd点云文件,切换到edge版本即可 $ sudo snap refresh --edge cloudcompare

  6. 怎么写Java项目?

    我们通常说的Java项目也都是JavaWeb,J2ee项目;现在说的是JavaWeb. 最简单的办法 多看别人项目源码 在别人基础上修改,而现在要一点一点掰开看看. 1.立项: 要做什么东西,最后的要 ...

  7. docker--发布docker镜像

    前戏 前面我们自己做了个docker镜像,我们可以上传到docker hub,别人就可以下载使用了 发布到docker hub 我们前面使用docker search 查找的镜像都是从docker h ...

  8. A1070 Mooncake (25 分)

    一.参考代码 #include<cstdio> #include<algorithm> #include<iostream> using namespace std ...

  9. Linux性能优化实战学习笔记:第四十八讲

    一.上节回顾 上一节,我们一起学习了如何分析网络丢包的问题,特别是从链路层.网络层以及传输层等主要的协议栈中进行分析. 不过,通过前面这几层的分析,我们还是没有找出最终的性能瓶颈.看来,还是要继续深挖 ...

  10. [LeetCode] 145. Binary Tree Postorder Traversal 二叉树的后序遍历

    Given a binary tree, return the postorder traversal of its nodes' values. For example: Given binary ...