Skip to content

Initialize client

Before any request can be issued, an HttpJsonClient instance must have a base URL and a ClientInfo (machine name, application ID, user name) associated with it, either supplied at construction or set afterward through SetClientInfo.

Field Value
Operation ID OP-01
Trigger Construction of HttpJsonClient, or a call to SetClientInfo on a resolved instance
Inputs Base URL; ClientInfo (machine name, application ID, user name) or its constituent strings; optional timeout override in milliseconds
Outputs An initialized HttpJsonClient ready to accept requests, or an instance that will throw ClientNotInitializedException on first use if initialization is incomplete
Primary components HttpJsonClient.HttpJsonClient(string, ClientInfo), HttpJsonClient.HttpJsonClient(string, string, string, string), HttpJsonClient.HttpJsonClient(), HttpJsonClient.SetClientInfo, ClientInfo.ClientInfo
Entry point src/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/HttpJsonClient/HttpJsonClient.cs

Steps

  1. The consumer constructs HttpJsonClient using one of three paths:
  2. new HttpJsonClient(baseUrl, clientInfo) — baseUrl is null-checked and throws ArgumentNullException if null; clientInfo is not null-checked on this overload, so a null clientInfo is accepted silently here (BR-HTTP-02).
  3. new HttpJsonClient(baseUrl, userName, machineName, applicationId) — builds a ClientInfo internally, whose constructor null-checks each of machine name, application ID, and user name and throws ArgumentNullException immediately if any is null (BR-HTTP-03).
  4. new HttpJsonClient() — leaves the instance uninitialized; this is the only constructor dependency injection can satisfy, so DI-resolved instances require a subsequent SetClientInfo call before use*.
  5. If initialization was deferred or needs updating, the consumer calls SetClientInfo(baseUrl, userName, machineName, applicationId, msTimeoutOverride) or the four-argument overload without a timeout. Unlike the two-argument constructor, SetClientInfo validates immediately rather than deferring to the next request, but the call is not atomic: the five-argument overload stores a positive msTimeoutOverride on the instance first, then the shared four-argument logic constructs and assigns a new ClientInfo built from userName, machineName, and applicationId, and only after that succeeds does it construct and assign a new Uri built from baseUrl. A failing ClientInfo construction (null identity argument) or a failing Uri construction (invalid baseUrl) throws immediately, but any state mutation that already completed before the failure point — the stored timeout, and, for a bad baseUrl, the newly assigned ClientInfo — remains in effect on the instance.
  6. The timeout override is stored only when greater than 0; a value of 0 or less leaves any previously stored override unchanged rather than resetting it (BR-HTTP-06).
  7. This operation has two genuinely deferred-failure paths, both surfacing only on the first subsequent verb method call rather than at configuration time: the two-argument constructor called with a non-null baseUrl but a null clientInfo (step 1), and the parameterless constructor used without ever calling SetClientInfo afterward. In both cases ClientInfo and/or the base URI remain unset, and the first verb method invoked afterward throws ClientNotInitializedException (BR-HTTP-01).
  8. The instance is now ready to accept authentication configuration (see Configure authentication), option configuration (see Configure options), and request execution (see Execute request).

Process flow

The following diagram visualizes the initialization paths, the actual mutation order inside SetClientInfo, and the deferred-failure behavior when initialization is incomplete.

flowchart TD
    Start([Consumer obtains HttpJsonClient]) --> Choice{Construction path?}
    Choice -->|"baseUrl + ClientInfo"| C1["Null-check baseUrl only;<br>null clientInfo accepted silently"]
    Choice -->|"baseUrl + identity strings"| C2["Build ClientInfo immediately<br>(throws if any field is null)"]
    Choice -->|Parameterless / DI| C3["Uninitialized instance"]
    C3 --> SetInfo["SetClientInfo(...)"]
    SetInfo --> StoreTimeout{"5-arg overload with<br>msTimeoutOverride > 0?"}
    StoreTimeout -->|Yes| StoredTimeout["Store timeout override<br>(first mutation)"]
    StoreTimeout -->|No| SkipTimeout["Leave any previously stored<br>override unchanged"]
    StoredTimeout --> BuildClientInfo
    SkipTimeout --> BuildClientInfo
    BuildClientInfo["Construct and assign<br>new ClientInfo(...)<br>(throws on null identity field)"] --> BuildUri["Construct and assign<br>new Uri(baseUrl)<br>(throws on invalid baseUrl)"]
    BuildUri --> Ready([Ready for requests])
    C2 --> Ready
    C1 --> ClientInfoCheck{"clientInfo was non-null?"}
    ClientInfoCheck -->|Yes| Ready
    ClientInfoCheck -->|No| Fail(["First request throws<br>ClientNotInitializedException"])
    C3 -->|"No SetClientInfo call made"| Fail

Failure and edge-case behavior

  • A null baseUrl in the two-argument constructor fails immediately with ArgumentNullException, before any request is attempted.
  • A null clientInfo passed to the two-argument constructor is accepted silently, and a parameterless-constructed instance that never receives a SetClientInfo call is likewise left uninitialized; both gaps are discovered only when the first verb method throws ClientNotInitializedException — these are the two genuinely deferred-failure paths through this operation.
  • Calling SetClientInfo with a null or invalid baseUrl, or a null userName/machineName/applicationId, fails immediately inside the call itself (ArgumentNullException from ClientInfo's constructor, or an exception from the Uri constructor), but the call is not atomic: the positive timeout override (if supplied) and a successfully constructed ClientInfo are stored on the instance before the Uri construction is attempted, so a failing baseUrl can leave the instance with a newly updated ClientInfo/timeout and its previous base URI.
  • A timeout override of 0 or a negative value passed to SetClientInfo is not stored; any previously stored override remains unchanged. A value greater than 600000 ms is accepted and stored by SetClientInfo but ignored at request time (BR-HTTP-06).

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts.

Sources

  • src/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/HttpJsonClient/HttpJsonClient.cs
  • src/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/ClientInfo.cs