Skip to content

Add back typed part#158

Open
twogood wants to merge 3 commits into
mainfrom
add-back-typed-part
Open

Add back typed part#158
twogood wants to merge 3 commits into
mainfrom
add-back-typed-part

Conversation

@twogood

@twogood twogood commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • Tests
    • Added coverage for HTTP client factory integrations with delegating handlers.
    • Verified successful movie and review retrieval, review submission, and typed error responses.
    • Added validation for safely handling request and response content.
    • Confirmed that reusing disposed HTTP content produces the expected error.
  • Chores
    • Added required HTTP client support for the test suite.

@twogood twogood self-assigned this Jul 23, 2026
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9fef282f-ee2f-4c9d-a932-f9f4ccd53ad6

📥 Commits

Reviewing files that changed from the base of the PR and between f1c699f and 5c51cc9.

📒 Files selected for processing (1)
  • Activout.RestClient.Newtonsoft.Json.Test/Activout.RestClient.Newtonsoft.Json.Test.csproj
🚧 Files skipped from review as they are similar to previous changes (1)
  • Activout.RestClient.Newtonsoft.Json.Test/Activout.RestClient.Newtonsoft.Json.Test.csproj

Walkthrough

The test project adds HTTP client factory support, a mock handler pipeline, a buffering logging delegating handler, and five integration tests covering movie and review requests, reused content disposal, POST submission, and typed 404 errors.

Changes

Delegating handler integration

Layer / File(s) Summary
HTTP pipeline setup
Activout.RestClient.Newtonsoft.Json.Test/Activout.RestClient.Newtonsoft.Json.Test.csproj, Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.cs, Activout.RestClient.Newtonsoft.Json.Test/MockHttpMessageHandlerBuilder.cs
The test project references Microsoft.Extensions.Http; mock handler builders, dependency injection, MovieReviewServiceFactory, and LoggingDelegatingHandler compose the HTTP client pipeline.
Delegated request and error behavior
Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.cs, Activout.RestClient.Newtonsoft.Json.Test/DomainExceptions/MyApiError.cs
Tests cover movie and review GETs, reused-content disposal, review POSTs, and typed 404 error details using the new Unexpected enum member.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Test as HttpClientFactoryWithDelegatingHandlerTest
  participant Factory as MovieReviewServiceFactory
  participant Logging as LoggingDelegatingHandler
  participant Mock as MockHttpMessageHandler
  Test->>Factory: Create IMovieReviewService
  Factory->>Logging: Send movie review request
  Logging->>Mock: Forward buffered request
  Mock-->>Logging: Return HTTP response
  Logging-->>Factory: Return buffered response
  Factory-->>Test: Deserialize service result
Loading

Poem

I’m a rabbit with handlers in line,
Buffering each byte till the tests all shine.
GET, POST, errors hop through the queue,
Mocked little messages come back true.
“Unexpected” now has a place to land—
Thump, thump, shipped by paw and hand!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is vague and does not clearly describe the added HTTP client factory tests, mock handler builder, or typed error handling changes. Use a more specific title that names the main change, such as adding HttpClient delegating-handler tests or restoring typed error handling.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch add-back-typed-part

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Checkov (3.3.8)
Activout.RestClient.Newtonsoft.Json.Test/Activout.RestClient.Newtonsoft.Json.Test.csproj

Traceback (most recent call last):
File "/usr/local/bin/checkov", line 2, in
from checkov.main import Checkov
ModuleNotFoundError: No module named 'checkov'


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@twogood
twogood requested a review from Copilot July 23, 2026 09:59

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (4)
Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.cs (4)

164-164: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove action-label comments.

The Arrange/Act/Assert labels restate the test structure rather than documenting a non-obvious rationale. As per coding guidelines, only include comments that explain why something is done, not what is done.

Also applies to: 177-180, 189-189, 204-204, 213-213, 231-231, 244-244, 253-256, 265-265, 281-281

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.cs`
at line 164, Remove the Arrange, Act, and Assert action-label comments from the
affected tests in HttpClientFactoryWithDelegatingHandlerTest, including the
labels at the referenced sections. Leave test setup, execution, assertions, and
any comments explaining non-obvious rationale unchanged.

Source: Coding guidelines


88-96: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use expression-bodied members for the single-return methods.

  • Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.cs#L88: convert CreateMovieReviewService to public IMovieReviewService CreateMovieReviewService() => ...;
  • Activout.RestClient.Newtonsoft.Json.Test/MockHttpMessageHandlerBuilder.cs#L29: convert Build to an expression-bodied member if it still has the same single return form.

Follow the file-guideline preference for expression-bodied members on simple single-return methods.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.cs`
around lines 88 - 96, Convert CreateMovieReviewService in
Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.cs
(lines 88-96) to an expression-bodied member while preserving its existing
builder chain. Also convert Build in
Activout.RestClient.Newtonsoft.Json.Test/MockHttpMessageHandlerBuilder.cs (lines
29-32) to an expression-bodied member if it still consists of a single return
statement.

Source: Coding guidelines


165-169: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use collection expressions consistently.

  • Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.cs#L165-L169, #L190-L194, and #L214-L218: declare the movie/review collections with target-typed arrays using [...].
  • Activout.RestClient.Newtonsoft.Json.Test/MockHttpMessageHandlerBuilder.cs#L27: initialize AdditionalHandlers with = [];.

