---
title: SAIF.Web.API architecture
summary: Architectural responsibilities, boundaries, and interaction patterns.
status: draft
owner: andmil
last_reviewed: 2026-09-15
library: SAIF.Web.API
reference_type: package
---

# SAIF.Web.API architecture

`SAIF.Web.API` is a cross-cutting-concerns library for ASP.NET Web API 2 (`System.Web.Http`) host applications. It supplies a response/error post-processing message handler, a delegated role-based authorization attribute, an HTTPS-enforcement action filter, a static exception-to-HTTP-status mapper, and a request-header extension helper. It contains no controllers, no entry point, and no database access; every actual authorization and configuration decision is delegated to services assumed to be supplied by the hosting application — no such registration or supply exists inside this library.*

## Responsibilities
- Post-process every outbound Web API response to add a correlation `MessageID`/`MessageIDUrl`, redact sensitive request content from debug traces, and rewrite non-success responses into a structured `ErrorResponse` body (`ApiResponseHandler`).
- Enforce role/resource-based authorization on Web API controllers/actions by delegating the authorization decision to an injected `ISecurityApiClient` (`SaifAuthorizeAttribute`).
- Enforce HTTPS on Web API actions, with a configurable relaxation for local/developer requests (`RequireSSLAttribute`).
- Provide a static, reusable mapping from typed `SAIF.API.Exceptions.*` exceptions to `HttpStatusCode` values for consuming controllers/exception filters (`ExceptionHandler`).
- Consume a response-envelope/typed-exception contract (`ErrorResponse`, `SAIF.API.Exceptions.*`) by fully-qualified type name; the compile-time-resolved assembly that actually supplies these types could not be confirmed — see [Component boundaries](#component-boundaries).**

## Component boundaries
- `ApiResponseHandler` (`SAIF.Web.API`, derives `System.Net.Http.DelegatingHandler`): registered by the host in `HttpConfiguration.MessageHandlers`; no such registration exists in this repository.* Once registered, it wraps every request/response pair, times it, resolves `ILogService`/`IEnvironmentService` per request via `IDependencyScope`, and rewrites error responses.
- `SaifAuthorizeAttribute` (`SAIF.Web.API`, derives `System.Web.Http.AuthorizeAttribute`, sealed): applied by the *host* to its own controllers/actions (no controllers exist inside this library, and no such application exists in this repository).* Resolves `ISecurityApiClient`/`IEnvironmentService` per request and never calls `base.IsAuthorized`, so the base attribute's built-in identity check is bypassed entirely.
- `RequireSSLAttribute` (`SAIF.Web.API`, derives `System.Web.Http.Filters.ActionFilterAttribute`): applied by the host as an action filter; no such application exists in this repository.* Reads the ambient application's `RequireSSLForLocal` app setting directly via `ConfigurationManager.AppSettings`, bypassing `IEnvironmentService`; no such application or setting exists in this repository.*
- `ExceptionHandler` (`SAIF.Web.API`, static class): a stateless mapping utility with no call site inside this library; intended for host controllers/exception filters to call explicitly.
- `HttpRequestExtensions` (`SAIF.Web.API`, static extension class): a generic request-header reader (`TryGetFirstHeader`) with no security-specific role in this library.
- `ErrorResponse` / `SAIF.API.Exceptions.*` (consumed types, not defined in this library's boundary): `ApiResponseHandler` and `ExceptionHandler` reference these fully-qualified type names at compile time, but `SAIF.Web.API.csproj` declares no `<ProjectReference>`/`<PackageReference>` to any project or package that names them explicitly. A sibling project in this repository, `SAIF.Web.API.Core` (out of scope for this library's documentation), declares types with these exact namespace-qualified names, and the `SAIF.Framework.Core` NuGet package is also a candidate supplier. Which assembly the compiler and runtime actually resolve these types from is unresolved — see [Dependencies](dependencies.md).**
- Externally supplied contracts consumed via the host's dependency scope (not defined in this library): `IEnvironmentService`, `ILogService`/`ILogServiceForApi`, `ISecurityApiClient` — all originate from the `SAIF.Framework.Core` NuGet package.

## Interaction model
- The hosting Web API application registers `ApiResponseHandler` in `HttpConfiguration.MessageHandlers`, so it wraps every inbound request/outbound response pair in the pipeline; no registration call site exists in this repository, so this describes the intended host-side usage pattern rather than an observed registration.*
- The hosting application decorates its own controllers/actions with `[SaifAuthorizeAttribute(roles)]` and/or `[RequireSSLAttribute]`; this library provides the attribute implementations only — it applies neither to any code of its own.*
- `ApiResponseHandler` and `SaifAuthorizeAttribute` both resolve `ILogService`, `IEnvironmentService`, and `ISecurityApiClient` per request via ASP.NET Web API's `IDependencyScope` (`request.GetDependencyScope().GetService(typeof(T))`) — a service-locator pattern, not constructor injection. This means the library assumes the hosting application has registered these services with its own `IDependencyResolver`; if `ISecurityApiClient` or `IEnvironmentService` is unregistered, `SaifAuthorizeAttribute.IsAuthorized` throws `MissingDependencyException` rather than denying access.*
- `SaifAuthorizeAttribute` delegates the actual per-role authorization decision to `ISecurityApiClient.IsAuthorized(user, role)`; the concrete implementation (WCF `SecurityService` facade, HTTP API, or other mechanism) is defined in `SAIF.Framework.Core` and is not determinable from this repository.**
- `SAIF.Web.API` references `ErrorResponse` and `SAIF.API.Exceptions.*` by fully-qualified type name at compile time, but `SAIF.Web.API.csproj` declares **no `<ProjectReference>` or `<PackageReference>`** that names either the sibling `SAIF.Web.API.Core` project or an equivalent package containing these types explicitly. Both `SAIF.Web.API.Core` (same repository) and the `SAIF.Framework.Core` NuGet package are candidate suppliers of these identically-named types; which one the build actually resolves is an open question that would require inspecting the restored `SAIF.Framework.Core` 2.0.25119.2 assembly to settle — see [Dependencies](dependencies.md).**
- `ExceptionHandler.ToHttpError` has no call site inside this library; it is exposed as a static utility for host controllers/exception filters to call explicitly.*

## Architecture diagram
The following diagram shows the inbound request path through this library's components, from the client request to the response (or the unresolved contracts dependency).

```mermaid
flowchart TD
	Client[Client request] --> Handler["ApiResponseHandler<br>(DelegatingHandler)"]
	Handler --> Pipeline["Host Web API pipeline<br>(controllers/actions)"]
	Pipeline --> AuthAttr["SaifAuthorizeAttribute<br>(AuthorizeAttribute)"]
	Pipeline --> SSLAttr["RequireSSLAttribute<br>(ActionFilterAttribute)"]
	Pipeline --> ExHandler["ExceptionHandler<br>(static utility,<br>host-invoked)"]
	Handler -.->|"resolved assembly<br>unconfirmed"| Contracts["ErrorResponse /<br>SAIF.API.Exceptions.*<br>(source unresolved:<br>SAIF.Web.API.Core?<br>SAIF.Framework.Core?)"]
	ExHandler -.->|"resolved assembly<br>unconfirmed"| Contracts
	Handler --> ClientResp[Response to client]
```

The following diagram shows how `ApiResponseHandler`, `SaifAuthorizeAttribute`, and `RequireSSLAttribute` — the same nodes shown above — each depend on services the hosting application is expected to supply.

```mermaid
flowchart TD
	AuthAttr["SaifAuthorizeAttribute<br>(AuthorizeAttribute)"] --> SecClient["ISecurityApiClient<br>(SAIF.Framework.Core)"]
	Handler["ApiResponseHandler<br>(DelegatingHandler)"] --> EnvSvc["IEnvironmentService<br>(SAIF.Framework.Core)"]
	AuthAttr --> EnvSvc
	Handler --> LogSvc["ILogService /<br>ILogServiceForApi<br>(SAIF.Framework.Core)"]
	AuthAttr --> LogSvc
	SSLAttr["RequireSSLAttribute<br>(ActionFilterAttribute)"] --> AppConfig["Host<br>ConfigurationManager.<br>AppSettings"]
```

## Sequence diagram
The following diagram shows the primary request sequence when a decorated action fails authorization.

```mermaid
sequenceDiagram
	participant Client
	participant Handler as ApiResponseHandler
	participant Auth as SaifAuthorizeAttribute
	participant SecClient as ISecurityApiClient
	participant LogSvc as ILogService
	Client->>Handler: HTTP request
	Handler->>Auth: base.SendAsync -> pipeline dispatch
	Auth->>Auth: Resolve ISecurityApiClient / IEnvironmentService via IDependencyScope
	Auth->>SecClient: IsAuthorized(user, role) for each configured role
	SecClient-->>Auth: false (no matching role)
	Auth->>LogSvc: LogException(SecurityException) if user known
	Auth-->>Handler: 401 Unauthorized response
	Handler->>Handler: BuildApiResponse (MessageID, ErrorResponse body)
	Handler-->>Client: 401 response with structured ErrorResponse
```

## Design constraints
- Targets .NET Framework 4.6.2 and ASP.NET Web API 2 (`System.Web.Http`, IIS/OWIN hosting) — not ASP.NET Core; `RequireSSLAttribute`'s redirect further couples it to `System.Web`/`HttpContext.Current`.
- All cross-cutting service dependencies (`IEnvironmentService`, `ILogService`, `ISecurityApiClient`) are resolved via the per-request `IDependencyScope` service locator, not constructor injection — the hosting application's DI container must register concrete implementations, or dependent operations fail (`MissingDependencyException` for authorization; graceful degradation for logging/Splunk-URL resolution).*
- The library ships no `Web.config`/`app.config` `<appSettings>` of its own; the one directly-read app setting (`RequireSSLForLocal`) is read from the ambient application's configuration — no such application or supplying configuration exists in this repository.*
- No database access of any kind exists in this library — it is purely a Web API cross-cutting-concerns layer.
- `SAIF.Web.API` references `ErrorResponse`/`SAIF.API.Exceptions.*` by fully-qualified type name, but `SAIF.Web.API.csproj` expresses no `<ProjectReference>` or `<PackageReference>` that names their supplying project/package explicitly; whether the compile-time assembly is the sibling `SAIF.Web.API.Core` project or the `SAIF.Framework.Core` package is unresolved — see [Dependencies](dependencies.md).**
- `SaifAuthorizeAttribute` never calls `base.IsAuthorized`, so the base `AuthorizeAttribute`'s built-in authenticated-identity check is bypassed; an attribute applied with no roles authorizes every request, including unauthenticated ones.
- `RequireSSLAttribute` enforces HTTPS unconditionally for non-local requests; for local requests it is controlled by the ambient application's `RequireSSLForLocal` app setting — no such application or setting exists in this repository.* If the key is absent, or present but unparsable by `bool.TryParse`, `requireSSL` is set to `false` and local requests skip HTTPS enforcement — see [Configuration](configuration.md).

> **Note:** Statements marked with * were inferred from code structure, naming conventions, or
> contextual evidence where direct confirmation was not available in source artifacts. Statements
> marked with ** could not be confirmed; treat as unknown until verified.

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Dependencies](dependencies.md)
- [Configuration](configuration.md)
- [Operations and processes](operations-processes.md)
- [Business rules](business-rules.md)
- [Security and authorization](security-authorization.md)
- [API reference](api/index.md)

## Sources
- `src/SAIF.Web.API/ApiResponseHandler.cs`
- `src/SAIF.Web.API/ExceptionHandler.cs`
- `src/SAIF.Web.API/HttpRequestExtensions.cs`
- `src/SAIF.Web.API/RequireSSLAttribute.cs`
- `src/SAIF.Web.API/SaifAuthorizeAttribute.cs`
- `src/SAIF.Web.API/app.config`
- `src/SAIF.Web.API/SAIF.Web.API.csproj`
- `src/SAIF.Web.API.Core/ApiResponse.cs`
- `src/SAIF.Web.API.Core/BuildInfo.cs`
- `src/SAIF.Web.API.Core/ErrorResponse.cs`
- `src/SAIF.Web.API.Core/SAIFException.cs`
- `src/SAIF.Web.API.Core/SAIF.Web.API.Core.csproj`
- `src/SAIF.Web.API.sln`
