Як здійснити дзвінки до програми REST за допомогою C #?


335

Це код, який у мене є:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System;
using System.Net.Http;
using System.Web;
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;
            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);
            }

        }
    }
}

Проблема полягає в тому, що я думаю, що блокування винятків спрацьовує (тому що, коли я видаляю пробний улов, я отримую повідомлення про помилку сервера (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).

Я використовую Visual Studio 2011 Beta та .NET 4.5 Beta.


Крім того, ти поставив там місця перерви, щоб побачити, де саме це вибухає?
NotMe

це результат у вихідному вікні, але не консольному
Serj-Tm

5
MSDN мала чудову статтю про створення RESTful сервісів: msdn.microsoft.com/library/dd203052.aspx ... та RESTful клієнтів: msdn.microsoft.com/en-us/magazine/ee309509.aspx
Lynn

@ChrisLively, що це стосується IE? = \ Показує на request.GetResponse-рядок.
NullVoxPopuli

@TheLindyHop; Абсолютно нічого. Я неправильно прочитав.
NotMe

Відповіді:


427

Веб-API ASP.Net замінив раніше згаданий веб-API WCF.

Я думав, що опублікую оновлену відповідь, оскільки більшість цих відповідей є з початку 2012 року, і ця тема є одним із найкращих результатів, коли Google шукає "виклик спокійного обслуговування c #".

Поточне керівництво від Microsoft полягає у використанні клієнтських бібліотек Microsoft ASP.NET для користування послугою RESTful. Він доступний як пакет NuGet, Microsoft.AspNet.WebApi.Client. Вам потрібно буде додати цей пакет NuGet до свого рішення.

Ось як виглядав би ваш приклад під час реалізації за допомогою бібліотеки клієнтів веб-API ASP.Net:

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: Чи потрібно утилізувати HttpClient та HttpClientHandler?

Більш детальну інформацію, включаючи інші приклади, можна знайти тут: http://www.asp.net/web-api/overview/web-api-clients/calling-a-web-api-from-a-net-client

Цей допис у блозі також може бути корисним: http://johnnycode.com/2012/02/23/consuming-your-own-asp-net-web-api-rest-service/


6
Дякую! Мені потрібно було встановити пакет NuGet для клієнта WebApi, щоб це працювало для мене: Install-Package Microsoft.AspNet.WebApi.Client
Ev.

3
Якщо вам потрібно глузувати з інтеграції REST, навіть з клієнтськими бібліотеками це все ще непросто. Спробуйте RestSharp?
Церква Роб

6
Щоб зробити цю відповідь ще кращою, ніж вона є, вам слід загорнути декларацію HttpClient у використовувану операцію, щоб краще керувати вашим ресурсом :)
Daniel Siebert

7
Пробував використовувати, але не міг використовувати ReadAsAsync (), отримуючи помилку "HttpContent не містить визначення для" ReadAsAsync "і не має методу розширення.
Роберт Грін MBA

7
@RobertGreenMBA: Щоб отримати метод розширення ReadAsAsync(), додайте посилання на System.Net.Http.Formatting.dll. (Інтуїтивно зрозуміло, правда?)
Арін

122

Моя пропозиція буде використовувати RestSharp . Ви можете телефонувати до служб REST і вводити їх у об'єкти POCO з дуже маленьким кодовим кодом, щоб насправді потрібно було проаналізувати відповідь. Це не вирішить вашу конкретну помилку, але відповість на ваше загальне питання про те, як телефонувати до служб REST. Необхідність змінити код на його використання має окупитися простотою використання та надійністю, що рухається вперед. Це лише мої 2 копійки, хоча

Приклад:

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

6
RestSharp та JSON.NET - це безперечно шлях. Я виявив, що набір інструментів MS не вистачає і може вийти з ладу.
cbuteau

2
Ще один голос за RestSharp, тому що ви можете знущатися над його тестуванням набагато, набагато простіше, ніж бібліотеки клієнтів WebApi.
Церква Роб

1
для моно користувачів - RestSharp, здається, використовує apis System.Net WebRequest - який, на мій досвід, не настільки надійний, як реалізації .net. ('випадкові' висить)
Том

3
Було б непогано мати приклад у цій відповіді, будь ласка.
Caltor

2
Відсутність прикладу робить цю публікацію не корисною!
smac2020

39

Я не впевнений, але переконайте IDisposableоб'єкти в usingблоки, щоб забезпечити належне утилізацію:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System;
using System.Web;
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);
            }

        }
    }
}

4
Приємна відповідь, яка не використовує зайвих пакетів поза звичайним середовищем .NET.
palswim

@Jesse C. Slicer ... чому я потрапив помилку 404 у WebResponse webResponse = request.GetResponse ();
Гон Хань

2
Тому що ресурсу не знайшли? Є чимало причин отримати 404.
Джессі С.

1
Це чудове рішення @ JesseC.Slicer. Я можу застосувати цей код, щоб витягнути маркер і побачити його з консолі. Чи є у вас які-небудь поради для того, щоб я тепер взяв цей маркер для використання для автентифікації / входу? Я хочу використовувати GET для отримання даних, але можу лише якщо я ввійшов у систему. Де я міг би дізнатися більше про це? Дякую!
Пол Лагуна

18

Ось кілька різних способів виклику зовнішнього API в C # (оновлено 2019 рік).

Вбудовані способи .NET:

  • WebRequest & WebClient - багатослівні API та документація Microsoft не дуже легко дотримуватися
  • HttpClient - найновіша дитина .NET у блоці & набагато простіший у використанні, ніж вище.

Безкоштовні пакети NuGet з відкритим кодом , які, відверто кажучи, мають набагато кращий досвід для розробників, ніж вбудовані клієнтами .NET:

  • ServiceStack.Text (1 к. Зірок github, 7м завантажень Nuget) (*) - швидкий, легкий і стійкий.
  • RestSharp (6-зірковий github зірок, 23м завантаження Nuget) (*) - простий REST та HTTP API-клієнт
  • Flurl (1,7 тис. Зірок github, 3м Nuget Downloads) (*) - вільна, портативна, перевірена HTTP-клієнтська бібліотека

Всі перераховані вище пакети забезпечують чудовий досвід для розробників (тобто стислий, простий API) та чудово підтримуються.

(*) станом на серпень 2019 року

Приклад: Отримання елемента Todo з API підробленого відпочинку за допомогою ServiceStack.Text. Інші бібліотеки мають дуже схожий синтаксис.

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 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 Console, видається наступний результат.

введіть тут опис зображення

Встановіть ці пакети за допомогою NuGet

Install-Package ServiceStack.Text, or

Install-Package RestSharp, or

Install-Package Flurl.Http

17

Будь ласка, використовуйте код нижче для вашого 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. Без цього ваш код не розширюватиметься для кількох користувачів (і, так, це важливо, настільки важливо, щоб у мові було визначене ключове слово для його вирішення).
JCKödel

5
@ JCKödel - Ви не зовсім праві тут і повинні прочитати цю stackoverflow.com/a/22561368 - HttpClient був розроблений , щоб бути повторно використаний для кількох викликів
HB0

1
Так @ JCKödel, будь ласка, прочитайте цю статтю stackoverflow.com/questions/15705092/…
Натан

11

Я хотів би поділитися своїм рішенням в 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}");

2
Це дійсно приємний шматочок коду, хоча вам не слід використовувати httpclient всередині використовуючого блоку. дивіться aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
Myke Black

9

Оновлення для виклику API REST при використанні .NET 4.5 або .NET Core

Я б запропонував 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);

5

Отримати:

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

Примітка: Для серіалізації та дезіріалізації JSON я використав пакет Newtonsoft.Json NuGet.


4

Перевірте Refit для здійснення дзвінків до послуг відпочинку з .net. Я вважаю це дуже простим у використанні: https://github.com/paulcbetts/refit

Перегляньте: автоматична безпечна для бібліотеки тип REST для .NET Core, Xamarin та .NET

Refit - це бібліотека, натхненна бібліотекою модернізації Square, і вона перетворює ваш 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

Вибачте @tfrascaroli Я не впевнений.
patrickbadley

2

Це приклад коду, який працює точно. На це мені знадобився день, щоб прочитати набір об’єктів від сервісу відпочинку:

RootObject - це тип об'єкта, який я читаю з сервісу відпочинку.

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

1
    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();

1

Я зробив це простим способом, за допомогою веб-версії 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 ;


0

Відповідь, позначена тут, пропонує безпосередньо використовувати HttpClient та розпоряджатися ним. Це може спрацювати, але досить просто натрапити на проблеми з HttpClient, якщо ви не використовуєте його правильно. Якщо ви збираєтеся використовувати HttpClient, вам краще передавати створення / видалення HttpClients сторонній бібліотеці, яка використовує заводський зразок. 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 від Microsoft також може бути використана для останнього та найкращого:

    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


-2

Першим кроком є ​​створення класу helper для 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;
        }

    }
}

Тоді ви можете використовувати цей клас у своєму коді.

це приклад того, як ви називаєте решту 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();
}

це приклад того, як ви можете назвати решту апі, які потребують носія.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.