如何使用 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 - 如何使用错误代码扩展模型状态错误

如何在 C# 中使用 rest api 从 github 为用户(人)获取数据?

如何在 C# 中实现 YouTrack REST API

如何在 C# 的 REST API 中获取 PDF 文件