Задать вопрос
@LebedevStr

Как сделать цикл на основе ответа на Web запрос в C#?

Код:

get_url       = request_uri + s;
req           = (HttpWebRequest) WebRequest.Create(get_url);
resp          = (HttpWebResponse) req.GetResponse();
sr            = new StreamReader(resp.GetResponseStream(), Encoding.GetEncoding("utf-8"));
content       = sr.ReadToEnd();
sr.Close();


Как обернуть в цикл, выполнять пока не получим ответ 200? Тоесть, валидный.
Спасибо.
  • Вопрос задан
  • 232 просмотра
Подписаться 1 Простой 11 комментариев
Решения вопроса 1
habcerga1
@habcerga1
class WebWorker
    {
        public async Task<string> GetWhileNotOk(string request_uri)
        {
            var get_url = request_uri;
            HttpWebResponse resp = new HttpWebResponse();
            var req           = (HttpWebRequest) WebRequest.Create(get_url);
            resp = (HttpWebResponse) await req.GetResponseAsync();
            if (resp.StatusCode != HttpStatusCode.OK)
            {
                this.GetWhileNotOk(request_uri);
            }
            var sr            = new StreamReader(resp.GetResponseStream(), Encoding.GetEncoding("utf-8"));
            var content       = sr.ReadToEndAsync();
            sr.Close();
            return content.Result;
        }
    }


А вот так вам не подойдет?
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
Casper-SC
@Casper-SC
Программист (.NET)
Данный пример хорош тем, что ты можешь очень быстро создать ещё хоть 10 разных методов для обращения к API сервера. Часть кода была взята со справки майкрософта, частично модифицирована (где XML комментарии на английском).

HttpClientExample.csproj
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
  </ItemGroup>

</Project>


Точка входа в приложение и основной алгоритм по получению данных в цикле.
Program.cs
using System;
using System.Threading;
using System.Threading.Tasks;

namespace HttpClientExample
{
    class Program
    {
        // В качестве исключения я расположил в самом верху класса метод Main, 
        // обычно здесь должны быть поля класса, а все методы ниже.
        #region Entry point

        static async Task Main(string[] args)
        {
            var program = new Program();
            await program.Run(args);
        }

        #endregion

        private readonly SomeClient _client;

        public Program()
        {
            _client = new SomeClient("http://localhost:5000");
        }

        private async Task Run(string[] args)
        {
            bool success = false;
            do
            {
                try
                {
                    // CancellationToken пригодится в приложениях с UI, где нужно, например, 
                    // закрыть окно или уйти со страницы не дожидаясь, пока запрос отработает. 
                    // Здесь заранее это заложено, можно и не использовать, если приложение консольное.
                    string data = await _client.GetData(CancellationToken.None);
                    success = true;

                    Console.WriteLine(data);
                }
                catch (ApiException ex)
                {
                    // Одна реакция
                    Console.WriteLine(ex);
                    Console.WriteLine();
                }
                catch (Exception ex)
                {
                    // Другая реакция
                    Console.WriteLine(ex);
                    Console.WriteLine();
                }

                await Task.Delay(150);
            } while (!success);

            _client.Dispose();
        }
    }
}


