简体   繁体   English

如何使用 C# 调用 REST API?

[英]How do I make calls to a REST API using C#?

This is the code I have so far:这是我到目前为止的代码:

    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);
            }

        }
    }

The problem is that I think the exception block is being triggered (because when I remove the try-catch, I get a server error (500) message. But I don't see the Console.Out lines I put in the catch block.问题是我认为异常块正在被触发(因为当我删除 try-catch 时,我收到服务器错误 (500) 消息。但我没有看到我放在 catch 块中的 Console.Out 行。

My Console:我的控制台:

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).

The ASP.NET Web API has replaced the WCF Web API previously mentioned. ASP.NET Web API 已经取代了前面提到的WCF Web API。

I thought I'd post an updated answer since most of these responses are from early 2012, and this thread is one of the top results when doing a Google search for "call restful service C#".我想我会发布一个更新的答案,因为这些回复大多来自 2012 年初,并且这个帖子是在 Google 上搜索“call restful service C#”时的最佳结果之一。

Current guidance from Microsoft is to use the Microsoft ASP.NET Web API Client Libraries to consume a RESTful service. Microsoft 当前的指导方针是使用 Microsoft ASP.NET Web API 客户端库来使用RESTful服务。 This is available as a NuGet package, Microsoft.AspNet.WebApi.Client.它以NuGet包 Microsoft.AspNet.WebApi.Client 的形式提供。 You will need to add this NuGet package to your solution.您需要将此 NuGet 包添加到您的解决方案中。

Here's how your example would look when implemented using the ASP.NET Web API Client Library:以下是您的示例在使用 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();
        }
    }
}

If you plan on making multiple requests, you should re-use your HttpClient instance.如果您计划发出多个请求,则应重用 HttpClient 实例。 See this question and its answers for more details on why a using statement was not used on the HttpClient instance in this case: Do HttpClient and HttpClientHandler have to be disposed between requests?有关在这种情况下为何不在 HttpClient 实例上使用 using 语句的更多详细信息,请参阅此问题及其答案: Do HttpClient 和 HttpClientHandler 必须在请求之间进行处理?

For more details, including other examples, see Call a Web API From a .NET Client (C#)有关更多详细信息,包括其他示例,请参阅从 .NET 客户端调用 Web API (C#)

This blog post may also be useful: Using HttpClient to Consume ASP.NET Web API REST Services这篇博文也可能有用: Using HttpClient to Consume ASP.NET Web API REST Services

My suggestion would be to use RestSharp .我的建议是使用RestSharp You can make calls to REST services and have them cast into POCO objects with very little boilerplate code to actually have to parse through the response.您可以调用 REST 服务,并使用很少的样板代码将它们转换为POCO对象,以便实际解析响应。 This will not solve your particular error, but it answers your overall question of how to make calls to REST services.这不会解决您的特定错误,但可以回答您关于如何调用 REST 服务的总体问题。 Having to change your code to use it should pay off in the ease of use and robustness moving forward.必须更改代码才能使用它应该会在易用性和健壮性方面有所回报。 That is just my two cents though.不过那只是我的两分钱。

Example:例子:

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; }
    }
}

Unrelated, I'm sure, but do wrap your IDisposable objects in using blocks to ensure proper disposal:不相关,我敢肯定,但一定要把你的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);
            }
        }
    }
}

Here are a few different ways of calling an external API in C# (updated 2019).以下是在 C#(2019 年更新)中调用外部 API 的几种不同方式。

.NET's built-in ways: .NET 的内置方式:

  • WebRequest & WebClient - verbose APIs & Microsoft's documentation is not very easy to follow WebRequestWebClient - 详细的 API 和 Microsoft 的文档不是很容易理解
  • HttpClient - .NET's newest kid on the block & much simpler to use than above. HttpClient - .NET 块上最新的孩子 & 比上面更容易使用。

Free, open-source NuGet Packages , which frankly have a much better developer experience than .NET's built in clients:免费的开源 NuGet 包,坦率地说,它比 .NET 的内置客户端具有更好的开发人员体验:

  • ServiceStack.Text (1,000 GitHub stars, 7 million NuGet downloads) (*) - fast, light and resilient. ServiceStack.Text (1,000 个 GitHub 星,700 万次 NuGet 下载)(*) - 快速、轻便且有弹性。
  • RestSharp (6,000 GitHub stars, 23 million NuGet downloads) (*) - simple REST and HTTP API Client RestSharp (6,000 GitHub 星,2,300 万次 NuGet 下载)(*) - 简单的 REST 和 HTTP API 客户端
  • Flurl (1,700 GitHub stars, 3 million NuGet downloads) (*)- a fluent, portable, testable HTTP client library Flurl (1,700 个 GitHub 星,300 万次 NuGet 下载)(*)- 流畅、可移植、可测试的 HTTP 客户端库

All the above packages provide a great developer experience (ie, concise, easy API) and are well maintained.以上所有包都提供了很好的开发者体验(即简洁、简单的 API)并且维护得很好。

(*) as at August 2019 (*)截至 2019 年 8 月

