Skip to content

SAIF.Web.API.Clients.35 architecture

SAIF.Web.API.Clients.35 is a client-side integration/infrastructure library — the outbound HTTP client half of the SAIF Web API framework — that issues JSON requests to SAIF Web APIs and returns a typed result or a typed exception. It contains no business domain logic, no UI, and no persistence. The project is a .NET Framework v3.5 "shadow" build of the sibling SAIF.Web.API.Clients project: its folder holds no .cs files of its own, compiling instead the sibling project's source via <Compile Include> linked-file items. The project is not a member of src/SAIF.Web.API.Clients.sln, and its output is referenced only by commented-out entries in the shipped nuspec, so the evidence indicates a retired/dormant legacy variant retained in source but no longer built or packaged.

Responsibilities

  • Given a base URI, caller identity (ClientInfo), and an authenticator, issue a JSON HTTP request to a SAIF Web API and return a typed result (GetResult<T>), a typed result array (GetResults<T>), or a full response envelope (GetResponse<T>, PostJson<T>, PutJson<T>, PatchJson<T>, DeleteJson<T>).
  • Serialize outbound request bodies and deserialize inbound JSON payloads using a Newtonsoft-based JsonSerializer with configurable DateTimeZoneHandling.
  • Translate unsuccessful HTTP responses into a typed SAIFException subtype (ExceptionHandler), sourced from SAIF.Web.API.Core's exception taxonomy.
  • Optionally propagate identity headers on every request (Client-Name, Application-ID, Client-User) and, when configured, an on-behalf-of impersonation header.
  • Retry transient failures (default: transport failure/502/503/401) up to 3 times with a configurable delay before surfacing an error.

Component boundaries

  • Public façade (JsonHttpClient): verb-specific entry points (GetResult, GetResults, GetResponse, PostJson, PutJson, PatchJson, DeleteJson) — the only public API surface consumers use directly.
  • Request construction / transport (JsonHttpClient.GetJsonResponse, private): RestClient/RestRequest assembly, header injection, authenticator attachment, retry loop, and timeout handling.
  • Serialization (JsonSerializer, JsonHttpClient.GetContentArray<T>): Newtonsoft-based JSON ⇄ CLR conversion honoring the configured DateTimeZoneHandling.
  • Error translation (ExceptionHandler): maps HTTP status code + response body to a specific SAIFException subtype.
  • Data carriers (ClientInfo, EnvironmentSetting public; JsonResponse internal): immutable/POCO state passed between the layers above. EnvironmentSetting is not referenced by any other type in this library's compiled scope — it is an unused public DTO here.*

Interaction model

  • Outbound boundary: HTTP(S) to a SAIF Web API, via RestSharp. The base URI is supplied entirely by the caller (Uri serviceBaseUri); the library contains no endpoint literals.
  • Contract boundary: SAIF.Web.API.Core defines the shared response envelope (ApiResponse<T>) and exception taxonomy (SAIF.API.Exceptions.*) used on both the service and client side — the coupling point that keeps client and server error semantics aligned.
  • Ambient-context boundary (leaky): when SetOnBehalfOfUserHeaders is true, JsonHttpClient reads System.Web.HttpContext.Current, binding an otherwise transport-neutral library to an ASP.NET hosting context. In this .35 project the supporting HttpContextExtensions.cs source file is excluded from compilation and System.Web is not referenced, so this path has no working implementation in the net3.5 variant.

Architecture diagram

The following diagram shows the high-level component interactions for the .35 variant, including its coupling to the sibling source project and its outbound call chain to the remote API.

flowchart TD
    Caller["Calling application"] --> Facade["JsonHttpClient<br>(public facade)"]
    Facade --> Transport["GetJsonResponse<br>(request<br>construction/transport)"]
    Transport --> Serializer["JsonSerializer<br>(Newtonsoft-based)"]
    Transport --> RestSharpLib["RestSharp 105.2.3<br>(external package)"]
    RestSharpLib --> RemoteApi["SAIF Web API<br>(caller-supplied base<br>URI)"]
    Transport --> ErrorHandler["ExceptionHandler<br>(HTTP status to<br>SAIFException)"]
    LinkedSource["Linked source from<br>SAIF.Web.API.Clients<br>(no .cs files owned<br>locally)"] -.compiles into.-> Facade

