bhylu.com

Advertisements

C# HttpClient

Inject a deterministic handler and check the response status before reading its result.

How it works

HttpClient sends requests through a message handler, which can be supplied for a controlled test. This lesson uses an in-memory fixture handler rather than a network connection, making the response deterministic and avoiding credentials or external side effects. Production clients need timeouts, cancellation, response-size limits and a policy for retrying only appropriate failures. Reuse clients according to their lifetime contract; creating one per real request can create connection-management problems.

Run it locally

Use the .NET 10 SDK with C# 14 in a separate console lab. Create an empty project once with dotnet new console --framework net10.0, then replace Program.cs with this complete source and add any supporting files shown. Keep only one lesson entry point in the project. C# does not currently run in Bhylu’s browser playground. Apache, PHP and MySQL are not needed.

dotnet build -p:LangVersion=14.0 -p:Nullable=enable -p:TreatWarningsAsErrors=true
dotnet run --no-build

Use the SDK’s project workflow; the review compiles against its matching reference assemblies and executes the results without external NuGet packages. File-writing examples belong in a private empty lab directory.

Environment boundary: In-memory HttpMessageHandler fixture only. No live request, loopback server, TLS verification or external API delivery is claimed.

Download the complete C# source as Program.cs.

Example

C# 14 · Program.cs

using System;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

internal static class Program
{
    private static async System.Threading.Tasks.Task Main(string[] args)
    {
        using var client = new HttpClient(new FixtureHandler());
        using HttpResponseMessage response = await client.GetAsync("https://fixture.invalid/workshops");
        response.EnsureSuccessStatusCode();
        string body = await response.Content.ReadAsStringAsync();
        Console.WriteLine(body);
    }
}

internal sealed class FixtureHandler : HttpMessageHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken token)
    {
        token.ThrowIfCancellationRequested();
        if (request.RequestUri?.AbsolutePath != "/workshops")
            return Task.FromResult(new HttpResponseMessage(HttpStatusCode.NotFound));
        return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent("2 workshops available") });
    }
}

Expected result

2 workshops available

The supplied handler returns an owned response entirely in memory. The example tests client-side handler composition and status handling, not DNS, TLS, sockets or a live API. The reserved invalid hostname is never contacted. A production import must still validate the response’s content and domain schema instead of treating HTTP 200 as proof of a valid booking.

Consult Microsoft’s C# documentation for language and library contracts, including target-framework and version requirements.

Advertisements