L
L
LebedevStr2020-11-15 04:54:04
C++ / C#
LebedevStr, 2020-11-15 04:54:04

How to Loop Based on Web Request Response in C#?

The code:

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


How to wrap in a loop, execute until we get a response of 200? That is, valid.
Thank you.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
I
Igor Tkhorik, 2020-11-15
@LebedevStr

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

And that doesn't work for you?

B
Boris the Animal, 2020-11-15
@Casper-SC

This example is good because you can very quickly create at least 10 more different methods for accessing the server API. Part of the code was taken from Microsoft help, partially modified (where XML comments are in English).
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>

The entry point to the application and the main algorithm for receiving data in a loop.
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";
            }
        }
    }
}

This class is just used as an example of how to convert JSON received from the server into an instance of the
User.cs class
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 to give you an idea of ​​what's going on.
Screenshot taken from video: https://youtu.be/lh8cT6qI-nA?t=1123
5fb13cbe569ab013358287.jpeg

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question