The following diagram shows the shared contract boundary: both the public facade and the error handler depend on SAIF.Web.API.Core for the response envelope and exception taxonomy used by both the client and the server.

flowchart TD
    Facade["JsonHttpClient<br>(public facade)"] --> CoreLib["SAIF.Web.API.Core<br>(ApiResponse&lt;T&gt;,<br>SAIFException hierarchy)"]
    ErrorHandler["ExceptionHandler<br>(HTTP status to<br>SAIFException)"] --> CoreLib

Sequence diagram

The following diagram shows the primary request/response sequence for a write operation (for example PostJson<T>), including the retry and error-translation steps.

sequenceDiagram
    participant Caller
    participant JsonHttpClient
    participant RestSharp
    participant SAIFWebAPI as SAIF Web API
    participant ExceptionHandler
    Caller->>JsonHttpClient: PostJson<T>(uriSegment, body)
    JsonHttpClient->>JsonHttpClient: Build RestRequest + identity headers
    JsonHttpClient->>RestSharp: Execute(request)
    RestSharp->>SAIFWebAPI: HTTP request
    SAIFWebAPI-->>RestSharp: HTTP response
    RestSharp-->>JsonHttpClient: IRestResponse
    alt retryable status and retries remain
        JsonHttpClient->>JsonHttpClient: Sleep(RetryDelayInMs), retry
    end
    JsonHttpClient->>ExceptionHandler: EnsureSuccessfulResponse(response)
    alt status 200-399
        ExceptionHandler-->>JsonHttpClient: return normally
        JsonHttpClient-->>Caller: ApiResponse<T>
    else status <200 or >=400
        ExceptionHandler-->>JsonHttpClient: throw SAIFException subtype
        JsonHttpClient-->>Caller: exception propagated
    end

Design constraints

  • Dormant/retired legacy variant. The project has no source files of its own (links compile from the sibling SAIF.Web.API.Clients folder), is absent from src/SAIF.Web.API.Clients.sln (so CI never builds it), and its output is referenced only by commented-out <file> entries in nuspec/SAIF.Web.API.Clients/SAIF.Web.API.Clients.nuspec — the net35 assembly is not shipped by the current package definition.
  • Cross-framework project reference mismatch. This project targets .NET Framework v3.5 but its only in-repo dependency, SAIF.Web.API.Core, targets v4.6.2; a net4.6.2 assembly cannot be referenced from a net3.5 assembly.
  • Excluded on-behalf-of implementation. JsonHttpClient.cs declares using SAIF.Web.API.Clients.Extensions; and calls HttpContext.Current.DomainlessUser(), but Extensions/HttpContextExtensions.cs is deliberately excluded from this project and System.Web is not referenced — the on-behalf-of impersonation path (SetOnBehalfOfUserHeaders) has no compilable implementation in this variant.
  • RestSharp namespace drift. The linked source imports RestSharp.Serialization.Json, a namespace introduced in the RestSharp 106.x line, while this project pins RestSharp 105.2.3 via packages.config — the namespace is not expected to exist in the pinned assembly, compounding the build-viability concern.
  • Dependency version divergence from the net4.6.2 sibling. RestSharp (105.2.3 vs 106.12.0) and SAIF.Framework.Common (1.0.17234.2 vs 2.0.22074.3, a major-version gap) are pinned to older versions than the actively-built sibling project.
  • No assembly-level attributes compiled. The excluded Properties/AssemblyInfo.cs leaves only an empty Properties\ folder declared in the project, so no assembly-level attributes are compiled into the net35 output.

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.35/SAIF.Web.API.Clients.35.csproj
  • src/SAIF.Web.API.Clients.35/packages.config
  • src/SAIF.Web.API.Clients/JsonHttpClient.cs
  • src/SAIF.Web.API.Clients/ClientInfo.cs
  • src/SAIF.Web.API.Clients/ExceptionHandler.cs
  • src/SAIF.Web.API.Clients/JsonSerializer.cs
  • src/SAIF.Web.API.Clients/JsonResponse.cs
  • src/SAIF.Web.API.Clients/EnvironmentSetting.cs
  • src/SAIF.Web.API.Clients/Extensions/HttpContextExtensions.cs (excluded from this project)
  • src/SAIF.Web.API.Core/SAIF.Web.API.Core.csproj
  • src/SAIF.Web.API.Clients.sln
  • nuspec/SAIF.Web.API.Clients/SAIF.Web.API.Clients.nuspec