---
title: Initialize client
summary: Configure the base URL and caller identity an HttpJsonClient instance uses for every request.
status: draft
owner: Framework
last_reviewed: 2026-10-02
library: SAIF.NetCore.HttpClients
reference_type: package
operation_id: OP-01
trigger: A consumer constructs or configures a resolved HttpJsonClient before issuing its first request
---

# 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:
   - `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](../business-rules.md#br-http-02-base-url-required-in-the-two-argument-constructor)).
   - `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](../business-rules.md#br-http-03-clientinfo-requires-non-null-identity-values)).
   - `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*.
2. 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.
   - 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](../business-rules.md#br-http-06-timeout-override-bounds)).
   - 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](../business-rules.md#br-http-01-client-initialization-required-before-any-request)).
3. The instance is now ready to accept authentication configuration (see [Configure authentication](configure-authentication.md)), option configuration (see [Configure options](configure-options.md)), and request execution (see [Execute request](execute-request.md)).

## Process flow

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

```mermaid
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](../business-rules.md#br-http-06-timeout-override-bounds)).

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)

> **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`
