.NET Core 下调用WebAPI
前言
今天我们介绍多种客户端调用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的更多相关文章
- .net core 下调用.net framework框架的WCF方法写法
通过添加服务引用后生成的代码,可以得知首先要设置Basic连接写法的属性,并且设置WCF服务的地址: 我在这里建立工厂类如下: using System; using System.ServiceMo ...
- Core下简易WebApi
代码很粗糙~ 粘贴github地址 https://github.com/htrlq/MiniAspNetCoreMini demo public class Startup { public Sta ...
- .net core下简单构建高可用服务集群
一说到集群服务相信对普通开发者来说肯定想到很复杂的事情,如zeekeeper ,反向代理服务网关等一系列的搭建和配置等等:总得来说需要有一定经验和规划的团队才能应用起来.在这文章里你能看到在.net ...
- ASP.NET Core 3.0 WebApi中使用Swagger生成API文档简介
参考地址,官网:https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/getting-started-with-swashbuckle?view ...
- WebApi接口 - 如何在应用中调用webapi接口
很高兴能再次和大家分享webapi接口的相关文章,本篇将要讲解的是如何在应用中调用webapi接口:对于大部分做内部管理系统及类似系统的朋友来说很少会去调用别人的接口,因此可能在这方面存在一些困惑,希 ...
- 跨域调用webapi
web端跨域调用webapi 在做Web开发中,常常会遇到跨域的问题,到目前为止,已经有非常多的跨域解决方案. 通过自己的研究以及在网上看了一些大神的博客,写了一个Demo 首先新建一个webap ...
- .NET Core下使用gRpc公开服务(SSL/TLS)
一.前言 前一阵子关于.NET的各大公众号都发表了关于gRpc的消息,而随之而来的就是一波关于.NET Core下如何使用的教程,但是在这众多的教程中基本都是泛泛而谈,难以实际在实际环境中使用,而该篇 ...
- .Net Core下如何管理配置文件
一.前言 根据该issues来看,System.Configuration在.net core中已经不存在了,那么取而代之的是由Microsoft.Extensions.Cnfiguration.XX ...
- Web API应用架构在Winform混合框架中的应用(3)--Winfrom界面调用WebAPI的过程分解
最近一直在整合WebAPI.Winform界面.手机短信.微信公众号.企业号等功能,希望把它构建成一个大的应用平台,把我所有的产品线完美连接起来,同时也在探索.攻克更多的技术问题,并抽空写写博客,把相 ...
随机推荐
- day8_7.8 文件操作
一.文件模式 1.在文件的操作中,也有很多补充 的模式可使用 1.r+,可读可写模式,在此模式中,操作权限时可读可写,这里的写与write模式不一样的是,不再清空文件内容,写的内容添加到文件的后面,而 ...
- loadrunner 集合点设置2
1.集合点的含义 当通过controller虚拟多个用户执行该脚本时.用户的启动或运行步骤不一定都是同步的,集合点是在脚本的某处设置一个标记.当有虚拟用户运行到这个标记处时,停下等待,直到 ...
- SLAM:暑期学校
专门开个(大)坑: RGB-D SLAM:姜翰青,商汤 视觉SLAM:章国锋,浙大CAD&CG国家重点实验室
- SpringDataJPA对SimpleJpaRepository/JPARepository返回结果的进一步处理(大体浏览,没细看)
package com.yb.fw.core.helper; public enum Op { LIKE,// like NOTLIKE,// notlike EQ,// = NOTEQ,// != ...
- Python进阶-XIII 导入模块和包 异常处理
一.模块的导入 1).import # 测试一:money与my_module.money不冲突 import my_module money=10 print(my_module.money) '' ...
- haproxy是什么以及作用?
HAProxy 是一款提供高可用性.负载均衡以及基于TCP(第四层)和HTTP(第七层)应用的代理软件,支持虚拟主机,它是免费.快速并且可靠的一种解决方案. HAProxy特别适用于那些负载特大的we ...
- Linux学习笔记-第3天 - 勤能补拙
学一门技术,基础一定要打牢,多练习是关键,还要尽可能理解其背后的知识.并时刻提醒自己,求知若饥,虚心若愚.
- [RN] React Native 错误 Module does not exist in the module map
React Native 错误 Module does not exist in the module map 代码如下: import Login from 'login' import Index ...
- Linux文件系统与日志
1.inode 包含文件的元信息(1)inode 内容:文件的字节数.拥有者的 UID.GID.文件的读写执行权限.时间戳等,但不包含文件名.文件名是储存在目录的目录项中.(2)查看文件的 inode ...
- MySQL实战45讲学习笔记:第二十八讲
一.读写分离架构 在上一篇文章中,我和你介绍了一主多从的结构以及切换流程.今天我们就继续聊聊一主多从架构的应用场景:读写分离,以及怎么处理主备延迟导致的读写分离问题. 我们在上一篇文章中提到的一主多从 ...