SomeClient.cs
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace HttpClientExample
{
    public class SomeClient : IDisposable
    {
        private const string GET_TEXT_PART = "/api/system/get-text";
        private const string GET_USER_PART = "/api/system/get-user";

        private HttpClient _httpClient;

        public Dictionary<string, string> DefaultHeaders { get; }

        public SomeClient(string baseAddress)
        {
            var httpHandler = new HttpClientHandler
            {
                AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip
            };

            _httpClient = new HttpClient(httpHandler)
            {
                BaseAddress = new Uri(baseAddress)
            };

            DefaultHeaders = new Dictionary<string, string>
            {
                ["Accept"] = "*/*",
                ["Accept-Encoding"] = "gzip, deflate",
                ["Cache-Control"] = "no-cache",
                ["Connection"] = "keep-alive",
            };
        }

        public void Dispose()
        {
            if (_httpClient != null)
            {
                _httpClient.Dispose();
                _httpClient = null;
                GC.SuppressFinalize(this);
            }
        }

        public async Task<string> GetData(CancellationToken cancellationToken)
        {
            string text = await InvokeText(HttpMethod.Get, GET_TEXT_PART, cancellationToken);
            // Возможно, что-то залогировал.
            return text;
        }

        public async Task<User> GetUser(CancellationToken cancellationToken)
        {
            var user = await InvokeJson<User>(HttpMethod.Get, GET_USER_PART, cancellationToken);
            // Возможно, что-то залогировал.
            return user;
        }

        /// <summary>
        /// Sets the request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="requestContent">Content of the request.</param>
        private void SetRequest(HttpRequestMessage request, object requestContent)
        {
            foreach (var header in DefaultHeaders)
            {
                request.Headers.Add(header.Key, header.Value);
            }

            if (requestContent != null)
            {
                request.Content = new StringContent(JsonConvert.SerializeObject(requestContent),
                    Encoding.UTF8,
                    Constants.HttpMimeTypes.JsonContentType);
            }
        }

        /// <summary>
        /// Invokes the specified HTTP method.
        /// </summary>
        /// <param name="httpMethod">The HTTP method.</param>
        /// <param name="relativeUrl">The relative URL.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        /// <param name="requestContent">Content of the request.</param>
        /// <returns>instance of the type T</returns>
        /// <exception cref="ApiException"></exception>
        private async Task<string> InvokeText(HttpMethod httpMethod, string relativeUrl, CancellationToken cancellationToken, object requestContent = null)
        {
            using (var request = new HttpRequestMessage(httpMethod, relativeUrl))
            {
                SetRequest(request, requestContent);

                using (HttpResponseMessage response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead, cancellationToken))
                {
                    string responseText = await response.Content.ReadAsStringAsync();
                    if (response.IsSuccessStatusCode)
                    {
                        return responseText;
                    }

                    throw new ApiException(response.StatusCode, responseText);
                }
            }
        }

        /// <summary>
        /// Invokes the specified HTTP method.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="httpMethod">The HTTP method.</param>
        /// <param name="relativeUrl">The relative URL.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        /// <param name="requestContent">Content of the request.</param>
        /// <returns>instance of the type T</returns>
        /// <exception cref="ApiException"></exception>
        private async Task<T> InvokeJson<T>(HttpMethod httpMethod, string relativeUrl, CancellationToken cancellationToken, object requestContent = null)
        {
            using (var request = new HttpRequestMessage(httpMethod, relativeUrl))
            {
                SetRequest(request, requestContent);

                using (HttpResponseMessage response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead, cancellationToken))
                {
                    string responseText = await response.Content.ReadAsStringAsync();
                    if (response.IsSuccessStatusCode)
                    {
                        var resource = JsonConvert.DeserializeObject<T>(responseText);
                        return resource;
                    }

                    throw new ApiException(response.StatusCode, responseText);
                }
            }
        }

        private static class Constants
        {
            public static class HttpMimeTypes
            {
                /// <summary>
                /// The json content type
                /// </summary>
                public const string JsonContentType = "application/json";
            }
        }
    }
}


Этот класс используется просто для примера, как преобразовать JSON, полученный от сервера в экземпляр класса
User.cs
using Newtonsoft.Json;

namespace HttpClientExample
{
    public class User
    {
        [JsonProperty("id", Required = Required.Always)]
        public long Id { get; set; }

        [JsonProperty("name", Required = Required.Always)]
        public string Name { get; set; }
    }
}


async await, чтобы было примепрное понимание, что происходит.
Скриншот сделан с видео: https://youtu.be/lh8cT6qI-nA?t=1123
5fb13cbe569ab013358287.jpeg
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы