如何使用c#调用REST API ?

这是我到目前为止的代码:

    public class Class1
{
private const string URL = "https://sub.domain.com/objects.json?api_key=123";
private const string DATA = @"{""object"":{""name"":""Name""}}";


static void Main(string[] args)
{
Class1.CreateObject();
}


private static void CreateObject()
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
request.Method = "POST";
request.ContentType = "application/json";
request.ContentLength = DATA.Length;
StreamWriter requestWriter = new StreamWriter(request.GetRequestStream(), System.Text.Encoding.ASCII);
requestWriter.Write(DATA);
requestWriter.Close();


try {
WebResponse webResponse = request.GetResponse();
Stream webStream = webResponse.GetResponseStream();
StreamReader responseReader = new StreamReader(webStream);
string response = responseReader.ReadToEnd();
Console.Out.WriteLine(response);
responseReader.Close();
} catch (Exception e) {
Console.Out.WriteLine("-----------------");
Console.Out.WriteLine(e.Message);
}


}
}

问题是我认为异常块正在被触发(因为当我删除try-catch时,我得到一个服务器错误(500)消息。但是我没有看到控制台。我在catch block里放了几行。

我的控制台:

The thread 'vshost.NotifyLoad' (0x1a20) has exited with code 0 (0x0).
The thread '<No Name>' (0x1988) has exited with code 0 (0x0).
The thread 'vshost.LoadReference' (0x1710) has exited with code 0 (0x0).
'ConsoleApplication1.vshost.exe' (Managed (v4.0.30319)): Loaded 'c:\users\l. preston sego iii\documents\visual studio 11\Projects\ConsoleApplication1\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe', Symbols loaded.
'ConsoleApplication1.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Configuration\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Configuration.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
A first chance exception of type 'System.Net.WebException' occurred in System.dll
The thread 'vshost.RunParkingWindow' (0x184c) has exited with code 0 (0x0).
The thread '<No Name>' (0x1810) has exited with code 0 (0x0).
The program '[2780] ConsoleApplication1.vshost.exe: Program Trace' has exited with code 0 (0x0).
The program '[2780] ConsoleApplication1.vshost.exe: Managed (v4.0.30319)' has exited with code 0 (0x0).
1391171 次浏览

我的建议是使用RestSharp。你可以调用REST服务,并将它们转换为对象,只需要很少的样板代码就可以解析响应。这不会解决您的特定错误,但它回答了如何调用REST服务的总体问题。必须更改代码才能使用它,这应该会在易用性和健壮性方面得到回报。不过这只是我的个人观点。

例子:

namespace RestSharpThingy
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;


using RestSharp;


public static class Program
{
public static void Main()
{
Uri baseUrl = new Uri("https://httpbin.org/");
IRestClient client = new RestClient(baseUrl);
IRestRequest request = new RestRequest("get", Method.GET) { Credentials = new NetworkCredential("testUser", "P455w0rd") };


request.AddHeader("Authorization", "Bearer qaPmk9Vw8o7r7UOiX-3b-8Z_6r3w0Iu2pecwJ3x7CngjPp2fN3c61Q_5VU3y0rc-vPpkTKuaOI2eRs3bMyA5ucKKzY1thMFoM0wjnReEYeMGyq3JfZ-OIko1if3NmIj79ZSpNotLL2734ts2jGBjw8-uUgKet7jQAaq-qf5aIDwzUo0bnGosEj_UkFxiJKXPPlF2L4iNJSlBqRYrhw08RK1SzB4tf18Airb80WVy1Kewx2NGq5zCC-SCzvJW-mlOtjIDBAQ5intqaRkwRaSyjJ_MagxJF_CLc4BNUYC3hC2ejQDoTE6HYMWMcg0mbyWghMFpOw3gqyfAGjr6LPJcIly__aJ5__iyt-BTkOnMpDAZLTjzx4qDHMPWeND-TlzKWXjVb5yMv5Q6Jg6UmETWbuxyTdvGTJFzanUg1HWzPr7gSs6GLEv9VDTMiC8a5sNcGyLcHBIJo8mErrZrIssHvbT8ZUPWtyJaujKvdgazqsrad9CO3iRsZWQJ3lpvdQwucCsyjoRVoj_mXYhz3JK3wfOjLff16Gy1NLbj4gmOhBBRb8rJnUXnP7rBHs00FAk59BIpKLIPIyMgYBApDCut8V55AgXtGs4MgFFiJKbuaKxq8cdMYEVBTzDJ-S1IR5d6eiTGusD5aFlUkAs9NV_nFw");
request.AddParameter("clientId", 123);


IRestResponse<RootObject> response = client.Execute<RootObject>(request);


if (response.IsSuccessful)
{
response.Data.Write();
}
else
{
Console.WriteLine(response.ErrorMessage);
}


Console.WriteLine();


string path = Assembly.GetExecutingAssembly().Location;
string name = Path.GetFileName(path);


request = new RestRequest("post", Method.POST);
request.AddFile(name, File.ReadAllBytes(path), name, "application/octet-stream");
response = client.Execute<RootObject>(request);
if (response.IsSuccessful)
{
response.Data.Write();
}
else
{
Console.WriteLine(response.ErrorMessage);
}


Console.ReadLine();
}


private static void Write(this RootObject rootObject)
{
Console.WriteLine("clientId: " + rootObject.args.clientId);
Console.WriteLine("Accept: " + rootObject.headers.Accept);
Console.WriteLine("AcceptEncoding: " + rootObject.headers.AcceptEncoding);
Console.WriteLine("AcceptLanguage: " + rootObject.headers.AcceptLanguage);
Console.WriteLine("Authorization: " + rootObject.headers.Authorization);
Console.WriteLine("Connection: " + rootObject.headers.Connection);
Console.WriteLine("Dnt: " + rootObject.headers.Dnt);
Console.WriteLine("Host: " + rootObject.headers.Host);
Console.WriteLine("Origin: " + rootObject.headers.Origin);
Console.WriteLine("Referer: " + rootObject.headers.Referer);
Console.WriteLine("UserAgent: " + rootObject.headers.UserAgent);
Console.WriteLine("origin: " + rootObject.origin);
Console.WriteLine("url: " + rootObject.url);
Console.WriteLine("data: " + rootObject.data);
Console.WriteLine("files: ");
foreach (KeyValuePair<string, string> kvp in rootObject.files ?? Enumerable.Empty<KeyValuePair<string, string>>())
{
Console.WriteLine("\t" + kvp.Key + ": " + kvp.Value);
}
}
}


public class Args
{
public string clientId { get; set; }
}


public class Headers
{
public string Accept { get; set; }


public string AcceptEncoding { get; set; }


public string AcceptLanguage { get; set; }


public string Authorization { get; set; }


public string Connection { get; set; }


public string Dnt { get; set; }


public string Host { get; set; }


public string Origin { get; set; }


public string Referer { get; set; }


public string UserAgent { get; set; }
}


public class RootObject
{
public Args args { get; set; }


public Headers headers { get; set; }


public string origin { get; set; }


public string url { get; set; }


public string data { get; set; }


public Dictionary<string, string> files { get; set; }
}
}

由于您使用的是Visual Studio 11 Beta,您将希望使用最新的和最好的。新的Web API包含了这方面的类。

参见HttpClient: http://wcf.codeplex.com/wikipage?title=WCF%20HTTP

我确定与此无关,但请将IDisposable对象包装在using块中,以确保正确的处理:

using System;
using System.Net;
using System.IO;


namespace ConsoleProgram
{
public class Class1
{
private const string URL = "https://sub.domain.com/objects.json?api_key=123";
private const string DATA = @"{""object"":{""name"":""Name""}}";


static void Main(string[] args)
{
Class1.CreateObject();
}


private static void CreateObject()
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
request.Method = "POST";
request.ContentType = "application/json";
request.ContentLength = DATA.Length;
using (Stream webStream = request.GetRequestStream())
using (StreamWriter requestWriter = new StreamWriter(webStream, System.Text.Encoding.ASCII))
{
requestWriter.Write(DATA);
}


try
{
WebResponse webResponse = request.GetResponse();
using (Stream webStream = webResponse.GetResponseStream() ?? Stream.Null)
using (StreamReader responseReader = new StreamReader(webStream))
{
string response = responseReader.ReadToEnd();
Console.Out.WriteLine(response);
}
}
catch (Exception e)
{
Console.Out.WriteLine("-----------------");
Console.Out.WriteLine(e.Message);
}
}
}
}

