File: System\Net\Http\Json\HttpClientJsonExtensions.Get.AsyncEnumerable.cs
Web Access
Project: src\src\libraries\System.Net.Http.Json\src\System.Net.Http.Json.csproj (System.Net.Http.Json)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text.Json;
using System.Text.Json.Serialization.Metadata;
using System.Threading;
using System.Threading.Tasks;
 
namespace System.Net.Http.Json
{
    public static partial class HttpClientJsonExtensions
    {
        /// <summary>
        /// Sends an <c>HTTP GET</c> request to the specified <paramref name="requestUri"/> and returns the value that results
        /// from deserializing the response body as JSON in an async enumerable operation.
        /// </summary>
        /// <typeparam name="TValue">The target type to deserialize to.</typeparam>
        /// <param name="client">The client used to send the request.</param>
        /// <param name="requestUri">The Uri the request is sent to.</param>
        /// <param name="options"></param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
        /// <returns>An <see cref="IAsyncEnumerable{TValue}"/> that represents the deserialized response body.</returns>
        /// <exception cref="ArgumentNullException">The <paramref name="client"/> is <see langword="null"/>.</exception>
        [RequiresUnreferencedCode(HttpContentJsonExtensions.SerializationUnreferencedCodeMessage)]
        [RequiresDynamicCode(HttpContentJsonExtensions.SerializationDynamicCodeMessage)]
        public static IAsyncEnumerable<TValue?> GetFromJsonAsAsyncEnumerable<TValue>(
            this HttpClient client,
            [StringSyntax(StringSyntaxAttribute.Uri)] string? requestUri,
            JsonSerializerOptions? options,
            CancellationToken cancellationToken = default) =>
            GetFromJsonAsAsyncEnumerable<TValue>(client, CreateUri(requestUri), options, cancellationToken);
 
        /// <summary>
        /// Sends an <c>HTTP GET</c>request to the specified <paramref name="requestUri"/> and returns the value that results
        /// from deserializing the response body as JSON in an async enumerable operation.
        /// </summary>
        /// <typeparam name="TValue">The target type to deserialize to.</typeparam>
        /// <param name="client">The client used to send the request.</param>
        /// <param name="requestUri">The Uri the request is sent to.</param>
        /// <param name="options"></param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
        /// <returns>An <see cref="IAsyncEnumerable{TValue}"/> that represents the deserialized response body.</returns>
        /// <exception cref="ArgumentNullException">The <paramref name="client"/> is <see langword="null"/>.</exception>
        [RequiresUnreferencedCode(HttpContentJsonExtensions.SerializationUnreferencedCodeMessage)]
        [RequiresDynamicCode(HttpContentJsonExtensions.SerializationDynamicCodeMessage)]
        public static IAsyncEnumerable<TValue?> GetFromJsonAsAsyncEnumerable<TValue>(
            this HttpClient client,
            Uri? requestUri,
            JsonSerializerOptions? options,
            CancellationToken cancellationToken = default) =>
            FromJsonStreamAsyncCore<TValue>(client, requestUri, options, cancellationToken);
 
        /// <summary>
        /// Sends an <c>HTTP GET</c>request to the specified <paramref name="requestUri"/> and returns the value that results
        /// from deserializing the response body as JSON in an async enumerable operation.
        /// </summary>
        /// <typeparam name="TValue">The target type to deserialize to.</typeparam>
        /// <param name="client">The client used to send the request.</param>
        /// <param name="requestUri">The Uri the request is sent to.</param>
        /// <param name="jsonTypeInfo">The JsonTypeInfo used to control the behavior during deserialization.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
        /// <returns>An <see cref="IAsyncEnumerable{TValue}"/> that represents the deserialized response body.</returns>
        /// <exception cref="ArgumentNullException">The <paramref name="client"/> is <see langword="null"/>.</exception>
        public static IAsyncEnumerable<TValue?> GetFromJsonAsAsyncEnumerable<TValue>(
            this HttpClient client,
            [StringSyntax(StringSyntaxAttribute.Uri)] string? requestUri,
            JsonTypeInfo<TValue> jsonTypeInfo,
            CancellationToken cancellationToken = default) =>
            GetFromJsonAsAsyncEnumerable(client, CreateUri(requestUri), jsonTypeInfo, cancellationToken);
 
        /// <summary>
        /// Sends an <c>HTTP GET</c>request to the specified <paramref name="requestUri"/> and returns the value that results
        /// from deserializing the response body as JSON in an async enumerable operation.
        /// </summary>
        /// <typeparam name="TValue">The target type to deserialize to.</typeparam>
        /// <param name="client">The client used to send the request.</param>
        /// <param name="requestUri">The Uri the request is sent to.</param>
        /// <param name="jsonTypeInfo">The JsonTypeInfo used to control the behavior during deserialization.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
        /// <returns>An <see cref="IAsyncEnumerable{TValue}"/> that represents the deserialized response body.</returns>
        /// <exception cref="ArgumentNullException">The <paramref name="client"/> is <see langword="null"/>.</exception>
        public static IAsyncEnumerable<TValue?> GetFromJsonAsAsyncEnumerable<TValue>(
            this HttpClient client,
            Uri? requestUri,
            JsonTypeInfo<TValue> jsonTypeInfo,
            CancellationToken cancellationToken = default) =>
            FromJsonStreamAsyncCore(client, requestUri, jsonTypeInfo, cancellationToken);
 
