今天咱們介紹多種客戶端調用WebApi的方式,能夠是原生寫的,也能夠藉助.NET 框架下的其餘HTTP庫。咱們一塊兒來看看它們之間的一些異同吧~前端
首先要介紹的就是這款REST 客戶端,咱們先來一塊兒看看它的簡介:git
RestSharp 是一個基於 .NET 框架的 REST 客戶端,RestSharp 是一個輕量的,不依賴任何第三方的組件或者類庫的 HTTP 組件,RestSharp具備如下的優勢:github
0一、支持.NET4.5.2+ 和 .NET Standard 2.0 平臺
0二、使用NuGet輕鬆安裝開發包
0三、自動 XML 和 JSON 反序列化
0四、經過 ISerializer 和 IDeserializer 自定義序列化和反序列化爲
0五、模糊匹配元素名稱 (例如:XML或JSON中的product_id將匹配名爲ProductId的C#屬性)
0六、自動檢測返回內容的類型
0七、指出 GET, POST, PUT, PATCH, HEAD, OPTIONS, DELETE 和 COPY 請求,支持其它非標準 HTTP 方法
0八、OAuth 1.0、OAuth 2.0、Basic、NTLM 和基於參數的身份認證
0九、經過 IAuthenticator 接口自定義身份驗證方案
十、支持異步操做json
官方示例:api
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();
使用案例:xcode
引入RestSharp包app
新建一個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幫助類async
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地址 //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
假設如今咱們須要修改用戶的一些基本信息,這些信息須要經過前端 發送到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時攜帶實體參數