ASP。NET Web API已经取代了前面提到的WCF Web API。

我想我应该发布一个更新的答案,因为这些回答大部分来自2012年初,这个帖子是在谷歌搜索“call restful service c#”时的顶级结果之一。

目前微软的指导方针是使用微软ASP。NET Web API客户端库来使用宁静的服务。这是一个NuGet包,Microsoft.AspNet.WebApi.Client。您需要将这个NuGet包添加到您的解决方案中。

下面是使用ASP实现示例时的外观。NET Web API客户端库:

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;


namespace ConsoleProgram
{
public class DataObject
{
public string Name { get; set; }
}


public class Class1
{
private const string URL = "https://sub.domain.com/objects.json";
private string urlParameters = "?api_key=123";


static void Main(string[] args)
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(URL);


// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));


// List data response.
HttpResponseMessage response = client.GetAsync(urlParameters).Result;  // Blocking call! Program will wait here until a response is received or a timeout occurs.
if (response.IsSuccessStatusCode)
{
// Parse the response body.
var dataObjects = response.Content.ReadAsAsync<IEnumerable<DataObject>>().Result;  //Make sure to add a reference to System.Net.Http.Formatting.dll
foreach (var d in dataObjects)
{
Console.WriteLine("{0}", d.Name);
}
}
else
{
Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
}


// Make any other calls using HttpClient here.


// Dispose once all HttpClient calls are complete. This is not necessary if the containing object will be disposed of; for example in this case the HttpClient instance will be disposed automatically when the application terminates so the following call is superfluous.
client.Dispose();
}
}
}

如果您计划发出多个请求,您应该重用HttpClient实例。有关为什么using语句没有在HttpClient实例中使用的更多细节,请参阅这个问题及其答案: HttpClient和HttpClientHandler必须在请求之间被处理吗?< / >

有关更多细节,包括其他示例,请参见从。net客户端调用Web API (c#)

这篇博客文章可能也有用:使用HttpClient消费ASP. ASP. >NET Web API REST Services . NET

    var TakingRequset = WebRequest.Create("http://xxx.acv.com/MethodName/Get");
TakingRequset.Method = "POST";
TakingRequset.ContentType = "text/xml;charset=utf-8";
TakingRequset.PreAuthenticate = true;


//---Serving Request path query
var PAQ = TakingRequset.RequestUri.PathAndQuery;


//---creating your xml as per the host reqirement
string xmlroot=@"<root><childnodes>passing parameters</childnodes></root>";
string xmlroot2=@"<root><childnodes>passing parameters</childnodes></root>";


//---Adding Headers as requested by host
xmlroot2 = (xmlroot2 + "XXX---");
//---Adding Headers Value as requested by host
//  var RequestheaderVales = Method(xmlroot2);


WebProxy proxy = new WebProxy("XXXXX-----llll", 8080);
proxy.Credentials = new NetworkCredential("XXX---uuuu", "XXX----", "XXXX----");
System.Net.WebRequest.DefaultWebProxy = proxy;




// Adding The Request into Headers
TakingRequset.Headers.Add("xxx", "Any Request Variable ");
TakingRequset.Headers.Add("xxx", "Any Request Variable");


byte[] byteData = Encoding.UTF8.GetBytes(xmlroot);
TakingRequset.ContentLength = byteData.Length;


using (Stream postStream = TakingRequset.GetRequestStream())
{
postStream.Write(byteData, 0, byteData.Length);
postStream.Close();
}






StreamReader stredr = new StreamReader(TakingRequset.GetResponse().GetResponseStream());
string response = stredr.ReadToEnd();

请使用以下代码进行REST API请求:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Json;


namespace ConsoleApplication2
{
class Program
{
private const string URL = "https://XXXX/rest/api/2/component";
private const string DATA = @"{
""name"": ""Component 2"",
""description"": ""This is a JIRA component"",
""leadUserName"": ""xx"",
""assigneeType"": ""PROJECT_LEAD"",
""isAssigneeTypeValid"": false,
""project"": ""TP""}";


static void Main(string[] args)
{
AddComponent();
}


private static void AddComponent()
{
System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
client.BaseAddress = new System.Uri(URL);
byte[] cred = UTF8Encoding.UTF8.GetBytes("username:password");
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(cred));
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));