        /// <summary>
        /// Sends an <c>HTTP GET</c>request to the specified <paramref name="requestUri"/> and returns the value that results
        /// from deserializing the response body as JSON in an async enumerable operation.
        /// </summary>
        /// <typeparam name="TValue">The target type to deserialize to.</typeparam>
        /// <param name="client">The client used to send the request.</param>
        /// <param name="requestUri">The Uri the request is sent to.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
        /// <returns>An <see cref="IAsyncEnumerable{TValue}"/> that represents the deserialized response body.</returns>
        /// <exception cref="ArgumentNullException">The <paramref name="client"/> is <see langword="null"/>.</exception>
        [RequiresUnreferencedCode(HttpContentJsonExtensions.SerializationUnreferencedCodeMessage)]
        [RequiresDynamicCode(HttpContentJsonExtensions.SerializationDynamicCodeMessage)]
        public static IAsyncEnumerable<TValue?> GetFromJsonAsAsyncEnumerable<TValue>(
            this HttpClient client,
            [StringSyntax(StringSyntaxAttribute.Uri)] string? requestUri,
            CancellationToken cancellationToken = default) =>
            GetFromJsonAsAsyncEnumerable<TValue>(client, requestUri, options: null, cancellationToken);
 
        /// <summary>
        /// Sends an <c>HTTP GET</c>request to the specified <paramref name="requestUri"/> and returns the value that results
        /// from deserializing the response body as JSON in an async enumerable operation.
        /// </summary>
        /// <typeparam name="TValue">The target type to deserialize to.</typeparam>
        /// <param name="client">The client used to send the request.</param>
        /// <param name="requestUri">The Uri the request is sent to.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
        /// <returns>An <see cref="IAsyncEnumerable{TValue}"/> that represents the deserialized response body.</returns>
        /// <exception cref="ArgumentNullException">The <paramref name="client"/> is <see langword="null"/>.</exception>
        [RequiresUnreferencedCode(HttpContentJsonExtensions.SerializationUnreferencedCodeMessage)]
        [RequiresDynamicCode(HttpContentJsonExtensions.SerializationDynamicCodeMessage)]
        public static IAsyncEnumerable<TValue?> GetFromJsonAsAsyncEnumerable<TValue>(
            this HttpClient client,
            Uri? requestUri,
            CancellationToken cancellationToken = default) =>
            GetFromJsonAsAsyncEnumerable<TValue>(client, requestUri, options: null, cancellationToken);
 
        [RequiresUnreferencedCode(HttpContentJsonExtensions.SerializationUnreferencedCodeMessage)]
        [RequiresDynamicCode(HttpContentJsonExtensions.SerializationDynamicCodeMessage)]
        private static IAsyncEnumerable<TValue?> FromJsonStreamAsyncCore<TValue>(
            HttpClient client,
            Uri? requestUri,
            JsonSerializerOptions? options,
            CancellationToken cancellationToken)
        {
            var jsonTypeInfo = (JsonTypeInfo<TValue>)JsonHelpers.GetJsonTypeInfo(typeof(TValue), options);
 
            return FromJsonStreamAsyncCore(client, requestUri, jsonTypeInfo, cancellationToken);
        }
 
        private static IAsyncEnumerable<TValue?> FromJsonStreamAsyncCore<TValue>(
            HttpClient client,
            Uri? requestUri,
            JsonTypeInfo<TValue> jsonTypeInfo,
            CancellationToken cancellationToken)
        {
            if (client is null)
            {
                throw new ArgumentNullException(nameof(client));
            }
 
            return Core(client, requestUri, jsonTypeInfo, cancellationToken);
 
            static async IAsyncEnumerable<TValue?> Core(
                HttpClient client,
                Uri? requestUri,
                JsonTypeInfo<TValue> jsonTypeInfo,
                [EnumeratorCancellation] CancellationToken cancellationToken)
            {
                using HttpResponseMessage response = await client.GetAsync(requestUri, HttpCompletionOption.ResponseHeadersRead, cancellationToken)
                    .ConfigureAwait(false);
                response.EnsureSuccessStatusCode();
 
                using Stream readStream = await GetHttpResponseStreamAsync(client, response, false, cancellationToken)
                    .ConfigureAwait(false);
 
                await foreach (TValue? value in JsonSerializer.DeserializeAsyncEnumerable<TValue>(
                    readStream, jsonTypeInfo, cancellationToken).ConfigureAwait(false))
                {
                    yield return value;
                }
            }
        }
    }
}