Skip to content

SAIF.Web.API.Clients.35 business rules

This page captures the framework/behavioral contract rules enforced by this library. SAIF.Web.API.Clients.35 is an infrastructure library; the rules below govern HTTP client behavior (identity propagation, authentication, retry, serialization, and error translation), not SAIF insurance-domain business logic. No domain-specific rule was found in the compiled scope. All rules apply identically to the linked source shared with SAIF.Web.API.Clients, subject to the dormant/retired build status described in Overview.

BR-01 Identity headers on every request

Field Value
Statement Every outbound request must identify the calling machine, application, and user.
Trigger Any request built.
Enforcement JsonHttpClient.GetJsonResponse adds Client-Name, Application-ID, Client-User headers from ClientInfo.
Outcome The three identity headers are present on every outbound request.
Source src/SAIF.Web.API.Clients/JsonHttpClient.cs, src/SAIF.Web.API.Clients/ClientInfo.cs

BR-02 Default NTLM authentication

Field Value
Statement Requests authenticate with NTLM unless the caller supplies an authenticator.
Trigger Client construction.
Enforcement JsonHttpClient constructor: _authenticator = authenticator ?? new NtlmAuthenticator().
Outcome RestClient.Authenticator is set to the supplied authenticator, or NtlmAuthenticator by default.
Source src/SAIF.Web.API.Clients/JsonHttpClient.cs

BR-03 Conditional timeout override

Field Value
Statement A timeout override is applied only when greater than zero.
Trigger Client creation.
Enforcement JsonHttpClient.GetJsonResponse: if (TimeoutOverride > 0).
Outcome client.Timeout is set when TimeoutOverride > 0; otherwise the RestSharp default applies.
Source src/SAIF.Web.API.Clients/JsonHttpClient.cs

BR-04 On-behalf-of header forwarding

Field Value
Statement When acting on behalf of an interactive user, the domainless user name is forwarded.
Trigger SetOnBehalfOfUserHeaders == true.
Enforcement JsonHttpClient.GetJsonResponse adds an OnBehalfOfUser header sourced from HttpContext.Current.DomainlessUser().
Outcome The OnBehalfOfUser header is added to the request. In this .35 project, Extensions/HttpContextExtensions.cs is excluded from compilation and System.Web is not referenced, so this path has no compilable implementation here.*
Source src/SAIF.Web.API.Clients/JsonHttpClient.cs, src/SAIF.Web.API.Clients/Extensions/HttpContextExtensions.cs (excluded from this project)

BR-05 Transient failure retry

Field Value
Statement Transient failures are retried up to 3 times with a delay.
Trigger Response status is in RetryOnStatusCodes (default: transport failure 0, 502, 503, 401) and retries > 0.
Enforcement JsonHttpClient.GetJsonResponse: Thread.Sleep(RetryDelayInMs) then recursive re-issue.
Outcome Up to 3 retry attempts occur before the response is passed to error handling.
Source src/SAIF.Web.API.Clients/JsonHttpClient.cs

BR-06 Unsuccessful response raises typed exception

Field Value
Statement Unsuccessful responses raise typed exceptions unless suppressed.
Trigger EnsureSuccessfulResponse == true.
Enforcement JsonHttpClient.GetJsonResponse calls ExceptionHandler.EnsureSuccessfulResponse(response).
Outcome A typed SAIFException subtype is thrown for non-success responses.
Source src/SAIF.Web.API.Clients/JsonHttpClient.cs, src/SAIF.Web.API.Clients/ExceptionHandler.cs

BR-07 Configured DateTimeZoneHandling applied to serialization

Field Value
Statement Request bodies serialize with the client's configured DateTimeZoneHandling.
Trigger Request build.
Enforcement JsonHttpClient.GetJsonResponse / JsonSerializer constructor configure the serializer per instance.
Outcome The serializer instance honors the client's DateTimeZoneHandling setting for the request.
Source src/SAIF.Web.API.Clients/JsonHttpClient.cs, src/SAIF.Web.API.Clients/JsonSerializer.cs

BR-08 Array deserialization normalization

Field Value
Statement JSON arrays deserialize to List<T>; single objects deserialize to a one-element list.
Trigger Payload deserialization.
Enforcement JsonHttpClient.GetContentArray<T>.
Outcome ApiResponse<T>.Results is populated as a normalized list regardless of whether the payload was a JSON array or a single object.
Source src/SAIF.Web.API.Clients/JsonHttpClient.cs

BR-09 String deserialization failure fallback

Field Value
Statement Deserialization failures for T = string return the exception message as the result instead of throwing.
Trigger catch (Exception ex) in GetContentArray<T>.
Enforcement JsonHttpClient.GetContentArray<T>.
Outcome ex.Message becomes the single result for T = string; for other T the result array is empty.
Source src/SAIF.Web.API.Clients/JsonHttpClient.cs

BR-10 Server name from response header

Field Value
Statement The responding server name is taken from the Server-Name response header.
Trigger Envelope construction.
Enforcement JsonHttpClient.GetApiResponse<T>.
Outcome ApiResponse.Server is set from the first header named Server-Name; null when the header is absent.
Source src/SAIF.Web.API.Clients/JsonHttpClient.cs

BR-11 String result unquoting

Field Value
Statement A string result is returned with surrounding double quotes stripped.
Trigger T == string.
Enforcement JsonHttpClient.GetResult<T>.
Outcome The caller receives the unquoted string content.
Source src/SAIF.Web.API.Clients/JsonHttpClient.cs

BR-12 Primitive result conversion

Field Value
Statement Primitive results convert directly from raw content.
Trigger typeof(T).IsPrimitive.
Enforcement JsonHttpClient.GetResult<T> calls Convert.ChangeType(content, T).
Outcome The caller receives the converted primitive value.
Source src/SAIF.Web.API.Clients/JsonHttpClient.cs

BR-13 Byte array Base64 decoding

Field Value
Statement byte[] results are Base64-decoded from the quoted content.
Trigger T == byte[].
Enforcement JsonHttpClient.GetResult<T> calls Convert.FromBase64String(content.Trim('"')).
Outcome The caller receives the decoded byte array.
Source src/SAIF.Web.API.Clients/JsonHttpClient.cs

BR-14 Null payload default result

Field Value
Statement A null or literal "null" payload yields default(T).
Trigger Content is null or the literal string "null".
Enforcement JsonHttpClient.GetResult<T>.
Outcome The caller receives default(T).
Source src/SAIF.Web.API.Clients/JsonHttpClient.cs

BR-15 Cast failure default result

Field Value
Statement A cast failure on a complex result yields default(T) rather than an exception.
Trigger InvalidCastException thrown while extracting the first element of the deserialized content array.
Enforcement JsonHttpClient.GetResult<T>.
Outcome The caller receives default(T) instead of an unhandled exception. An empty result array raises IndexOutOfRangeException instead, since only InvalidCastException is caught.*
Source src/SAIF.Web.API.Clients/JsonHttpClient.cs

BR-16 Success status range

Field Value
Statement Only status codes in 200–399 are treated as success.
Trigger Any response.
Enforcement ExceptionHandler.EnsureSuccessfulResponse.
Outcome Status codes outside 200–399 proceed to error mapping; others pass through.
Source src/SAIF.Web.API.Clients/ExceptionHandler.cs

BR-17 Error message source selection

Field Value
Statement Error text is sourced from the response body when present. When the body is blank, GetContent's nested condition checks do not implement a simple "prefer ErrorMessage, else ErrorException, else status line" precedence: a nonblank ErrorMessage with a null ErrorException falls through to an empty string; a blank ErrorMessage with a non-null ErrorException returns the blank ErrorMessage (not the exception text); only when both ErrorMessage is nonblank and ErrorException is non-null does the method return ErrorException.Message. The synthesized status line is used only when both ErrorMessage and ErrorException are absent and the status is not 400.
Trigger Error mapping, when response.Content is null/whitespace.
Enforcement ExceptionHandler.GetContent: if (!Content.IsNullOrWhiteSpace()) return Content; else if (!ErrorMessage.IsNullOrWhiteSpace() \|\| ErrorException != null) { if (ErrorMessage.IsNullOrWhiteSpace()) return ErrorMessage; else if (ErrorException != null) return ErrorException.Message; } else if (StatusCode != BadRequest) return "{code} - {StatusDescription}"; return string.Empty; using SAIF.Common.Extensions.IsNullOrWhiteSpace from SAIF.Framework.Common.
Outcome Body present → body text. Body blank, ErrorMessage nonblank + ErrorException null → string.Empty (not ErrorMessage). Body blank, ErrorMessage blank + ErrorException non-null → blank ErrorMessage (not ErrorException.Message). Body blank, both present → ErrorException.Message. Body blank, both absent → status line unless status is 400, otherwise string.Empty.
Constraint/defect The inner branch order in GetContent appears inverted relative to its evident intent (prefer ErrorMessage, else fall back to ErrorException.Message): as written, a lone nonblank ErrorMessage is discarded and a lone ErrorException is also discarded in favor of the blank ErrorMessage. This is documented as observed, verified behavior of the current implementation, not its apparent designed intent.
Source src/SAIF.Web.API.Clients/ExceptionHandler.cs

BR-18 Recognized error property names

Field Value
Statement Recognized error property names are errormessage, exceptionmessage, message, usermessage (case-insensitive).
Trigger Response body parses as JSON.
Enforcement ExceptionHandler.ToKnownError via JToken.Parse(content).
Outcome Matching property values are accumulated into the extracted error message.
Source src/SAIF.Web.API.Clients/ExceptionHandler.cs

BR-19 Fallback to raw body on parse failure

Field Value
Statement Unparseable or empty structured errors fall back to the raw body.
Trigger JSON parsing throws, or the accumulated error-message builder is blank.
Enforcement ExceptionHandler.ToKnownError.
Outcome The raw response content becomes the error message.
Source src/SAIF.Web.API.Clients/ExceptionHandler.cs

BR-20 HTTP status to exception type mapping

Field Value
Statement HTTP status maps to exception type: 404 → NoMatchingDataException, 401/403 → UnauthorizedAccessException, 400 → InvalidDataException, all others → InternalServerError.
Trigger Error mapping.
Enforcement ExceptionHandler.ToKnownError, constructing types from SAIF.Web.API.Core's SAIF.API.Exceptions.SAIFException hierarchy.
Outcome A typed exception is thrown with HttpStatusCode populated.
Source src/SAIF.Web.API.Clients/ExceptionHandler.cs, src/SAIF.Web.API.Core/SAIFException.cs

BR-21 Serialization member and value handling

Field Value
Statement Serialization ignores unknown members and includes nulls and default values.
Trigger Request body serialization.
Enforcement JsonSerializer constructor applies MissingMemberHandling.Ignore, NullValueHandling.Include, DefaultValueHandling.Include.
Outcome Newtonsoft settings are applied consistently to every serialized request body.
Source src/SAIF.Web.API.Clients/JsonSerializer.cs

Notes

  • This is an infrastructure library; the rules above are framework/behavioral contract rules, not SAIF insurance-domain business rules. No domain-specific rule was found in the compiled scope.

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
  • 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/Extensions/HttpContextExtensions.cs (excluded from this project)
  • src/SAIF.Web.API.Core/SAIFException.cs