From 13e6bb4d1b34312b2e9e614199d2e7373979431e Mon Sep 17 00:00:00 2001 From: Anne Thompson Date: Fri, 16 Feb 2024 11:46:51 -0800 Subject: [PATCH] ClientModel: PipelineRequest and PipelineResponse API updates (#42010) * change Core methods to Core properties * rename ReadContent->BufferContent and export APIs * nits * Make PipelineRequest.Uri nullable --- .../api/System.ClientModel.net6.0.cs | 21 ++++----- .../api/System.ClientModel.netstandard2.0.cs | 21 ++++----- .../src/Convenience/ClientResultException.cs | 4 +- .../src/Message/PipelineRequest.cs | 32 +++++-------- .../src/Message/PipelineResponse.cs | 18 +++---- .../HttpClientPipelineTransport.Request.cs | 47 +++++++++---------- .../HttpClientPipelineTransport.Response.cs | 10 ++-- .../src/Pipeline/PipelineTransport.cs | 6 +-- .../Mocks/MockPipelineRequest.cs | 37 ++++++--------- .../Mocks/MockPipelineResponse.cs | 7 +-- .../Mocks/MockPipelineTransport.cs | 40 ++++++---------- .../Mocks/ObservableTransport.cs | 46 ++++++------------ 12 files changed, 119 insertions(+), 170 deletions(-) diff --git a/sdk/core/System.ClientModel/api/System.ClientModel.net6.0.cs b/sdk/core/System.ClientModel/api/System.ClientModel.net6.0.cs index bcb221ba06f9a..11d7723bfa5fd 100644 --- a/sdk/core/System.ClientModel/api/System.ClientModel.net6.0.cs +++ b/sdk/core/System.ClientModel/api/System.ClientModel.net6.0.cs @@ -180,17 +180,14 @@ public abstract partial class PipelineRequest : System.IDisposable { protected PipelineRequest() { } public System.ClientModel.BinaryContent? Content { get { throw null; } set { } } + protected abstract System.ClientModel.BinaryContent? ContentCore { get; set; } public System.ClientModel.Primitives.PipelineRequestHeaders Headers { get { throw null; } } + protected abstract System.ClientModel.Primitives.PipelineRequestHeaders HeadersCore { get; } public string Method { get { throw null; } set { } } - public System.Uri Uri { get { throw null; } set { } } + protected abstract string MethodCore { get; set; } + public System.Uri? Uri { get { throw null; } set { } } + protected abstract System.Uri? UriCore { get; set; } public abstract void Dispose(); - protected abstract System.ClientModel.BinaryContent? GetContentCore(); - protected abstract System.ClientModel.Primitives.PipelineRequestHeaders GetHeadersCore(); - protected abstract string GetMethodCore(); - protected abstract System.Uri GetUriCore(); - protected abstract void SetContentCore(System.ClientModel.BinaryContent? content); - protected abstract void SetMethodCore(string method); - protected abstract void SetUriCore(System.Uri uri); } public abstract partial class PipelineRequestHeaders : System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { @@ -209,14 +206,14 @@ protected PipelineResponse() { } public abstract System.BinaryData Content { get; } public abstract System.IO.Stream? ContentStream { get; set; } public System.ClientModel.Primitives.PipelineResponseHeaders Headers { get { throw null; } } + protected abstract System.ClientModel.Primitives.PipelineResponseHeaders HeadersCore { get; } public virtual bool IsError { get { throw null; } } + protected internal virtual bool IsErrorCore { get { throw null; } set { } } public abstract string ReasonPhrase { get; } public abstract int Status { get; } + public abstract System.BinaryData BufferContent(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + public abstract System.Threading.Tasks.ValueTask BufferContentAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); public abstract void Dispose(); - protected abstract System.ClientModel.Primitives.PipelineResponseHeaders GetHeadersCore(); - public abstract System.BinaryData ReadContent(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); - public abstract System.Threading.Tasks.ValueTask ReadContentAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); - protected virtual void SetIsErrorCore(bool isError) { } } public abstract partial class PipelineResponseHeaders : System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { diff --git a/sdk/core/System.ClientModel/api/System.ClientModel.netstandard2.0.cs b/sdk/core/System.ClientModel/api/System.ClientModel.netstandard2.0.cs index b67631bd1efa4..631faf6d45835 100644 --- a/sdk/core/System.ClientModel/api/System.ClientModel.netstandard2.0.cs +++ b/sdk/core/System.ClientModel/api/System.ClientModel.netstandard2.0.cs @@ -179,17 +179,14 @@ public abstract partial class PipelineRequest : System.IDisposable { protected PipelineRequest() { } public System.ClientModel.BinaryContent? Content { get { throw null; } set { } } + protected abstract System.ClientModel.BinaryContent? ContentCore { get; set; } public System.ClientModel.Primitives.PipelineRequestHeaders Headers { get { throw null; } } + protected abstract System.ClientModel.Primitives.PipelineRequestHeaders HeadersCore { get; } public string Method { get { throw null; } set { } } - public System.Uri Uri { get { throw null; } set { } } + protected abstract string MethodCore { get; set; } + public System.Uri? Uri { get { throw null; } set { } } + protected abstract System.Uri? UriCore { get; set; } public abstract void Dispose(); - protected abstract System.ClientModel.BinaryContent? GetContentCore(); - protected abstract System.ClientModel.Primitives.PipelineRequestHeaders GetHeadersCore(); - protected abstract string GetMethodCore(); - protected abstract System.Uri GetUriCore(); - protected abstract void SetContentCore(System.ClientModel.BinaryContent? content); - protected abstract void SetMethodCore(string method); - protected abstract void SetUriCore(System.Uri uri); } public abstract partial class PipelineRequestHeaders : System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { @@ -208,14 +205,14 @@ protected PipelineResponse() { } public abstract System.BinaryData Content { get; } public abstract System.IO.Stream? ContentStream { get; set; } public System.ClientModel.Primitives.PipelineResponseHeaders Headers { get { throw null; } } + protected abstract System.ClientModel.Primitives.PipelineResponseHeaders HeadersCore { get; } public virtual bool IsError { get { throw null; } } + protected internal virtual bool IsErrorCore { get { throw null; } set { } } public abstract string ReasonPhrase { get; } public abstract int Status { get; } + public abstract System.BinaryData BufferContent(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + public abstract System.Threading.Tasks.ValueTask BufferContentAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); public abstract void Dispose(); - protected abstract System.ClientModel.Primitives.PipelineResponseHeaders GetHeadersCore(); - public abstract System.BinaryData ReadContent(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); - public abstract System.Threading.Tasks.ValueTask ReadContentAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); - protected virtual void SetIsErrorCore(bool isError) { } } public abstract partial class PipelineResponseHeaders : System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { diff --git a/sdk/core/System.ClientModel/src/Convenience/ClientResultException.cs b/sdk/core/System.ClientModel/src/Convenience/ClientResultException.cs index b27ba2167b378..ed518854d5434 100644 --- a/sdk/core/System.ClientModel/src/Convenience/ClientResultException.cs +++ b/sdk/core/System.ClientModel/src/Convenience/ClientResultException.cs @@ -82,11 +82,11 @@ private static async ValueTask CreateMessageSyncOrAsync(PipelineResponse { if (async) { - await response.ReadContentAsync().ConfigureAwait(false); + await response.BufferContentAsync().ConfigureAwait(false); } else { - response.ReadContent(); + response.BufferContent(); } StringBuilder messageBuilder = new(); diff --git a/sdk/core/System.ClientModel/src/Message/PipelineRequest.cs b/sdk/core/System.ClientModel/src/Message/PipelineRequest.cs index 7ff75c42c8cf8..cf05b6d832494 100644 --- a/sdk/core/System.ClientModel/src/Message/PipelineRequest.cs +++ b/sdk/core/System.ClientModel/src/Message/PipelineRequest.cs @@ -10,37 +10,31 @@ public abstract class PipelineRequest : IDisposable /// public string Method { - get => GetMethodCore(); - set => SetMethodCore(value); + get => MethodCore; + set => MethodCore = value; } - protected abstract string GetMethodCore(); + protected abstract string MethodCore { get; set; } - protected abstract void SetMethodCore(string method); - - public Uri Uri + public Uri? Uri { - get => GetUriCore(); - set => SetUriCore(value); + get => UriCore; + set => UriCore = value; } - protected abstract Uri GetUriCore(); - - protected abstract void SetUriCore(Uri uri); + protected abstract Uri? UriCore { get; set; } - public PipelineRequestHeaders Headers { get => GetHeadersCore(); } + public PipelineRequestHeaders Headers => HeadersCore; - protected abstract PipelineRequestHeaders GetHeadersCore(); + protected abstract PipelineRequestHeaders HeadersCore { get; } public BinaryContent? Content { - get => GetContentCore(); - set => SetContentCore(value); + get => ContentCore; + set => ContentCore = value; } - protected abstract BinaryContent? GetContentCore(); - - protected abstract void SetContentCore(BinaryContent? content); + protected abstract BinaryContent? ContentCore { get; set; } public abstract void Dispose(); -} \ No newline at end of file +} diff --git a/sdk/core/System.ClientModel/src/Message/PipelineResponse.cs b/sdk/core/System.ClientModel/src/Message/PipelineResponse.cs index 5e280ea5d5938..e8aa772d928fe 100644 --- a/sdk/core/System.ClientModel/src/Message/PipelineResponse.cs +++ b/sdk/core/System.ClientModel/src/Message/PipelineResponse.cs @@ -12,8 +12,6 @@ public abstract class PipelineResponse : IDisposable // TODO(matell): The .NET Framework team plans to add BinaryData.Empty in dotnet/runtime#49670, and we can use it then. internal static readonly BinaryData s_EmptyBinaryData = new(Array.Empty()); - private bool _isError = false; - /// /// Gets the HTTP status code. /// @@ -24,9 +22,9 @@ public abstract class PipelineResponse : IDisposable /// public abstract string ReasonPhrase { get; } - public PipelineResponseHeaders Headers => GetHeadersCore(); + public PipelineResponseHeaders Headers => HeadersCore; - protected abstract PipelineResponseHeaders GetHeadersCore(); + protected abstract PipelineResponseHeaders HeadersCore { get; } /// /// Gets the contents of HTTP response. Returns null for responses without content. @@ -35,22 +33,18 @@ public abstract class PipelineResponse : IDisposable public abstract BinaryData Content { get; } - public abstract BinaryData ReadContent(CancellationToken cancellationToken = default); + public abstract BinaryData BufferContent(CancellationToken cancellationToken = default); - public abstract ValueTask ReadContentAsync(CancellationToken cancellationToken = default); + public abstract ValueTask BufferContentAsync(CancellationToken cancellationToken = default); /// /// Indicates whether the status code of the returned response is considered /// an error code. /// // IsError must be virtual in order to maintain Azure.Core back-compatibility. - public virtual bool IsError => _isError; - - // We have to have a separate method for setting IsError so that the IsError - // setter doesn't become virtual when we make the getter virtual. - internal void SetIsError(bool isError) => SetIsErrorCore(isError); + public virtual bool IsError => IsErrorCore; - protected virtual void SetIsErrorCore(bool isError) => _isError = isError; + protected internal virtual bool IsErrorCore { get; set; } public abstract void Dispose(); } diff --git a/sdk/core/System.ClientModel/src/Pipeline/HttpClientPipelineTransport.Request.cs b/sdk/core/System.ClientModel/src/Pipeline/HttpClientPipelineTransport.Request.cs index 2e9669a5bfc5c..e0b5a8ea8997b 100644 --- a/sdk/core/System.ClientModel/src/Pipeline/HttpClientPipelineTransport.Request.cs +++ b/sdk/core/System.ClientModel/src/Pipeline/HttpClientPipelineTransport.Request.cs @@ -32,41 +32,35 @@ protected internal HttpPipelineRequest() _headers = new ArrayBackedRequestHeaders(); } - protected override string GetMethodCore() - => _method; - - protected override void SetMethodCore(string method) + protected override string MethodCore { - Argument.AssertNotNull(method, nameof(method)); + get => _method; + set + { + Argument.AssertNotNull(value, nameof(value)); - _method = method; + _method = value; + } } - protected override Uri GetUriCore() + protected override Uri? UriCore { - if (_uri is null) + get => _uri; + set { - throw new InvalidOperationException("Uri has not been set on this instance."); - } + Argument.AssertNotNull(value, nameof(value)); - return _uri; + _uri = value; + } } - protected override void SetUriCore(Uri uri) + protected override BinaryContent? ContentCore { - Argument.AssertNotNull(uri, nameof(uri)); - - _uri = uri; + get => _content; + set => _content = value; } - protected override BinaryContent? GetContentCore() - => _content; - - protected override void SetContentCore(BinaryContent? content) - => _content = content; - - protected override PipelineRequestHeaders GetHeadersCore() - => _headers; + protected override PipelineRequestHeaders HeadersCore => _headers; // PATCH value needed for compat with pre-net5.0 TFMs private static readonly HttpMethod _patchMethod = new HttpMethod("PATCH"); @@ -82,11 +76,16 @@ private static HttpMethod ToHttpMethod(string method) "DELETE" => HttpMethod.Delete, "PATCH" => _patchMethod, _ => new HttpMethod(method), - }; ; + }; } internal static HttpRequestMessage BuildHttpRequestMessage(PipelineRequest request, CancellationToken cancellationToken) { + if (request.Uri is null) + { + throw new InvalidOperationException("Uri must be set on message request prior to sending message."); + } + HttpMethod method = ToHttpMethod(request.Method); Uri uri = request.Uri; HttpRequestMessage httpRequest = new HttpRequestMessage(method, uri); diff --git a/sdk/core/System.ClientModel/src/Pipeline/HttpClientPipelineTransport.Response.cs b/sdk/core/System.ClientModel/src/Pipeline/HttpClientPipelineTransport.Response.cs index cfddb4a4c6fed..91a90f5264bcf 100644 --- a/sdk/core/System.ClientModel/src/Pipeline/HttpClientPipelineTransport.Response.cs +++ b/sdk/core/System.ClientModel/src/Pipeline/HttpClientPipelineTransport.Response.cs @@ -41,7 +41,7 @@ public HttpClientTransportResponse(HttpResponseMessage httpResponse) public override string ReasonPhrase => _httpResponse.ReasonPhrase ?? string.Empty; - protected override PipelineResponseHeaders GetHeadersCore() + protected override PipelineResponseHeaders HeadersCore => new HttpClientResponseHeaders(_httpResponse, _httpResponseContent); public override Stream? ContentStream @@ -80,17 +80,17 @@ public override BinaryData Content if (_contentStream is null || _contentStream is MemoryStream) { - return ReadContent(); + return BufferContent(); } throw new InvalidOperationException($"The response is not buffered."); } } - public override BinaryData ReadContent(CancellationToken cancellationToken = default) + public override BinaryData BufferContent(CancellationToken cancellationToken = default) => ReadContentSyncOrAsync(cancellationToken, async: false).EnsureCompleted(); - public override async ValueTask ReadContentAsync(CancellationToken cancellationToken = default) + public override async ValueTask BufferContentAsync(CancellationToken cancellationToken = default) => await ReadContentSyncOrAsync(cancellationToken, async: true).ConfigureAwait(false); private async ValueTask ReadContentSyncOrAsync(CancellationToken cancellationToken, bool async) @@ -160,7 +160,7 @@ protected virtual void Dispose(bool disposing) if (ContentStream is MemoryStream) { - ReadContent(); + BufferContent(); } Stream? contentStream = _contentStream; diff --git a/sdk/core/System.ClientModel/src/Pipeline/PipelineTransport.cs b/sdk/core/System.ClientModel/src/Pipeline/PipelineTransport.cs index c34fb164ee36b..c8b7529cc9a1d 100644 --- a/sdk/core/System.ClientModel/src/Pipeline/PipelineTransport.cs +++ b/sdk/core/System.ClientModel/src/Pipeline/PipelineTransport.cs @@ -90,7 +90,7 @@ private async ValueTask ProcessSyncOrAsync(PipelineMessage message, bool async) } message.AssertResponse(); - message.Response!.SetIsError(ClassifyResponse(message)); + message.Response!.IsErrorCore = ClassifyResponse(message); // The remainder of the method handles response content according to // buffering logic specified by value of message.BufferResponse. @@ -127,11 +127,11 @@ private async ValueTask ProcessSyncOrAsync(PipelineMessage message, bool async) if (async) { - await message.Response.ReadContentAsync(timeoutTokenSource.Token).ConfigureAwait(false); + await message.Response.BufferContentAsync(timeoutTokenSource.Token).ConfigureAwait(false); } else { - message.Response.ReadContent(timeoutTokenSource.Token); + message.Response.BufferContent(timeoutTokenSource.Token); } } // We dispose stream on timeout or user cancellation so catch and check if diff --git a/sdk/core/System.ClientModel/tests/TestFramework/Mocks/MockPipelineRequest.cs b/sdk/core/System.ClientModel/tests/TestFramework/Mocks/MockPipelineRequest.cs index 78fd48fbd822f..bfafc9750091e 100644 --- a/sdk/core/System.ClientModel/tests/TestFramework/Mocks/MockPipelineRequest.cs +++ b/sdk/core/System.ClientModel/tests/TestFramework/Mocks/MockPipelineRequest.cs @@ -22,33 +22,26 @@ public MockPipelineRequest() _method = "GET"; } - protected override BinaryContent? GetContentCore() - => _content; + protected override BinaryContent? ContentCore + { + get => _content; + set => _content = value; + } - protected override PipelineRequestHeaders GetHeadersCore() + protected override PipelineRequestHeaders HeadersCore => _headers; - protected override string GetMethodCore() - => _method; - - protected override Uri GetUriCore() + protected override string MethodCore { - if (_uri is null) - { - throw new InvalidOperationException("Uri has not be set on HttpMessageRequest instance."); - } - - return _uri; + get => _method; + set => _method = value; } - protected override void SetContentCore(BinaryContent? content) - => _content = content; - - protected override void SetMethodCore(string method) - => _method = method; - - protected override void SetUriCore(Uri uri) - => _uri = uri; + protected override Uri? UriCore + { + get => _uri; + set => _uri = value; + } public sealed override void Dispose() { @@ -71,4 +64,4 @@ protected void Dispose(bool disposing) _disposed = true; } } -} \ No newline at end of file +} diff --git a/sdk/core/System.ClientModel/tests/TestFramework/Mocks/MockPipelineResponse.cs b/sdk/core/System.ClientModel/tests/TestFramework/Mocks/MockPipelineResponse.cs index e4163ffc85f59..d19ab2a9caac7 100644 --- a/sdk/core/System.ClientModel/tests/TestFramework/Mocks/MockPipelineResponse.cs +++ b/sdk/core/System.ClientModel/tests/TestFramework/Mocks/MockPipelineResponse.cs @@ -78,7 +78,8 @@ public override BinaryData Content } } - protected override PipelineResponseHeaders GetHeadersCore() => _headers; + protected override PipelineResponseHeaders HeadersCore + => _headers; public sealed override void Dispose() { @@ -102,7 +103,7 @@ protected void Dispose(bool disposing) } } - public override BinaryData ReadContent(CancellationToken cancellationToken = default) + public override BinaryData BufferContent(CancellationToken cancellationToken = default) { if (_bufferedContent is not null) { @@ -126,7 +127,7 @@ public override BinaryData ReadContent(CancellationToken cancellationToken = def return _bufferedContent; } - public override async ValueTask ReadContentAsync(CancellationToken cancellationToken = default) + public override async ValueTask BufferContentAsync(CancellationToken cancellationToken = default) { if (_bufferedContent is not null) { diff --git a/sdk/core/System.ClientModel/tests/TestFramework/Mocks/MockPipelineTransport.cs b/sdk/core/System.ClientModel/tests/TestFramework/Mocks/MockPipelineTransport.cs index c811ae1304462..cfa28349067b5 100644 --- a/sdk/core/System.ClientModel/tests/TestFramework/Mocks/MockPipelineTransport.cs +++ b/sdk/core/System.ClientModel/tests/TestFramework/Mocks/MockPipelineTransport.cs @@ -119,7 +119,7 @@ public void SetResponse(int status) private class TransportRequest : PipelineRequest { - private Uri _uri; + private Uri? _uri; private readonly PipelineRequestHeaders _headers; public TransportRequest() @@ -130,34 +130,26 @@ public TransportRequest() public override void Dispose() { } - protected override BinaryContent? GetContentCore() + protected override BinaryContent? ContentCore { - throw new NotImplementedException(); + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); } - protected override PipelineRequestHeaders GetHeadersCore() + protected override PipelineRequestHeaders HeadersCore => _headers; - protected override string GetMethodCore() - { - throw new NotImplementedException(); - } - - protected override Uri GetUriCore() - => _uri; - - protected override void SetContentCore(BinaryContent? content) + protected override string MethodCore { - throw new NotImplementedException(); + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); } - protected override void SetMethodCore(string method) + protected override Uri? UriCore { - throw new NotImplementedException(); + get => _uri; + set => _uri = value; } - - protected override void SetUriCore(Uri uri) - => _uri = uri; } private class RetriableTransportResponse : PipelineResponse @@ -179,19 +171,17 @@ public override Stream? ContentStream public override BinaryData Content => throw new NotImplementedException(); - protected override PipelineResponseHeaders GetHeadersCore() - { - throw new NotImplementedException(); - } + protected override PipelineResponseHeaders HeadersCore + => throw new NotImplementedException(); public override void Dispose() { } - public override BinaryData ReadContent(CancellationToken cancellationToken = default) + public override BinaryData BufferContent(CancellationToken cancellationToken = default) { throw new NotImplementedException(); } - public override ValueTask ReadContentAsync(CancellationToken cancellationToken = default) + public override ValueTask BufferContentAsync(CancellationToken cancellationToken = default) { throw new NotImplementedException(); } diff --git a/sdk/core/System.ClientModel/tests/TestFramework/Mocks/ObservableTransport.cs b/sdk/core/System.ClientModel/tests/TestFramework/Mocks/ObservableTransport.cs index b9cc98db95d90..be6496cea9467 100644 --- a/sdk/core/System.ClientModel/tests/TestFramework/Mocks/ObservableTransport.cs +++ b/sdk/core/System.ClientModel/tests/TestFramework/Mocks/ObservableTransport.cs @@ -90,39 +90,25 @@ public override void Dispose() throw new NotImplementedException(); } - protected override BinaryContent? GetContentCore() + protected override BinaryContent? ContentCore { - throw new NotImplementedException(); - } - - protected override PipelineRequestHeaders GetHeadersCore() - { - throw new NotImplementedException(); - } - - protected override string GetMethodCore() - { - throw new NotImplementedException(); - } - - protected override Uri GetUriCore() - { - throw new NotImplementedException(); + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); } - protected override void SetContentCore(BinaryContent? content) - { - throw new NotImplementedException(); - } + protected override PipelineRequestHeaders HeadersCore + => throw new NotImplementedException(); - protected override void SetMethodCore(string method) + protected override string MethodCore { - throw new NotImplementedException(); + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); } - protected override void SetUriCore(Uri uri) + protected override Uri? UriCore { - throw new NotImplementedException(); + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); } } @@ -140,22 +126,20 @@ public override Stream? ContentStream public override BinaryData Content => throw new NotImplementedException(); - protected override PipelineResponseHeaders GetHeadersCore() - { - throw new NotImplementedException(); - } + protected override PipelineResponseHeaders HeadersCore + => throw new NotImplementedException(); public override void Dispose() { throw new NotImplementedException(); } - public override BinaryData ReadContent(CancellationToken cancellationToken = default) + public override BinaryData BufferContent(CancellationToken cancellationToken = default) { throw new NotImplementedException(); } - public override ValueTask ReadContentAsync(CancellationToken cancellationToken = default) + public override ValueTask BufferContentAsync(CancellationToken cancellationToken = default) { throw new NotImplementedException(); }