System.Net.Http.HttpContent content = new StringContent(DATA, UTF8Encoding.UTF8, "application/json");
HttpResponseMessage messge = client.PostAsync(URL, content).Result;
string description = string.Empty;
if (messge.IsSuccessStatusCode)
{
string result = messge.Content.ReadAsStringAsync().Result;
description = result;
}
}
}
}

这是可以肯定工作的示例代码。我花了一天的时间来从REST服务中读取一组对象:

RootObject是我从REST服务中读取的对象类型。

string url = @"http://restcountries.eu/rest/v1";
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(IEnumerable<RootObject>));
WebClient syncClient = new WebClient();
string content = syncClient.DownloadString(url);


using (MemoryStream memo = new MemoryStream(Encoding.Unicode.GetBytes(content)))
{
IEnumerable<RootObject> countries = (IEnumerable<RootObject>)serializer.ReadObject(memo);
}


Console.Read();

在使用。net 4.5或。net Core时调用REST API

我会建议DalSoft。RestClient(警告:我创建了它)。原因是,因为它使用动态类型,您可以在一个流畅的调用中包装所有内容,包括序列化/反序列化。下面是一个工作的示例:

dynamic client = new RestClient("http://jsonplaceholder.typicode.com");


var post = new Post { title = "foo", body = "bar", userId = 10 };


var result = await client.Posts(1).Put(post);

检查改装从。net调用REST服务。我发现它很容易使用:

Refit:自动类型安全的REST库。net Core, Xamarin和 net < / p >

Refit是一个深受Square的Retrofit库启发的库,并且 它把你的REST API变成一个活动接口:

public interface IGitHubApi {
[Get("/users/{user}")]
Task<User> GetUser(string user);
}


// The RestService class generates an implementation of IGitHubApi
// that uses HttpClient to make its calls:


var gitHubApi = RestService.For<IGitHubApi>("https://api.github.com");


var octocat = await gitHubApi.GetUser("octocat");

得到:

// GET JSON Response
public WeatherResponseModel GET(string url) {
WeatherResponseModel model = new WeatherResponseModel();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
try {
WebResponse response = request.GetResponse();
using(Stream responseStream = response.GetResponseStream()) {
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
model = JsonConvert.DeserializeObject < WeatherResponseModel > (reader.ReadToEnd());
}
} catch (WebException ex) {
WebResponse errorResponse = ex.Response;
using(Stream responseStream = errorResponse.GetResponseStream()) {
StreamReader reader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
String errorText = reader.ReadToEnd();
// Log errorText
}
throw;
}
return model;
}

职位:

// POST a JSON string
void POST(string url, string jsonContent) {
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";


System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
Byte[]byteArray = encoding.GetBytes(jsonContent);


request.ContentLength = byteArray.Length;
request.ContentType =  @ "application/json";


using(Stream dataStream = request.GetRequestStream()) {
dataStream.Write(byteArray, 0, byteArray.Length);
}


long length = 0;
try {
using(HttpWebResponse response = (HttpWebResponse)request.GetResponse()) {
// Got response
length = response.ContentLength;
}
} catch (WebException ex) {
WebResponse errorResponse = ex.Response;
using(Stream responseStream = errorResponse.GetResponseStream()) {
StreamReader reader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
String errorText = reader.ReadToEnd();
// Log errorText
}
throw;
}
}