This follows the required [] collection syntax while relying on collection expressions for arrays and IList<DelegatingHandler>.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.cs`
around lines 165 - 169, Replace the explicit movie/review array initializers at
Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.cs
lines 165-169, 190-194, and 214-218 with target-typed collection expressions
using [...]. Also initialize AdditionalHandlers at
Activout.RestClient.Newtonsoft.Json.Test/MockHttpMessageHandlerBuilder.cs line
27 with = [];.

Source: Coding guidelines


32-35: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use primary constructors for DI-only types.

Targeting net8.0 with <LangVersion>default</LangVersion> enables primary constructors for non-record classes, so collapse these dependency-only constructors:

  • Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.cs#L32-L35
  • Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.cs#L41-L44
  • Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.cs#L78-L86
  • Activout.RestClient.Newtonsoft.Json.Test/MockHttpMessageHandlerBuilder.cs#L13-L16
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.cs`
around lines 32 - 35, Replace the dependency-only constructors with primary
constructors, preserving each existing injected parameter and its
assignment/use. Apply this to HttpClientFactoryWithDelegatingHandlerTest.cs at
lines 32-35, 41-44, and 78-86, and MockHttpMessageHandlerBuilder.cs at lines
13-16; ensure the affected test types and MockHttpMessageHandlerBuilder retain
the same dependencies and behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@Activout.RestClient.Newtonsoft.Json.Test/Activout.RestClient.Newtonsoft.Json.Test.csproj`:
- Line 15: Update the test project’s TargetFramework to net9.0 and change its
Microsoft.Extensions.Http PackageReference to the matching 9.0.x version. Apply
the same .NET 9 target framework and dependency baseline to the related .csproj
configuration files, preserving their existing project settings.

In
`@Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.cs`:
- Around line 108-135: Dispose every root service provider created by
CreateServiceProvider and CreateMovieReviewServiceWithConfiguredPrimaryHandler,
including providers used through CreateMovieReviewService. Update the helpers or
their callers so each BuildServiceProvider result is disposed after the test
completes, while preserving the existing client creation and test behavior.

In `@Activout.RestClient.Newtonsoft.Json.Test/MockHttpMessageHandlerBuilder.cs`:
- Around line 21-25: Update the PrimaryHandler property in
MockHttpMessageHandlerBuilder to use a mutable backing handler initialized to
_mockHttp. Make the setter assign the provided handler to that backing field,
and have the getter return it so ConfigurePrimaryHttpMessageHandler settings are
preserved.

In `@Activout.RestClient.Test/MultipartFormDataContentTest.cs`:
- Around line 117-137: Update the test around SendTypedParts to use a collection
expression instead of new[] for the Part<string> arguments, and remove the
Arrange, Act, and Assert phase-label comments while leaving the test behavior
unchanged.

In `@Activout.RestClient/Part.cs`:
- Around line 8-18: Update the generic Part<T> record to use an explicit
constructor instead of declaring Content as a positional parameter. Initialize
the base Part with Content, Name, and FileName, and retain the strongly typed
Content property without hiding a generated positional member.

---

Nitpick comments:
In
`@Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.cs`:
- Line 164: Remove the Arrange, Act, and Assert action-label comments from the
affected tests in HttpClientFactoryWithDelegatingHandlerTest, including the
labels at the referenced sections. Leave test setup, execution, assertions, and
any comments explaining non-obvious rationale unchanged.
- Around line 88-96: Convert CreateMovieReviewService in
Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.cs
(lines 88-96) to an expression-bodied member while preserving its existing
builder chain. Also convert Build in
Activout.RestClient.Newtonsoft.Json.Test/MockHttpMessageHandlerBuilder.cs (lines
29-32) to an expression-bodied member if it still consists of a single return
statement.
- Around line 165-169: Replace the explicit movie/review array initializers at
Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.cs
lines 165-169, 190-194, and 214-218 with target-typed collection expressions
using [...]. Also initialize AdditionalHandlers at
Activout.RestClient.Newtonsoft.Json.Test/MockHttpMessageHandlerBuilder.cs line
27 with = [];.
- Around line 32-35: Replace the dependency-only constructors with primary
constructors, preserving each existing injected parameter and its
assignment/use. Apply this to HttpClientFactoryWithDelegatingHandlerTest.cs at
lines 32-35, 41-44, and 78-86, and MockHttpMessageHandlerBuilder.cs at lines
13-16; ensure the affected test types and MockHttpMessageHandlerBuilder retain
the same dependencies and behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: de1f4d1c-9f2e-4161-b03a-a1c924b0a774

📥 Commits

Reviewing files that changed from the base of the PR and between 85e06b1 and f1c699f.

📒 Files selected for processing (6)
  • Activout.RestClient.Newtonsoft.Json.Test/Activout.RestClient.Newtonsoft.Json.Test.csproj
  • Activout.RestClient.Newtonsoft.Json.Test/DomainExceptions/MyApiError.cs
  • Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.cs
  • Activout.RestClient.Newtonsoft.Json.Test/MockHttpMessageHandlerBuilder.cs
  • Activout.RestClient.Test/MultipartFormDataContentTest.cs
  • Activout.RestClient/Part.cs


<ItemGroup>
<PackageReference Include="MartinCostello.Logging.XUnit" Version="0.6.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.1" />

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

fd -HI -t f \
  -g 'global.json' \
  -g 'Directory.Build.props' \
  -g 'Directory.Build.targets' \
  -g '*.csproj' . -0 |
  xargs -0 -r rg -n -C2 'TargetFrameworks?|LangVersion|Microsoft\.Extensions\.Http'

Repository: twogood/Activout.RestClient

Length of output: 358


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf 'Relevant project/config files:\n'
git ls-files | rg '(^|/)(global\.json|Directory\.Build\.props|Directory\.Build\.targets|.*\.csproj)$' || true

printf '\nMicrosoft.Extensions.Http references:\n'
git ls-files | rg '(^|/)(.*\.csproj|global\.json|Directory\.Build\.props|Directory\.Build\.targets)$' | xargs -r rg -n 'Microsoft\.Extensions\.Http|TargetFrameworks?|LangVersion|Sdk="' || true

printf '\nTarget framework config occurrences:\n'
git ls-files | rg '(^|/)(global\.json|Directory\.Build\.props|Directory\.Build\.targets|.*\.csproj)$' | while read -r f; do
  printf '\n-- %s --\n' "$f"
  rg -n 'TargetFramework|TargetFrameworks|LangVersion|Sdk="|PackageReference' "$f" || true
done

Repository: twogood/Activout.RestClient

Length of output: 7567


Align the SDK configuration to the .NET 9 baseline.

Activout.RestClient.Newtonsoft.Json.Test.csproj and this package reference are currently on the .NET 8 baseline. Migrate <TargetFramework> to net9.0, update Microsoft.Extensions.Http to 9.0.x, and apply the same configuration baseline to the related .NET/.csproj configuration files.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Activout.RestClient.Newtonsoft.Json.Test/Activout.RestClient.Newtonsoft.Json.Test.csproj`
at line 15, Update the test project’s TargetFramework to net9.0 and change its
Microsoft.Extensions.Http PackageReference to the matching 9.0.x version. Apply
the same .NET 9 target framework and dependency baseline to the related .csproj
configuration files, preserving their existing project settings.

Source: Coding guidelines

Comment on lines +108 to +135
private IServiceProvider CreateServiceProvider()
{
var services = new ServiceCollection();
services.AddTransient<HttpMessageHandlerBuilder>(_ => new MockHttpMessageHandlerBuilder(_mockHttp));

AddRestClient(services);

services.AddLogging(builder =>
{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("Activout.RestClient", LogLevel.Debug)
.AddXUnit(_outputHelper);
});

services.AddHttpClient<MovieReviewServiceFactory>()
.AddHttpMessageHandler(() => new LoggingDelegatingHandler(_outputHelper));

return services.BuildServiceProvider();
}

private IMovieReviewService CreateMovieReviewService()
{
var serviceProvider = CreateServiceProvider();
var factory = serviceProvider.GetRequiredService<MovieReviewServiceFactory>();
return factory.CreateMovieReviewService();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

rg -n -C3 'BuildServiceProvider\(|CreateServiceProvider\(|IDisposable|Dispose\(' \
  Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.cs

Repository: twogood/Activout.RestClient

Length of output: 1350


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

# Inspect the test class structure and the relevant helper implementations.
sed -n '1,180p' Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.rs

Repository: twogood/Activout.RestClient

Length of output: 295


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

sed -n '1,220p' 'Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.cs'

Repository: twogood/Activout.RestClient

Length of output: 7762


Dispose the root service providers.

CreateServiceProvider() and CreateMovieReviewServiceWithConfiguredPrimaryHandler() both call BuildServiceProvider() but neither the returned client nor the tests dispose the provider. Use using/await using and dispose the provider from each test or make the helper return it to the caller.

Also applies to: 137-159

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.cs`
around lines 108 - 135, Dispose every root service provider created by
CreateServiceProvider and CreateMovieReviewServiceWithConfiguredPrimaryHandler,
including providers used through CreateMovieReviewService. Update the helpers or
their callers so each BuildServiceProvider result is disposed after the test
completes, while preserving the existing client creation and test behavior.

Source: Coding guidelines

Comment on lines +21 to +25
public override HttpMessageHandler PrimaryHandler
{
get => _mockHttp;
set { }
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

For Microsoft.Extensions.Http 9.x, does IHttpClientBuilder.ConfigurePrimaryHttpMessageHandler assign HttpMessageHandlerBuilder.PrimaryHandler while constructing the handler pipeline?

💡 Result:

No, IHttpClientBuilder.ConfigurePrimaryHttpMessageHandler does not inherently assign the value to HttpMessageHandlerBuilder.PrimaryHandler while constructing the handler pipeline. Instead, ConfigurePrimaryHttpMessageHandler works by adding configuration actions to the HttpClientFactoryOptions [1]. When a client is created, the HttpClientFactory infrastructure runs these actions to configure the HttpMessageHandlerBuilder instance [2][1]. Specifically, there are different overloads of ConfigurePrimaryHttpMessageHandler that behave differently: 1. Overloads that accept a delegate to create/replace the handler (e.g., Func<IServiceProvider, HttpMessageHandler>) directly modify or replace the primary handler [3][1]. 2. The overload that accepts an Action<HttpMessageHandler, IServiceProvider> allows you to configure the existing primary handler [3][1]. In this specific case, the action is added to the builder's configuration actions, and when it executes, it receives the current PrimaryHandler instance as an argument, allowing you to modify it [1]. The assignment to the PrimaryHandler property on the builder typically happens as part of the internal pipeline construction process where the builder's state is finalized before the pipeline is built via CreateHandlerPipeline [4][5]. Therefore, the extension method adds the logic to perform the configuration, but it does not perform a direct assignment at the moment the extension method is called [1].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Files matching MockHttpMessageHandlerBuilder.cs:"
fd -a 'MockHttpMessageHandlerBuilder\.cs$' . || true

file="$(fd 'MockHttpMessageHandlerBuilder\.cs$' . | head -n 1 || true)"
if [ -n "${file:-}" ]; then
  echo
  echo "Line count:"
  wc -l "$file"
  echo
  echo "Outline:"
  ast-grep outline "$file" || true
  echo
  echo "Contents:"
  cat -n "$file"
fi

echo
echo "Search for MockHttpMessageHandlerBuilder registrations/usages:"
rg -n "MockHttpMessageHandlerBuilder|PrimaryHandler|ConfigurePrimaryHttpMessageHandler|AddTestClient|AddClient" . -g '*.cs' || true

Repository: twogood/Activout.RestClient

Length of output: 3219


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Relevant test locations:"
cat -n Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.cs | sed -n '80,185p'

echo
echo "Find HttpMessageHandlerBuilder/HttpClientFactoryOptions/Builder references in library/test:"
rg -n "HttpMessageHandlerBuilder|HttpClientFactoryOptions|BuildPrimaryMessageHandler|CreateHandlerPipeline|ConfigurePrimaryHttpMessageHandler|AddTestClient" . -g '*.cs' -g '*.csproj' || true

Repository: twogood/Activout.RestClient

Length of output: 5487


🌐 Web query:

OpenTelemetry Instrumentation.Http HttpMessageListener PrimaryHandler setter HttpMessageHandlerBuilder PrimaryHandler

💡 Result:

In the context of.NET and OpenTelemetry instrumentation, the terms you mentioned relate to how HTTP requests are handled, traced, and configured using the Microsoft Extensions HTTP infrastructure. HttpMessageHandlerBuilder.PrimaryHandler The PrimaryHandler is a property of the HttpMessageHandlerBuilder class [1][2]. It represents the base HttpMessageHandler responsible for actually sending the HTTP request over the network [3]. In an HttpClient pipeline, it sits at the bottom of the handler chain [3]. When using IHttpClientFactory, you can configure this handler using the ConfigurePrimaryHttpMessageHandler extension method [4][5]. OpenTelemetry Instrumentation and HttpMessageListener OpenTelemetry does not typically require you to manually interact with a "PrimaryHandler" setter for instrumentation purposes [6][7]. Instead, OpenTelemetry's.NET instrumentation for HttpClient (found in the OpenTelemetry.Instrumentation.Http library) works primarily by: 1. Subscribing to DiagnosticSource events (like System.Net.Http.HttpRequestOut.Start) [8]. 2. Using HttpClientTraceInstrumentationOptions to allow users to filter or enrich telemetry (e.g., via EnrichWithHttpRequestMessage) [9][7]. Relationship There is no direct "OpenTelemetry Instrumentation HttpMessageListener PrimaryHandler setter." If you need to add custom logic to your HTTP requests (such as logging, custom headers, or specific transport settings) while maintaining OpenTelemetry instrumentation, you should: - Use ConfigurePrimaryHttpMessageHandler to set your custom SocketsHttpHandler or HttpClientHandler [4]. - Use AddHttpMessageHandler to add custom DelegatingHandler instances to the pipeline [10]. OpenTelemetry will continue to collect telemetry because it instruments the HttpClient/HttpMessageHandler infrastructure at a lower level via DiagnosticSource [8][6]. When configuring the PrimaryHandler, note that in modern.NET versions, the default primary handler is SocketsHttpHandler [5]. If you override it, ensure your code remains compatible with the required handler types to avoid runtime errors (e.g., InvalidCastException if you expect an HttpClientHandler but receive a SocketsHttpHandler) [5].

Citations:


🌐 Web query:

HttpMessageHandlerBuilder PrimaryHandler assign value delegate ConfigurePrimaryHttpMessageHandler SetPrimaryHandlerAction

💡 Result:

In the context of ASP.NET Core and IHttpClientFactory, these components are part of the infrastructure used to configure the primary message handler of an HttpClient [1][2]. HttpMessageHandlerBuilder is a class responsible for constructing the HttpMessageHandler pipeline [3]. It contains a PrimaryHandler property, which is an abstract HttpMessageHandler that can be get or set [4]. When you use the IHttpClientBuilder extensions, the infrastructure internally manipulates this builder [5][6]. ConfigurePrimaryHttpMessageHandler is an extension method available on IHttpClientBuilder [7][8]. It allows you to provide a delegate that defines how the primary HttpMessageHandler should be created or configured [1][2]. Under the hood, when you call ConfigurePrimaryHttpMessageHandler, the framework registers an action with HttpClientFactoryOptions [5][6]. This action is added to the HttpMessageHandlerBuilderActions collection [5][6]. Specifically, these actions are configured to assign a value to the PrimaryHandler property of the HttpMessageHandlerBuilder instance during the pipeline construction process [5][6]. There is no public API explicitly named SetPrimaryHandlerAction; this appears to be a misinterpretation of the internal mechanism where delegates (actions) are added to the HttpMessageHandlerBuilderActions list to perform the assignment of the PrimaryHandler property [5][6]. To configure the primary handler, you should use the provided extension methods on IHttpClientBuilder, such as [1][2]: services.AddHttpClient("my-client").ConfigurePrimaryHttpMessageHandler( => new HttpClientHandler { UseCookies = false }); The framework handles the underlying delegation to the HttpMessageHandlerBuilder automatically [5][6]. Direct interaction with HttpMessageHandlerBuilder.PrimaryHandler is typically reserved for advanced scenarios where you might be implementing a custom builder, though using the standard IHttpClientBuilder extensions is the recommended approach [3][9].

Citations:


🌐 Web query:

github dotnet runtime HttpMessageHandlerBuilder BuildPrimaryMessageHandler PrimaryHandler =

💡 Result:

In.NET, HttpMessageHandlerBuilder.PrimaryHandler is an abstract property of the HttpMessageHandlerBuilder class that represents the primary HttpMessageHandler used by an HttpClient [1][2]. The primary handler is the innermost handler in an HttpClient's pipeline, responsible for actually performing the HTTP transport operations [3]. When using the IHttpClientFactory infrastructure, this handler acts as the final destination for an outbound request after it has passed through all configured additional handlers [2][3]. Key details regarding PrimaryHandler: 1. Functionality: It is the foundation of the handler chain. The HttpMessageHandlerBuilder.CreateHandlerPipeline method constructs the full pipeline by chaining additional handlers onto this primary handler [2][3]. 2. Configuration: You can configure the primary handler for a named HttpClient using the ConfigurePrimaryHttpMessageHandler extension method on IHttpClientBuilder [4][5]. 3. Default Behavior: If not explicitly configured, the default primary handler implementation varies by platform. In modern.NET versions, it is typically a SocketsHttpHandler, whereas on platforms like.NET Framework, it defaults to HttpClientHandler [5]. 4. Usage Note: There is no method named BuildPrimaryMessageHandler. The builder uses the PrimaryHandler property directly when constructing the handler pipeline [1][2]. Users should avoid reusing or caching instances of handlers provided to the builder, as the internal infrastructure expects them to be used in a specific lifecycle [1][6][3]. Top results: [1] https://github.com/dotnet/runtime/blob/main/src/libraries/Microsoft.Extensions.Http/src/HttpMessageHandlerBuilder.cs [2] https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.http.httpmessagehandlerbuilder [3] https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.http.httpmessagehandlerbuilder.createhandlerpipeline [5] https://learn.microsoft.com/en-us/dotnet/core/compatibility/networking/9.0/default-handler

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

dotnet --version 2>/dev/null || true
dotnet --info 2>/dev/null | sed -n '1,40p' || true

echo
echo "Project SDK/framework references:"
cat -n Activout.RestClient.Newtonsoft.Json.Test/Activout.RestClient.Newtonsoft.Json.Test.csproj | sed -n '1,120p'

echo
echo "Find Microsoft.Extensions.Http package versions in project files:"
rg -n "Microsoft\.Extensions\.Http|<TargetFrameworks>|<TargetFramework>" -g '*.csproj' -g '*.props' -g '*.targets' . || true

echo
echo "Inspect installed/reference metadata from project assets if present:"
fd 'project.assets.json' . -x sh -c 'echo "--- $1"; cat "$1" | jq ".targets//empty" 2>/dev/null | jq -r --arg file "$1" "File:\($file)\n" | head -n 80' sh {}

Repository: twogood/Activout.RestClient

Length of output: 3094


🌐 Web query:

github dotnet runtime HttpClientBuilderExtensions SetPrimaryHandlerAction PrimaryHandler

💡 Result:

In the.NET Microsoft.Extensions.Http library, HttpClientBuilderExtensions provides several methods for configuring the primary message handler for a named HttpClient. While there is no public method named "SetPrimaryHandlerAction" in the standard API, the functionality to define a custom primary handler is achieved through ConfigurePrimaryHttpMessageHandler methods [1][2]. The underlying architecture uses the HttpMessageHandlerBuilder class, which exposes a PrimaryHandler property [3]. This property is the definitive location where the primary HttpMessageHandler is stored during the construction process [3][4]. Key technical points regarding PrimaryHandler and its configuration: 1. PrimaryHandler Property: The HttpMessageHandlerBuilder.PrimaryHandler property (type HttpMessageHandler) is used to get or set the primary handler that the HttpClient will use as its base handler [3]. 2. Configuration via Extensions: Instead of directly manipulating PrimaryHandler, developers use ConfigurePrimaryHttpMessageHandler extension methods on IHttpClientBuilder [1][5]. These methods accept delegates that allow you to instantiate or configure the HttpMessageHandler [2][4]. For example: services.AddHttpClient("myClient").ConfigurePrimaryHttpMessageHandler( => new HttpClientHandler { AllowAutoRedirect = false }); [6] 3. Implementation Detail: Internally, within HttpClientBuilderExtensions.cs, these extension methods register actions in the HttpMessageHandlerBuilder's internal collection of actions. When the handler is built, these actions are invoked to assign the handler to the PrimaryHandler property [7][4]. If you are looking for specific ways to interact with the primary handler, you should use the ConfigurePrimaryHttpMessageHandler overloads, which provide hooks to configure the handler via IServiceProvider or directly [2][5].

Citations:


🌐 Web query:

dotnet/runtime 8.0 HttpMessageHandlerBuilder BuildPrimaryMessageHandler PrimaryHandler = builder.Actions

💡 Result:

In.NET 8, there is no method named BuildPrimaryMessageHandler within the HttpMessageHandlerBuilder class [1][2][3]. The HttpMessageHandlerBuilder abstraction uses the Build method to construct the HttpMessageHandler pipeline [2][4]. The configuration of the PrimaryHandler and AdditionalHandlers is managed through the options pattern in the Microsoft.Extensions.Http library [5][6]. Specifically, when you use extension methods like ConfigurePrimaryHttpMessageHandler, the configuration actions are stored in the HttpMessageHandlerBuilderActions collection (which is part of the HttpClient factory options) [5][6]. When an HttpClient is created, these actions are executed against an instance of the HttpMessageHandlerBuilder, setting its PrimaryHandler and AdditionalHandlers properties [5][2]. The pipeline itself is constructed using the protected static method CreateHandlerPipeline, which chains the PrimaryHandler and AdditionalHandlers together [7][2][3]. The logic mentioned in your query—where PrimaryHandler is set via builder actions—is consistent with how the IHttpClientFactory infrastructure populates the builder before calling Build [5][6].

Citations:


🌐 Web query:

dotnet/runtime 8.0 DependencyInjection HttpClientBuilderExtensions SetPrimaryHandlerAction PrimaryHandler = builder.PrimaryHandler

💡 Result:

In.NET 8, the PrimaryHandler is a property of the HttpMessageHandlerBuilder class [1], which is used by the HttpClientFactory infrastructure to construct the HttpMessageHandler pipeline [1]. While you can interact with the PrimaryHandler during the construction of an HttpClient, you do not typically set it by assigning a property named PrimaryHandler directly on a builder extension. Instead, you use the extension methods provided by the HttpClientBuilderExtensions class to configure it [2][3]. Key points regarding the PrimaryHandler and HttpClientBuilderExtensions in.NET 8: 1. HttpMessageHandlerBuilder.PrimaryHandler: This is an abstract property defined in the HttpMessageHandlerBuilder class [1]. It represents the primary HttpMessageHandler that sits at the base of the handler chain [1]. 2. Configuring the Primary Handler: You configure this handler via IHttpClientBuilder extension methods. The most common methods are: - ConfigurePrimaryHttpMessageHandler(Func): Allows you to provide a delegate that returns a new primary handler instance [4][3]. - ConfigurePrimaryHttpMessageHandler(Action<HttpMessageHandler, IServiceProvider>): Allows you to configure an existing primary handler [5][6]. - UseSocketsHttpHandler(Action<SocketsHttpHandler, IServiceProvider>): A specialized extension for configuring a SocketsHttpHandler as the primary handler [4][3]. 3. Internal Implementation: Internally, these extension methods register configuration actions with the HttpClientFactory [7]. When the HttpClientFactory builds the handler, it populates an HttpMessageHandlerBuilder instance [1], and the actions you registered are invoked to set or modify the PrimaryHandler property on that builder [7][1]. If you are looking at code similar to builder.PrimaryHandler =..., it is likely occurring inside a internal callback or a custom implementation of an extension method that has access to the HttpMessageHandlerBuilder instance being used during the pipeline construction process [7][8][1]. For standard application code, you should rely on the public API methods like ConfigurePrimaryHttpMessageHandler to define your primary handler [5][9].

Citations:


🌐 Web query:

github dotnet/runtime v8.0.0 HttpMessageHandlerBuilder.cs private HttpMessageHandler _primaryHandler PrimaryHandler = builder._primaryHandler

💡 Result:

The class HttpMessageHandlerBuilder in the.NET runtime (including version 8.0.0) is an abstract class [1][2]. It defines the PrimaryHandler property as an abstract property, meaning it does not contain a private field named _primaryHandler or any concrete implementation of that property within the class itself [1][3]. The definition in HttpMessageHandlerBuilder.cs is: public abstract HttpMessageHandler PrimaryHandler { get; set; } As an abstract class, it provides the blueprint for building an HttpMessageHandler pipeline, but the actual state management (such as the backing field for the primary handler) is handled by concrete implementations provided by the infrastructure, not the base class itself [1][4]. The IHttpClientFactory infrastructure uses this builder to chain additional handlers with the primary handler at the end of the pipeline [4].

Citations:


🌐 Web query:

github dotnet/runtime v8.0.0 HttpMessageHandlerBuilder.cs protected constructor PrimaryHandler = default

💡 Result:

In the.NET 8.0.0 implementation of HttpMessageHandlerBuilder.cs, there is no protected constructor that assigns PrimaryHandler = default. The HttpMessageHandlerBuilder class is defined as an abstract class [1]. In C#, an abstract class does not require an explicit constructor to be defined; if none is provided, the compiler generates a default public parameterless constructor. Specifically, in the v8.0.0 source code for HttpMessageHandlerBuilder [1]: - The class is defined as public abstract class HttpMessageHandlerBuilder [1]. - The PrimaryHandler property is declared as an abstract property: public abstract HttpMessageHandler PrimaryHandler { get; set; } [1]. Because PrimaryHandler is abstract, it cannot be assigned a default value within the base class constructor. Any implementation of the builder must provide its own concrete implementation of the PrimaryHandler property [1]. The infrastructure (such as DefaultHttpClientFactory) manages the configuration and instantiation of the builder, ensuring that the necessary properties are set appropriately before the handler pipeline is built [2].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for nuget in "$HOME/.nuget/packages/microsoft.extensions.http/8.0.1" "$(dirname "$(dirname "$(dirname "$(pwd)")")")/.nuget/packages/microsoft.extensions.http/8.0.1"; do
  [ -d "$nuget" ] && { echo "FOUND $nuget"; find "$nuget" -maxdepth 3 -type f -printf '%p\n' | sort; }
done

pkg="$(find "$HOME/.nuget/packages/microsoft.extensions.http" -type f -path '*/8.0.1/**/*.dll' -o -path '*/8.0.1/**/*.pdb' 2>/dev/null | head -n 20)"
echo "PKG DLL/PDB candidates:"
echo "$pkg" | head -n 40

if command -v ildasm >/dev/null 2>&1; then
  dll="$(find "$HOME/.nuget/packages/microsoft.extensions.http" -type f -path '*8.0.1/*.dll' | head -n 1 || true)"
  if [ -n "${dll:-}" ]; then
    echo
    echo "ILDASM HttpMessageHandlerBuilder properties/methods:"
    ildasm "$dll" 2>/dev/null | \
      sed -n '/\.class Microsoft\.Extensions\.Http\.HttpMessageHandlerBuilder/,/^\.method/p' | head -n 200 || true
    echo
    echo "ILDASM HttpClientBuilderExtensions configure/set methods:"
    ildasm "$dll" 2>/dev/null | rg -n "SetPrimaryHandler|ConfigurePrimaryHttpMessageHandler|PrimaryHandler" -C 4 || true
  fi
fi

if command -v dotnet >/dev/null 2>&1; then
  temp="$(mktemp -d)"
  proj="$temp/proj.csproj"
  cat >/tmp/Probe.cs <<'CS'
using System;
using System.Linq;
using System.Reflection;
using Microsoft.Extensions.Http;

public static class Probe
{
  public static void Main()
  {
    try
    {
      var ext = typeof(Microsoft.Extensions.DependencyInjection.HttpClientBuilderExtensions);
      foreach (var name in new[] { "SetPrimaryHandlerAction", "SetPrimaryHandlerActionInternal", "UseSocketsHttpHandlerInternal" })
      {
        foreach (var m in ext.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance))
        {
          if (m.Name.Contains("PrimaryHandler") || m.Name.Contains("SocketsHttpHandler"))
            Console.WriteLine(m.Name + " | " + string.Join(", ", m.GetParameters().Select(p => string.Join(" ", p.ParameterType.Name, p.Name))));
        }
      }
      foreach (var m in ext.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance))
      {
        if (!m.Name.Contains("Primary") && !m.Name.Contains("Action") && !m.Name.Contains("Handler") && !m.Name.Contains("Logging")) continue;
        Console.WriteLine(m.Name + " | " + string.Join(", ", m.GetParameters().Select(p => p.ParameterType.Name + " " + p.Name)));
      }
    }
    catch (Exception ex)
    {
      Console.WriteLine(ex.GetType() + ": " + ex.Message);
    }
  }
}
CS
  cat >"$proj" <<'EP'
<Project Sdk="Microsoft.NET.Sdk">
 <PropertyGroup>
  <OutputType>Exe</OutputType>
  <TargetFramework>net8.0</TargetFramework>
 </PropertyGroup>
 <ItemGroup>
  <PackageReference Include="Microsoft.Extensions.Http" Version="8.0.1" />
 </ItemGroup>
 <ItemGroup>
  <Compile Include="/tmp/Probe.cs" />
 </ItemGroup>
</Project>
EP
  dotnet run --project "$proj" 2>&1 | sed -n '1,160p'
fi

# Read relevant source from available NuGet package if DLLs absent but XML/docs present.
for xml in $HOME/.nuget/packages/microsoft.extensions.http/8.0.1/lib/net8.0/*.xml; do
  [ -e "$xml" ] || continue
  rg -n -C 6 "PrimaryHandler|ConfigurePrimaryHttpMessageHandler|SetPrimaryHandlerAction|UseSocketsHttpHandler" "$xml" || true
done

Repository: twogood/Activout.RestClient

Length of output: 165


🌐 Web query:

dotnet/release-notes v8.0.0 Microsoft.Extensions.Http PrimaryHandler setter HttpMessageHandlerBuilder DefaultHttpMessageHandlerBuilder

💡 Result:

In.NET 8, the Microsoft.Extensions.Http library maintains the HttpMessageHandlerBuilder.PrimaryHandler property as a read-write property [1][2]. This property is defined in the abstract HttpMessageHandlerBuilder class [1] and implemented by the DefaultHttpMessageHandlerBuilder [3]. The PrimaryHandler property allows you to get or set the primary HttpMessageHandler used by an HttpClient [1][4]. While it is a settable property, it is intended to be managed by the IHttpClientFactory infrastructure [1][2]. Explicitly setting this property outside of standard configuration scenarios (like testing or custom factory implementations) can lead to unpredictable behavior [1][2]. It is important to note that while.NET 8 introduced significant networking improvements [5], the shift in the default primary handler from HttpClientHandler to SocketsHttpHandler (which affects how you might configure or cast the handler) was a behavioral change introduced in.NET 9 [6][7]. In.NET 8, the default primary handler remained HttpClientHandler [6][7]. To configure the primary handler in a supported, fluent manner, it is recommended to use the ConfigurePrimaryHttpMessageHandler extension method on the IHttpClientBuilder [8][9]. Avoid relying on the "factory-default" implementation of the primary handler, as this is an internal detail that can change between versions [6][9]. If you need to modify an existing handler, use the overload of ConfigurePrimaryHttpMessageHandler that accepts an Action<HttpMessageHandler, IServiceProvider>, which allows you to inspect and configure the handler safely [5][6][7].

Citations:


🌐 Web query:

"SetPrimaryHandlerAction" "PrimaryHandler" "HttpMessageHandlerBuilder"

💡 Result:

There is no specific method or property named SetPrimaryHandlerAction in the Microsoft.Extensions.Http namespace or the HttpMessageHandlerBuilder class [1][2][3]. It is highly likely you are referring to the configuration approach used with HttpClientFactoryOptions, where actions are added to the HttpMessageHandlerBuilderActions collection [4][5][6]. In modern.NET development, the recommended way to configure the primary handler is through extension methods on IHttpClientBuilder rather than manually manipulating the HttpMessageHandlerBuilder [7][8][9]. Key points regarding HttpMessageHandlerBuilder: 1. PrimaryHandler Property: The HttpMessageHandlerBuilder class contains a PrimaryHandler property of type HttpMessageHandler, which gets or sets the primary handler (the innermost handler responsible for transport) [1][2][3]. 2. Configuration via Options: You can configure this by adding an action to the HttpMessageHandlerBuilderActions collection within HttpClientFactoryOptions [4][5]. This is often done using service configuration, though it is considered a lower-level, more manual approach [4][5]. 3. Recommended Approaches: Instead of manually accessing HttpMessageHandlerBuilder, use the following extension methods provided by Microsoft.Extensions.DependencyInjection [7][8]: - ConfigurePrimaryHttpMessageHandler: Use this to explicitly configure the primary handler (e.g., to set SSL options, proxy settings, or cookies) [7][8][9]. - ConfigureAdditionalHttpMessageHandlers: Use this to add DelegatingHandlers to the pipeline [7]. 4. Deprecation: Methods that explicitly required an Action (such as the method ConfigureHttpMessageHandlerBuilder) have been marked as obsolete, and developers are encouraged to use the more specific ConfigurePrimaryHttpMessageHandler or ConfigureAdditionalHttpMessageHandlers methods instead [10][6]. If you were looking for a way to set the handler, you should prefer: services.AddHttpClient("MyClient").ConfigurePrimaryHttpMessageHandler( => new SocketsHttpHandler {... }); [8]

Citations:


🌐 Web query:

github.com/dotnet/runtime v8.0.0 HttpClientBuilderExtensions.cs SetPrimaryHandlerAction PrimaryHandler = builder.PrimaryHandler

💡 Result:

In the.NET runtime (specifically within Microsoft.Extensions.Http), the ConfigurePrimaryHttpMessageHandler extension methods in HttpClientBuilderExtensions.cs configure the primary message handler by adding an action to the HttpClientFactoryOptions.HttpMessageHandlerBuilderActions collection [1][2]. When this action is executed, it sets the PrimaryHandler property on the HttpMessageHandlerBuilder instance [1][3]. The code pattern commonly used is: options.HttpMessageHandlerBuilderActions.Add(b => b.PrimaryHandler = configureHandler); [1] Or, when using a delegate that accepts IServiceProvider: options.HttpMessageHandlerBuilderActions.Add(b => b.PrimaryHandler = configureHandler(b.Services)); [1][2] The HttpMessageHandlerBuilder.PrimaryHandler property is an abstract property that allows the handler to be assigned during the construction of the HttpMessageHandler pipeline [3][4]. The builder variable in the lambda expression (b) refers to the HttpMessageHandlerBuilder instance currently building the pipeline, not a variable named builder.PrimaryHandler as implied by the query's phrasing [1][3].

Citations:


🌐 Web query:

github.com/dotnet/runtime v8.0.0 HttpClientBuilderExtensions.cs ConfigurePrimaryHttpMessageHandler AddPrimaryHttpMessageHandlerAction PrimaryHandler

💡 Result:

In the.NET runtime repository, specifically within the Microsoft.Extensions.Http library, HttpClientBuilderExtensions.cs provides extension methods for configuring HttpClient instances via IHttpClientBuilder [1][2]. Regarding the specific components you mentioned: 1. ConfigurePrimaryHttpMessageHandler: This is a set of extension methods on IHttpClientBuilder that allows you to specify the primary HttpMessageHandler used by an HttpClient [1][3][4]. The primary handler is the innermost handler in the message handler pipeline, responsible for actually sending the request on the wire [5][6][7]. 2. AddPrimaryHttpMessageHandlerAction: This does not exist as a public API or a single named method in HttpClientBuilderExtensions. Instead, the configuration of the primary handler is achieved by adding actions to the HttpMessageHandlerBuilderActions collection within the internal configuration options of the IHttpClientBuilder [3][8]. When you call ConfigurePrimaryHttpMessageHandler, it registers a delegate that executes when the HttpMessageHandlerBuilder is built, which in turn sets the PrimaryHandler property on the builder [3][6]. 3. PrimaryHandler: This refers to the PrimaryHandler property of the HttpMessageHandlerBuilder class [6]. The IHttpClientFactory infrastructure uses this property to determine which handler acts as the base for the HTTP pipeline [5][7]. When you use ConfigurePrimaryHttpMessageHandler, you are effectively providing a factory function or a configuration delegate that the builder uses to set this PrimaryHandler [3]. In.NET 8.0 and later, the default primary handler is typically SocketsHttpHandler [5]. If you need to customize settings (like UseCookies or ClientCertificates), you can use ConfigurePrimaryHttpMessageHandler to either instantiate a new handler or configure the existing one [5]. Top results: [1][3][5][6]

Citations:


Do not discard configured primary handlers.

ConfigurePrimaryHttpMessageHandler(...) assigns the configured handler to HttpMessageHandlerBuilder.PrimaryHandler; the empty setter makes that assignment a no-op. Store a mutable backing handler initialized from _mockHttp and assign the setter to that handler so named client configuration is not silently ignored.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Activout.RestClient.Newtonsoft.Json.Test/MockHttpMessageHandlerBuilder.cs`
around lines 21 - 25, Update the PrimaryHandler property in
MockHttpMessageHandlerBuilder to use a mutable backing handler initialized to
_mockHttp. Make the setter assign the provided handler to that backing field,
and have the getter return it so ConfigurePrimaryHttpMessageHandler settings are
preserved.

Comment on lines +117 to +137
// Arrange
var client = CreateClient();
var collector = new HttpRequestMessageCollector();

_mockHttp
.Expect(HttpMethod.Post, BaseUri + "multiparttyped")
.With(message =>
{
collector.Message = message;
return message.Content?.Headers.ContentType?.MediaType == "multipart/form-data";
})
.Respond(HttpStatusCode.OK);

// Act
await client.SendTypedParts(new[]
{
new Part<string>(Content: "foo", FileName: "foo.txt"),
new Part<string>(Content: "bar", FileName: "bar.txt")
});

// Assert

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== candidate files =="
fd -a 'MultipartFormDataContentTest\.cs$' . || true

echo "== file excerpt =="
file=$(fd 'MultipartFormDataContentTest\.cs$' . | head -n 1)
if [ -n "${file:-}" ]; then
  wc -l "$file"
  sed -n '1,190p' "$file" | nl -ba | sed -n '100,150p'
fi

echo "== git diff context if available =="
git diff -- "$file" | sed -n '1,160p' || true

echo "== repository C# convention checks in test file around relevant lines =="
python3 - <<'PY'
from pathlib import Path
p = next(Path('.').rglob('MultipartFormDataContentTest.cs'), None)
if not p:
    print('file not found')
    raise SystemExit(0)
s=p.read_text()
for needle in ['// Arrange', '// Act', '// Assert', 'new[]', '[]\n']:
    print(f'{needle!r}: {needle in s}')
PY

Repository: twogood/Activout.RestClient

Length of output: 386


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="$(fd 'MultipartFormDataContentTest\.cs$' . | head -n 1)"

echo "== repository C# convention checks in test file around relevant lines =="
python3 - <<'PY'
from pathlib import Path
p = next(Path('.').rglob('MultipartFormDataContentTest.cs'), None)
if not p:
    print('file not found')
    raise SystemExit(0)
print(p)
for needle in ['// Arrange', '// Act', '// Assert', 'new[]', 'Part<string>(']:
    print(f'{needle!r}: {needle in p.read_text()}')
PY

echo "== relevant source excerpt =="
python3 - <<'PY'
from pathlib import Path
p = next(Path('.').rglob('MultipartFormDataContentTest.cs'), None)
lines = p.read_text().splitlines()
for i in range(109, 144):
    print(f"{i+1}: {lines[i]}")
PY

echo "== git diff context if available =="
git diff -- "$file" | sed -n '1,180p' || true

Repository: twogood/Activout.RestClient

Length of output: 1955


Align the new test with the repository C# conventions.

Use a collection expression instead of new[], and remove the phase-label comments that only describe what the code does.

Proposed fix
-            // Arrange
             var client = CreateClient();
             var collector = new HttpRequestMessageCollector();

-            // Act
-            await client.SendTypedParts(new[]
-            {
+            await client.SendTypedParts([
                 new Part<string>(Content: "foo", FileName: "foo.txt"),
                 new Part<string>(Content: "bar", FileName: "bar.txt")
-            });
+            ]);

-            // Assert
             _mockHttp.VerifyNoOutstandingExpectation();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Arrange
var client = CreateClient();
var collector = new HttpRequestMessageCollector();
_mockHttp
.Expect(HttpMethod.Post, BaseUri + "multiparttyped")
.With(message =>
{
collector.Message = message;
return message.Content?.Headers.ContentType?.MediaType == "multipart/form-data";
})
.Respond(HttpStatusCode.OK);
// Act
await client.SendTypedParts(new[]
{
new Part<string>(Content: "foo", FileName: "foo.txt"),
new Part<string>(Content: "bar", FileName: "bar.txt")
});
// Assert
var client = CreateClient();
var collector = new HttpRequestMessageCollector();
_mockHttp
.Expect(HttpMethod.Post, BaseUri + "multiparttyped")
.With(message =>
{
collector.Message = message;
return message.Content?.Headers.ContentType?.MediaType == "multipart/form-data";
})
.Respond(HttpStatusCode.OK);
await client.SendTypedParts([
new Part<string>(Content: "foo", FileName: "foo.txt"),
new Part<string>(Content: "bar", FileName: "bar.txt")
]);
_mockHttp.VerifyNoOutstandingExpectation();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Activout.RestClient.Test/MultipartFormDataContentTest.cs` around lines 117 -
137, Update the test around SendTypedParts to use a collection expression
instead of new[] for the Part<string> arguments, and remove the Arrange, Act,
and Assert phase-label comments while leaving the test behavior unchanged.

Source: Coding guidelines

Comment thread Activout.RestClient/Part.cs

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the REST client’s multipart upload model and broadens test coverage around multipart uploads and HttpClientFactory/delegating-handler scenarios (Newtonsoft.Json test suite), helping ensure correct request construction and response handling in more real-world DI setups.

Changes:

  • Added a generic Part<T> record and made Part.Content nullable to enable strongly typed multipart parts.
  • Added multipart upload test coverage for typed parts (Part<string>[]).
  • Added new Newtonsoft.Json tests and helpers to validate behavior through HttpClientFactory with delegating handlers, plus a small enum update and a new test dependency.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
Activout.RestClient/Part.cs Adds typed Part<T> and makes Content nullable for multipart parts.
Activout.RestClient.Test/MultipartFormDataContentTest.cs Adds a multipart test validating typed Part<string> uploads and routing.
Activout.RestClient.Newtonsoft.Json.Test/MockHttpMessageHandlerBuilder.cs Introduces a test HttpMessageHandlerBuilder for integrating MockHttp with HttpClientFactory.
Activout.RestClient.Newtonsoft.Json.Test/HttpClientFactoryWithDelegatingHandlerTest.cs Adds integration-style tests for delegating handlers and safe/unsafe content reuse scenarios.
Activout.RestClient.Newtonsoft.Json.Test/DomainExceptions/MyApiError.cs Adds an explicit Unexpected = 0 enum member.
Activout.RestClient.Newtonsoft.Json.Test/Activout.RestClient.Newtonsoft.Json.Test.csproj Adds Microsoft.Extensions.Http dependency required for HttpMessageHandlerBuilder.

set { }
}

public override IList<DelegatingHandler> AdditionalHandlers { get; } = new List<DelegatingHandler>();
Signed-off-by: David Eriksson <david@activout.se>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants