如何使用 C# 调用 REST API?
Posted
技术标签:
【中文标题】如何使用 C# 调用 REST API?【英文标题】:How do I make calls to a REST API using C#? 【发布时间】:2012-03-26 02:10:26 【问题描述】:这是我目前的代码:
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)消息。但我没有看到我放入的 Console.Out 行捕获块。
我的控制台:
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).
【问题讨论】:
另外,您是否在其中设置了断点以查看它到底在哪里爆炸? 这是输出窗口的结果,而不是控制台的结果 MSDN 有一篇关于构建 RESTful 服务的优秀文章:msdn.microsoft.com/library/dd203052.aspx ... 和 RESTful 客户端:msdn.microsoft.com/en-us/magazine/ee309509.aspx 【参考方案1】:ASP.NET Web API 已经取代了前面提到的WCF Web API。
我想我会发布一个更新的答案,因为这些回复中的大多数来自 2012 年初,并且这个帖子是在 Google 搜索“call restful service C#”时的最佳结果之一。
Microsoft 当前的指导是使用 Microsoft ASP.NET Web API 客户端库来使用 RESTful 服务。这可作为 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 实例。有关在这种情况下为什么没有在 HttpClient 实例上使用 using 语句的更多详细信息,请参阅此问题及其答案:Do HttpClient and HttpClientHandler have to be disposed between requests?
如需了解更多详情,包括其他示例,请参阅Call a Web API From a .NET Client (C#)
这篇博文也可能有用:Using HttpClient to Consume ASP.NET Web API REST Services
【讨论】:
谢谢!我需要安装 WebApi 客户端 NuGet 包才能为我工作:Install-Package Microsoft.AspNet.WebApi.Client 如果您需要模拟您的 REST 集成,即使使用客户端库,这仍然不容易。试试 RestSharp? 为了使这个答案比现在更好,您应该将 HttpClient 声明包装到 using 语句中以更好地管理您的资源:) 尝试使用但无法使用 ReadAsAsync(),出现错误“HttpContent 不包含 'ReadAsAsync' 的定义并且没有扩展方法。 @RobertGreenMBA:要获取扩展方法ReadAsAsync()
,请添加对System.Net.Http.Formatting.dll
的引用。 (直觉,对吧?)【参考方案2】:
我的建议是使用RestSharp。您可以调用 REST 服务并将它们转换为 POCO 对象,只需很少的样板代码实际上必须解析响应。这不会解决您的特定错误,但它会回答您关于如何调用 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;
【讨论】:
RestSharp 和 JSON.NET 绝对是要走的路。我发现缺少 MS 工具集并且可能会失败。 对 RestSharp 再投一票,因为您可以模拟它进行测试,比 WebApi 客户端库更容易。 对于单声道用户 - RestSharp 似乎正在使用 System.Net WebRequest api - 根据我的经验,它不如 .net 实现可靠。 (“随机”挂起) 请在这个答案中有一个例子。 缺少示例使这篇文章没有帮助!【参考方案3】:我敢肯定,这无关紧要,但请务必将您的 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);
【讨论】:
不错的答案,它不使用常规 .NET 环境之外的任何额外包。 @Jesse C. Slicer..为什么我在 WebResponse webResponse = request.GetResponse() 中遇到错误 404; 因为找不到资源?获得 404 的原因有很多。 这是一个很好的解决方案@JesseC.Slicer。我可以应用此代码来提取令牌并从控制台查看它。您有什么提示可以让我现在将此令牌用于身份验证/登录吗?我想使用 GET 来提取一些数据,但只有在我登录后才能使用。我在哪里可以了解更多信息?谢谢! 使用系统两次 :)【参考方案4】:以下是在 C# 中调用外部 API 的几种不同方式(2019 年更新)。
.NET 的内置方式:
WebRequest& WebClient - 冗长的 API 和微软的文档不太容易理解 HttpClient - .NET 的最新成员,使用起来比上面的简单得多。免费的开源 NuGet 包,坦率地说,它比 .NET 的内置客户端具有更好的开发者体验:
ServiceStack.Text(1,000 个 GitHub 星,700 万次 NuGet 下载)(*) - 快速、轻便且有弹性。 RestSharp(6000 个 GitHub 星,2300 万次 NuGet 下载)(*) - 简单的 REST 和 HTTP API 客户端 Flurl(1,700 个 GitHub 星,300 万次 NuGet 下载)(*)- 一个流畅、可移植、可测试的 HTTP 客户端库以上所有软件包都提供了出色的开发人员体验(即简洁、简单的 API)并且维护良好。
(*) 截至 2019 年 8 月
示例:使用 ServiceStack.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 Core 控制台应用程序中运行上述示例,会产生以下输出。
使用 NuGet 安装这些包
Install-Package ServiceStack.Text, or
Install-Package RestSharp, or
Install-Package Flurl.Http
【讨论】:
请记住,ServiceStack 不是免费开源的!免费版使用受限 - 详情请点击此处:servicestack.net/download#free-quotas @Tomasz - ServiceStack.Text 和上面显示的 HttpUtils 是免费的、开源的github.com/ServiceStack/ServiceStack.Text。 是的,你没看错,其中的ServiceStack.Text部分是FOSS,谢谢指正。 使用 IHttpClientFactory 和 GetFromJsonAsync ?【参考方案5】:请为您的 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;
【讨论】:
-1:.net 是一个托管平台,但 HttpClient 是非托管的(这意味着您必须使用 using 来告诉它何时可以处理这些非托管指针)。没有它,您的代码将无法扩展到几个用户(是的,这很重要,非常重要,以至于语言有一个特定的关键字来处理它)。 @JCKödel - 你不是绝对正确,应该阅读这个***.com/a/22561368 - HttpClient 被设计为可重复用于多次调用 是的@JCKödel 请阅读这篇文章***.com/questions/15705092/… 我认为@JCKödel 绝对正确!在上面发布的代码中,HttpClient 被一遍又一遍地实例化,这是不正确。请注意以下几点:“HttpClient 旨在被实例化一次并在应用程序的整个生命周期中重复使用。为每个请求实例化一个 HttpClient 类将耗尽重负载下可用的套接字数量。这将导致 SocketException错误。下面是正确使用 HttpClient 的示例。"来自Microsoft Docs【参考方案6】:ASP.NET Core中的一个解决方案:
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");
【讨论】:
这是一段非常棒的代码,虽然你不应该在 using 块中使用 httpclient。见aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong 你最好使用这个代码块而不是“result.EnsureSuccessStatusCode();” if (result.IsSuccessStatusCode) // 处理成功 else // 处理失败 【参考方案7】:使用 .NET 4.5 或 .NET Core 时调用 REST API
我建议DalSoft.RestClient(注意:我创建了它)。原因是,因为它使用动态类型,您可以将所有内容封装在一个流畅的调用中,包括序列化/反序列化。下面是一个有效的PUT 示例:
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);
【讨论】:
【参考方案8】:获取:
// 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 包。
【讨论】:
【参考方案9】:查看Refit 以从 .NET 调用 REST 服务。我发现它非常易于使用:
Refit:适用于 .NET Core、Xamarin 和 .NET
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");
【讨论】:
你知道Refit是否使用反射来实现这一点吗?我在任何地方都找不到信息。 对不起@tfrascaroli,我不确定。【参考方案10】:这是肯定有效的示例代码。我花了一天的时间从 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();
【讨论】:
【参考方案11】:我使用 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;
【讨论】:
【参考方案12】: 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();
【讨论】:
【参考方案13】:此处标记的答案建议直接使用 HttpClient 并将其处理掉。这可能有效,但如果使用不当,很容易使用 HttpClient run in to problems。
如果您要使用 HttpClient,最好将 HttpClients 的创建/处置交给使用 factory pattern 的第三方库。 RestClient.Net 就是这样一个库。
它带有一个非常基本的 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 考虑了依赖注入、模拟、IoC 容器、单元可测试性,最重要的是速度很快。我四处寻找,似乎以类似能力工作的唯一另一个客户端是 Flurl.Http。
【讨论】:
【参考方案14】:我们已经开始使用speakeasy。太好了:
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)
【讨论】:
【参考方案15】:由于您使用的是 Visual Studio 11 Beta,因此您将希望使用最新最好的。新的 Web API 包含用于此的类。
见HttpClient:http://wcf.codeplex.com/wikipage?title=WCF%20HTTP
【讨论】:
链接(实际上)已损坏。它重定向到https://archive.codeplex.com/?p=wcf
。【参考方案16】:
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;
【讨论】:
【参考方案17】:第一步是为 HTTP 客户端创建帮助类。
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
【讨论】:
你说的“无承载”是什么意思(在“...调用无承载的REST API”?以上是关于如何使用 C# 调用 REST API?的主要内容,如果未能解决你的问题,请参考以下文章
使用 C# 从 Unity 中的 REST Api 无延迟或抖动地检索数据
如何在 c# 中使用 rest api 进行 paypal 卡存在(刷卡)付款?
C# REST API - 如何使用错误代码扩展模型状态错误