注意:为了序列化和反序列化JSON,我使用了Newtonsoft。Json NuGet包。

第一步是为HTTP客户机创建helper类。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;


namespace callApi.Helpers
{
public class CallApi
{
private readonly Uri BaseUrlUri;
private HttpClient client = new HttpClient();


public CallApi(string baseUrl)
{
BaseUrlUri = new Uri(baseUrl);
client.BaseAddress = BaseUrlUri;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
}


public HttpClient getClient()
{
return client;
}


public HttpClient getClientWithBearer(string token)
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
return client;
}
}
}

然后可以在代码中使用这个类。

这是如何使用上面的类调用不带承载的REST API的示例。

// GET API/values
[HttpGet]
public async Task<ActionResult<string>> postNoBearerAsync(string email, string password,string baseUrl, string action)
{
var request = new LoginRequest
{
email = email,
password = password
};


var callApi = new CallApi(baseUrl);
var client = callApi.getClient();
HttpResponseMessage response = await client.PostAsJsonAsync(action, request);
if (response.IsSuccessStatusCode)
return Ok(await response.Content.ReadAsAsync<string>());
else
return NotFound();
}

这是一个如何调用需要承载的REST API的示例。

// GET API/values
[HttpGet]
public async Task<ActionResult<string>> getUseBearerAsync(string token, string baseUrl, string action)
{
var callApi = new CallApi(baseUrl);
var client = callApi.getClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
HttpResponseMessage response = await client.GetAsync(action);
if (response.IsSuccessStatusCode)
{
return Ok(await response.Content.ReadAsStringAsync());
}
else
return NotFound();
}

如果您想查看它如何工作的工作示例,还可以参考下面的存储库。

https://github.com/mokh223/callApi

我使用Web API 2.0以这种简单的方式做到了这一点。您可以删除UseDefaultCredentials。我在自己的用例中使用了它。

List<YourObject> listObjects = new List<YourObject>();


string response = "";
using (var client = new WebClient() { UseDefaultCredentials = true })
{
response = client.DownloadString(apiUrl);
}


listObjects = JsonConvert.DeserializeObject<List<YourObject>>(response);
return listObjects;

ASP。网络核心中的一个解决方案:

using Newtonsoft.Json;
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;


namespace WebApp
{
public static class HttpHelper
{
// In my case this is https://localhost:44366/
private static readonly string apiBasicUri = ConfigurationManager.AppSettings["apiBasicUri"];


public static async Task Post<T>(string url, T contentValue)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(apiBasicUri);
var content = new StringContent(JsonConvert.SerializeObject(contentValue), Encoding.UTF8, "application/json");
var result = await client.PostAsync(url, content);
result.EnsureSuccessStatusCode();
}
}


public static async Task Put<T>(string url, T stringValue)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(apiBasicUri);
var content = new StringContent(JsonConvert.SerializeObject(stringValue), Encoding.UTF8, "application/json");
var result = await client.PutAsync(url, content);
result.EnsureSuccessStatusCode();
}
}


public static async Task<T> Get<T>(string url)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(apiBasicUri);
var result = await client.GetAsync(url);
result.EnsureSuccessStatusCode();
string resultContentString = await result.Content.ReadAsStringAsync();
T resultContent = JsonConvert.DeserializeObject<T>(resultContentString);
return resultContent;
}
}


public static async Task Delete(string url)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(apiBasicUri);
var result = await client.DeleteAsync(url);
result.EnsureSuccessStatusCode();
}
}
}
}

要发布,可以使用这样的代码:

await HttpHelper.Post<Setting>($"/api/values/{id}", setting);

删除示例:

await HttpHelper.Delete($"/api/values/{id}");

获取列表的示例:

List<ClaimTerm> claimTerms = await HttpHelper.Get<List<ClaimTerm>>("/api/values/");

示例只获取一个:

ClaimTerm processedClaimImage = await HttpHelper.Get<ClaimTerm>($"/api/values/{id}");

以下是在c#中调用外部API的几种不同方式(2019年更新)。

.NET的内置方式:

免费、开源的NuGet包,坦率地说,它比.NET内置客户端拥有更好的开发体验:

  • ServiceStack。文本 (1000 GitHub星,700万NuGet下载)(*)-快速,轻和弹性。
  • RestSharp (6000 GitHub星,2300万NuGet下载)(*)-简单的REST和HTTP API客户端
  • Flurl (1700 GitHub星,300万NuGet下载)(*)-一个流畅,可移植,可测试的HTTP客户端库

上面所有的包都提供了很棒的开发体验(即简洁、简单的API),并且维护得很好。

(*)截至2019年8月

示例:使用servicstack . text从Fake Rest API获取Todo项。 其他库有非常相似的语法

class Program
{
static void Main(string[] args)
{
// Fake rest API
string url = "https://jsonplaceholder.typicode.com/todos/1";


// GET data from API & map to POCO
var todo =  url.GetJsonFromUrl().FromJson<Todo>();


// Print the result to screen
todo.PrintDump();
}


public class Todo
{
public int UserId { get; set; }
public int Id { get; set; }
public string Title { get; set; }
public bool Completed { get; set; }
}


}

在. net核心控制台应用程序中运行上述示例,产生以下输出。

Enter image description here

使用NuGet安装这些包

Install-Package ServiceStack.Text, or


Install-Package RestSharp, or


Install-Package Flurl.Http

此处标记的答案建议直接使用HttpClient并销毁它。这可能会起作用,但是如果你没有正确地使用HttpClient, 遇到问题是很容易的。

如果你打算使用HttpClient,你最好将HttpClient的创建/处理交给使用工厂模式的第三方库。RestClient。网就是这样一个库。

它带有一个非常基本的HttpClient工厂,这样你就不会碰到套接字耗尽的问题,

public class DefaultHttpClientFactory : IHttpClientFactory, IDisposable
{
#region Fields
private bool disposed;
private readonly ConcurrentDictionary<string, Lazy<HttpClient>> _httpClients;
private readonly Func<string, Lazy<HttpClient>> _createClientFunc;
#endregion


#region Constructor
public DefaultHttpClientFactory() : this(null)
{
}


public DefaultHttpClientFactory(Func<string, Lazy<HttpClient>> createClientFunc)
{
_createClientFunc = createClientFunc;
_httpClients = new ConcurrentDictionary<string, Lazy<HttpClient>>();


if (_createClientFunc != null) return;
_createClientFunc = name =>
{
return new Lazy<HttpClient>(() => new HttpClient(), LazyThreadSafetyMode.ExecutionAndPublication);
};
}
#endregion


#region Implementation
public HttpClient CreateClient(string name)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}


return _httpClients.GetOrAdd(name, _createClientFunc).Value;
}


public void Dispose()
{
if (disposed) return;
disposed = true;


foreach (var name in _httpClients.Keys)
{
_httpClients[name].Value.Dispose();
}
}
#endregion
}

但是微软的IHttpClientFactory实现也可以用于最新和最好的:

    var serviceCollection = new ServiceCollection();
var baseUri = new Uri("http://www.test.com");
serviceCollection.AddSingleton(typeof(ISerializationAdapter), typeof(NewtonsoftSerializationAdapter));
serviceCollection.AddSingleton(typeof(ILogger), typeof(ConsoleLogger));
serviceCollection.AddSingleton(typeof(IClient), typeof(Client));
serviceCollection.AddDependencyInjectionMapping();
serviceCollection.AddTransient<TestHandler>();


//Make sure the HttpClient is named the same as the Rest Client
serviceCollection.AddSingleton<IClient>(x => new Client(name: clientName, httpClientFactory: x.GetRequiredService<IHttpClientFactory>()));
serviceCollection.AddHttpClient(clientName, (c) => { c.BaseAddress = baseUri; })
.AddHttpMessageHandler<TestHandler>();


