Skip to content

JsonHttpClient

JsonHttpClient is the sole public entry point of SAIF.Web.API.Clients. It wraps a RestSharp.RestClient to issue authenticated, retried, header-annotated HTTP calls against a SAIF JSON Web API, and routes every public verb method through one shared private funnel (GetJsonResponse) so authentication, identity headers, retry, and success-enforcement apply uniformly and cannot be bypassed per call. It has no base class, defines no interface, and has no virtual members, so it cannot be substituted or mocked without wrapping it.

Purpose

  • Provide GET/POST/PUT/PATCH/DELETE verb methods (GetResult<T>, GetResults<T>, GetResponse<T>, PostJson<T>, PutJson<T>, PatchJson<T>, DeleteJson<T>) that a consuming application uses to call a SAIF Web API without hand-writing HTTP, authentication, retry, or JSON-shape-normalization code (see Operations and processes).
  • Enforce BR-CLI-001, BR-CLI-002, BR-CLI-005, and BR-CLI-006 on every request via the shared GetJsonResponse funnel.
  • Translate transport-level responses into the ApiResponse<T> envelope or a materialized T, normalizing array/object/scalar JSON shapes uniformly (BR-CLI-012).

Context

  • Namespace: SAIF.Web.API.Clients
  • Assembly/package: SAIF.Web.API.Clients (NuGet package SAIF.Web.API.Clients)

Public members

Member Signature Purpose
Constructor JsonHttpClient(Uri serviceBaseUri, ClientInfo clientInfo, IAuthenticator authenticator) Canonical constructor; falls back to new NtlmAuthenticator() when authenticator is null (BR-CLI-001).
Constructor JsonHttpClient(Uri serviceBaseUri, ClientInfo clientInfo) Chains to the canonical constructor with new NtlmAuthenticator().
Constructor JsonHttpClient(Uri serviceBaseUri, ClientInfo clientInfo, IAuthenticator authenticator, int timeoutOverride) Chains to the canonical constructor, then sets TimeoutOverride.
Constructor JsonHttpClient(Uri serviceBaseUri, ClientInfo clientInfo, int timeoutOverride) Chains to the canonical constructor with a fresh NtlmAuthenticator, then sets TimeoutOverride. This overload does not make a caller-supplied authenticator reachable, because it always passes a new NtlmAuthenticator*.
TimeoutOverride int { get; } (ctor-assigned, default 0) Request timeout in milliseconds; applied only when greater than 0 (BR-CLI-010).
DateTimeZoneHandling Newtonsoft.Json.DateTimeZoneHandling { get; set; } (default Local) Governs both request serialization and response deserialization of date values (BR-CLI-011).
EnsureSuccessfulResponse bool { get; set; } (default true) When true, non-success responses are converted to typed exceptions instead of being returned to the caller (BR-CLI-006).
SetOnBehalfOfUserHeaders bool { get; set; } (default false) When true, adds the OnBehalfOfUser header from the ambient HttpContext, requiring a web host (BR-CLI-003).
RetryDelayInMs int { get; set; } (default 1000) Sleep duration between retry attempts.
RetryOnStatusCodes IEnumerable<HttpStatusCode> { get; set; } (default {0, 502, 503, 401}) Status codes that trigger a retry before success is evaluated (BR-CLI-005).
GetResult<T> T GetResult<T>(string methodUriSegment) Issues a GET and returns a single materialized T with type-specific coercion; see GetResult\<T>.
GetResults<T> T[] GetResults<T>(string methodUriSegment) Issues a GET and returns ApiResponse<T>.Results; see GetResults\<T>.
GetResponse<T> ApiResponse<T> GetResponse<T>(string methodUriSegment) Issues a GET and returns the full envelope; see GetResponse\<T>.
PostJson<T> ApiResponse<T> PostJson<T>(string methodUriSegment, object requestBody) Issues a POST with a JSON body; see write operations.
PutJson<T> ApiResponse<T> PutJson<T>(string methodUriSegment, object requestBody) Issues a PUT with a JSON body; see write operations.
PatchJson<T> ApiResponse<T> PatchJson<T>(string methodUriSegment, object requestBody) Issues a PATCH with a JSON body; see write operations.
DeleteJson<T> ApiResponse<T> DeleteJson<T>(string methodUriSegment, object requestBody) Issues a DELETE with a JSON body — there is no body-less DELETE overload; see write operations.

Behavioral notes

  • Every public verb method routes through the private GetJsonResponse funnel, so header injection, authentication, retry, and success-enforcement cannot be bypassed per call (GetJsonResponse).
  • All HTTP execution is synchronous and blocking (client.Execute, Thread.Sleep for retry delay); there is no async/await surface.
  • A new RestClient is constructed for every call — there is no connection/handler reuse across calls*.
  • SetOnBehalfOfUserHeaders = true couples the client to System.Web.HttpContext.Current; calling it from a non-web host (console/service/test) throws NullReferenceException because no guard exists.
  • GetContentArray<T> (internal static) normalizes JSON response shapes for GetResult<T> and GetResponse<T>, but is not part of the public surface; see GetContentArray\<T>.

Constraints and usage notes

  • ClientInfo passed to the constructor is not null-checked; a null value throws NullReferenceException when headers are added.
  • methodUriSegment, serviceBaseUri, and requestBody receive no input validation from this library.

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.Web.API.Clients/JsonHttpClient.cs