Example: Getting a Todo item from a Fake Rest API using ServiceStack.Text.示例:使用 ServiceStack.Text 从 Fake Rest API 获取 Todo 项。 The other libraries have very similar syntax.其他库的语法非常相似。

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; }
    }

}

Running the above example in a .NET Core Console app, produces the following output.在 .NET Core 控制台应用程序中运行上述示例,会产生以下输出。

在此处输入图片说明

Install these packages using NuGet使用 NuGet 安装这些包

Install-Package ServiceStack.Text, or

Install-Package RestSharp, or

Install-Package Flurl.Http

Please use the below code for your REST API request:请为您的 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;
            }
        }
    }
}

A solution in ASP.NET Core : 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();
            }
        }
    }
}

To post, use something like this:要发布,请使用以下内容:

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

Example for delete:删除示例:

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

Example to get a list:获取列表的示例:

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

Example to get only one:仅获得一个的示例:

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

Calling a REST API when using .NET 4.5 or .NET Core使用 .NET 4.5 或 .NET Core 时调用 REST API

I would suggest DalSoft.RestClient (caveat: I created it).我建议DalSoft.RestClient (警告:我创建了它)。 The reason being, because it uses dynamic typing, you can wrap everything up in one fluent call including serialization/de-serialization.原因是,因为它使用动态类型,您可以将所有内容都包含在一个流畅的调用中,包括序列化/反序列化。 Below is a working PUT example:下面是一个有效的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);

GET:得到:

// 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:邮政:

// 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;
    }
}

Note: To serialize and desirialze JSON, I used the Newtonsoft.Json NuGet package.注意:为了序列化和反序列化 JSON,我使用了 Newtonsoft.Json NuGet 包。

Check out Refit for making calls to REST services from .NET.查看Refit以从 .NET 调用 REST 服务。 I've found it very easy to use:我发现它非常易于使用:

Refit: The automatic type-safe REST library for .NET Core, Xamarin and .NET Refit:适用于 .NET Core、Xamarin 和 .NET 的自动类型安全 REST 库

Refit is a library heavily inspired by Square's Retrofit library, and it turns your REST API into a live interface: 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");

This is example code that works for sure.这是肯定有效的示例代码。 It took me a day to make this to read a set of objects from a REST service:我花了一天时间才从 REST 服务中读取一组对象:

RootObject is the type of the object I'm reading from the REST service. 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();
    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();

I did it in this simple way, with Web API 2.0.我使用 Web API 2.0 以这种简单的方式做到了。 You can remove UseDefaultCredentials.您可以删除 UseDefaultCredentials。 I used it for my own use cases.我将它用于我自己的用例。

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;

The answer marked here suggests using HttpClient directly and the disposing of it.此处标记的答案建议直接使用 HttpClient 并对其进行处理。 This might work, but it's quite easy to run in to problems with HttpClient if you don't use it correctly.这可能有效,但如果您没有正确使用它,很容易 遇到HttpClient 的 问题

If you're going to use HttpClient, you're better off handing over the creation/disposal of HttpClients to a third-party library that uses the factory pattern .如果您打算使用 HttpClient,最好将 HttpClient 的创建/处置交给使用工厂模式的第三方库。 RestClient.Net is one such library. RestClient.Net就是这样一个库。

It comes with a very basic HttpClient factory so that you don't run in to the socket exhaustion problem,它带有一个非常基本的 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
}

But Microsoft's IHttpClientFactory implementation can also be used for the latest and greatest:但是微软的 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 takes in to account dependency injection, mocking, IoC containers, unit testability, and above all is fast. RestClient.Net 考虑了依赖注入、模拟、 IoC容器、单元可测试性,最重要的是速度很快。 I've hunted around and the only the other client that seems to work in a similar capacity is Flurl.Http.我四处寻找,似乎以类似能力工作的唯一其他客户端是 Flurl.Http。


HTTP GET Request 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) });
                    }
                }
            }
    
  • Read String from HttpResponseMessage as below从 HttpResponseMessage 中读取字符串如下
     var client = await this.httpClientService.GetAsync(url, logger, Convert.ToInt32(Id, CultureInfo.InvariantCulture)).ConfigureAwait(false);
     var response = await client.Content.ReadAsStringAsync();

HTTP POST Request 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;

We have started using speakeasy.我们已经开始使用speakeasy。 It is great:太好了:

https://github.com/jonnii/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)

Since you are using Visual Studio 11 Beta, you will want to use the latest and greatest.由于您使用的是 Visual Studio 11 Beta,您将希望使用最新最好的。 The new Web API contains classes for this.新的 Web API 包含用于此的类。

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

The first step is to create the helper class for the HTTP client.第一步是为 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;
        }
    }
}

Then you can use this class in your code.然后你可以在你的代码中使用这个类。

This is an example of how you call the REST API without bearer using the above class.这是您如何使用上述类在没有承载的情况下调用 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();
}

This is an example of how you can call the REST API that require bearer.这是一个如何调用需要承载的 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();
}

You can also refer to the below repository if you want to see the working example of how it works.如果您想查看其工作原理的工作示例,也可以参考以下存储库。

https://github.com/mokh223/callApi https://github.com/mokh223/callApi

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM