zoukankan      html  css  js  c++  java
  • .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", "123"); // 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 = 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;
            }
    }

    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 = 0;
                Count = 1;
            }
        }

    更多详情可访问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 = 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时携带实体参数

  • 相关阅读:
    android添加文件打开方式以及参数传递
    Android文字图片写入CSV(Base64)并分享
    Fragment嵌套Fragment要用getChildFragmentManager
    Android数据库存取图片以及转换成缩略图
    2015已经过去三分之一了
    GridView和ListView简单使用
    WPF处理Windows消息
    90后码农的北京求职之旅
    排序算法复习—快速排序
    排序算法复习—归并排序
  • 原文地址:https://www.cnblogs.com/zhangxiaoyong/p/10771566.html
Copyright © 2011-2022 走看看