var serviceProvider = serviceCollection.BuildServiceProvider();
var client = serviceProvider.GetService<IClient>();
await client.GetAsync<object>();

RestClient。Net考虑到依赖注入、模拟、国际奥委会容器、单元可测试性,最重要的是速度快。我四处寻找,唯一的另一个客户端,似乎工作在类似的能力是flul . http。


HTTP GET请求

    string api = this.configuration["getApiUrl"];//Read from Iconfiguration object injected
public async Task<HttpResponseMessage> GetAsync(string api, ILogger log, params dynamic[] parameters)
{
log.LogInformation($"Get Token");
var token = await GetTokenAsync(this.configuration["ClientId"], this.configuration["AppKey"]).ConfigureAwait(false);
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(BearerTokenName, token);
var apiBaseUrl = this.configuration["BaseUrl"];
                   

client.BaseAddress = new Uri(apiBaseUrl);
var apiUrl = ConstructUrl(api, parameters);
var result = await client.GetAsync(apiUrl).ConfigureAwait(false);
    

if (result.StatusCode == System.Net.HttpStatusCode.OK)
{
return result;
}
else
{
throw new HttpResponseException(new HttpResponseMessage(result.StatusCode) { Content = new StringContent(result.ReasonPhrase) });
}
}
}
    

  • 从HttpResponseMessage读取字符串,如下所示
     var client = await this.httpClientService.GetAsync(url, logger, Convert.ToInt32(Id, CultureInfo.InvariantCulture)).ConfigureAwait(false);
var response = await client.Content.ReadAsStringAsync();

HTTP POST请求

     public async Task<string> PostAsync(string api, string contentValue, ILogger logger)
{
var token = await GetTokenAsync(this.configuration["ClientId"], this.configuration["AppKey"]).ConfigureAwait(false);
   

using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(BearerTokenName, token);
client.BaseAddress = new Uri(resource);
var content = new StringContent(contentValue, Encoding.UTF8, MediaTypeNames.Application.Json);
var result = await client.PostAsync(new Uri(api, UriKind.Relative), content).ConfigureAwait(false);
   

if (result.StatusCode == System.Net.HttpStatusCode.OK)
{
return await result.Content.ReadAsStringAsync();
}
else
{
throw new HttpResponseException(new HttpResponseMessage(result.StatusCode) { Content = new StringContent(result.ReasonPhrase) });
}
}
}
    var response = await this.httpClientService.PostAsync(this.configuration["getDetails"], content, this.configuration["ApiBaseUrl"], logger).ConfigureAwait(false);
catch (System.Web.Http.HttpResponseException httpException)
{
if (httpException.Response.StatusCode == HttpStatusCode.Unauthorized)
{
logger.LogError($"Failed To Update", httpException);
}
else
{
throw;
}
}
return response;

我们已经开始使用地下酒吧了。这很棒:

https://github.com/jonnii/SpeakEasy

// create a client
var client = HttpClient.Create("http://example.com/api");
    

// get some companies!
var companies = client.Get("companies").OnOk().As<List<Company>>();
  

// upload a company, with validation error support
client.Post(company, "companies")
.On(HttpStatusCode.BadRequest, (List<ValidationError> errors) => {
Console.WriteLine("Ruh Roh, you have {0} validation errors", errors.Count());
})
.On(HttpStatusCode.Created, () => Console.WriteLine("Holy moly you win!"));
    

// update a company
client.Put(company, "company/:id", new { id = "awesome-sauce" })
.OnOk(() => Console.WriteLine("Company updated"));
        

// run a search
client.Get("images/:category", new { category = "cats", breed = "omg the cutest", size = "kittens" })
.OnOk().As<List<Image>>();
    

// make an asynchronous request
var response = await client.GetAsync("companies/:id", new { id = 5 })
response.OnOk(UpdateCompaniesCallback)