今天我们介绍多种客户端调用WebApi的方式,可以是原生写的,也可以借助.NET 框架下的其他HTTP库。我们一起来看看它们之间的一些异同吧~
首先要介绍的就是这款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 Methodrequest.AddUrlSegment("id", "123"); // replaces matching token in request.Resource// add parameters for all properties on an objectrequest.AddObject(object);// or just whitelisted propertiesrequest.AddObject(object, "PersonId", "Name", ...);// easily add HTTP Headersrequest.AddHeader("header", "value");// add files to upload (works with compatible verbs)request.AddFile("file", path);// execute the requestIRestResponse 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 diskclient.DownloadData(request).SaveAs(path);// easy async supportawait client.ExecuteAsync(request);// async with deserializationvar asyncHandle = client.ExecuteAsync<Person>(request, response => { Console.WriteLine(response.Data.Name);});// abort the request on demandasyncHandle.Abort();
使用案例:
引入RestSharp包
新建一个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(); }
新建一个实现类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); } }
新建一个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 = 1 }); // 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; }}
调用
//Get var notificationlist = HttpHelper.GetApi<string>(regattaId, "notification");//第二个参数是配置文件中的API地址//PostTask.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 = 0; Count = 1; } }
更多详情可访问github:https://github.com/restsharp/RestSharp
假设现在我们需要修改用户的一些基本信息,这些信息需要通过前端 发送到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 = 15000; 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时携带实体参数
__EOF__
作 者:潇十一郎
出 处:https://www.cnblogs.com/zhangxiaoyong/p/10771566.html
关于博主:编程路上的小学生,热爱技术,喜欢专研。评论和私信会在第一时间回复。或者直接私信我。
版权声明:署名 - 非商业性使用 - 禁止演绎,协议普通文本 | 协议法律文本。
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
联系客服