Skip to content

Architecture

This repository reaches SAIFFaxService through the generated FaxServiceSoapClient, wrapped by the authored FaxServiceProxy, which builds its own Windows-credentialed BasicHttpBinding and EndpointAddress in code rather than relying on the app.config endpoint.

Proxy mechanism

Aspect Finding
Mechanism Service Reference (svcutil)
Proxy type SAIF.Services.Web.Proxies.Fax.FaxServiceSoapClient (internal)
Base type System.ServiceModel.ClientBase<T>
Contract type internal interface FaxServiceSoap
Constructed in FaxService.SendFax constructor path (Services/SAIF.Services.WCF/Services/FaxService.cs:21-25, wrapper constructed with the resolved URL)
Binding configured in Code
Address supplied by Constructor argument (serviceUrl), itself sourced from EnvironmentConfigKeys.FaxSoapServiceUrl (faxSoapServiceUrl)

Architecture diagram

The following diagram visualizes how a call reaches the remote service.

flowchart TD
    CALLER["FaxService.SendFax"] --> WRAP["FaxServiceProxy<br>hand-written wrapper"]
    WRAP --> BIND["Binding constructed<br>BasicHttpBinding<br>TransportCredentialOnly, Windows"]
    BIND --> ADDR["EndpointAddress<br>from faxSoapServiceUrl setting"]
    ADDR --> PROXY["FaxServiceSoapClient<br>generated proxy"]
    PROXY --> REMOTE["Remote service<br>SAIFFaxService (ASMX)"]
    WRAP --> DISPOSE["Close only<br>no Abort on fault"]

Hand-written wrapper

Field Value
Type SAIF.Services.Web.Proxies.FaxServiceProxy
Source Services/SAIF.Services.Web.Proxies/FaxServiceProxy.cs
Visibility public
Implements IDisposable
Responsibility Validates the supplied service URL, constructs the generated FaxServiceSoapClient with a Windows-credentialed binding and an explicit address, and exposes SendFax
Proxy lifetime Per instance — constructed from OperationContext.Current in the FaxService constructor, so it is per-instance and not reused* (depends on the WCF service's undeclared InstanceContextMode)
Configuration applied Value Source
BasicHttpBinding security mode TransportCredentialOnly FaxServiceProxy.cs:18
Transport client credential HttpClientCredentialType.Windows FaxServiceProxy.cs:28
MaxReceivedMessageSize int.MaxValue FaxServiceProxy.cs:20
MaxBufferSize int.MaxValue FaxServiceProxy.cs:21
ReaderQuotas.MaxArrayLength int.MaxValue FaxServiceProxy.cs:22
Timeouts None set — binding defaults apply FaxServiceProxy.cs:18-28

The response message is empty, so the practical exposure of the unbounded quotas is small, but the setting is copied boilerplate rather than a deliberate choice for this operation — see Tech debt.

Endpoint resolution

Environment Address Resolved from Changeable without a rebuild
All (dev1, dev2, test1, test2, qa, prod) http://websvcprod/webservices/SAIFFaxService/faxservice.asmx Services/SAIF.Services.WebApi/EnvironmentApi/App_Data/environments.xml:16,35,54,73,91,109 Yes — the value is read from environments.xml at runtime, but every track currently points at the same production host

Three different hosts appear across the repository: the runtime value is websvcprod (environments.xml), the generation-time WSDL/disco/svcmap value is also websvcprod, and the unused app.config endpoint (Services/SAIF.Services.Web.Proxies/app.config:60) names api.saif.com. The disagreement is recorded as a finding with no reconciliation attempted.

Lifetime and disposal

Aspect Finding
Proxy lifetime Per instance* — see the wrapper table above
Disposal Dispose() calls webService.Close() (FaxServiceProxy.cs:57-65); there is no Abort() fallback
Faulted-channel handling Close() on a faulted ClientBase<T> throws CommunicationObjectFaultedException during dispose*
Thread safety Not determined from source

Integration points

System Type Purpose
SAIFFaxService SOAP service Delivers a fax document to a named recipient and fax number

Note: Statements marked with * were inferred from code structure or contextual evidence.

Sources

  • Services/SAIF.Services.Web.Proxies/FaxServiceProxy.cs
  • Services/SAIF.Services.WCF/Services/FaxService.cs
  • Services/SAIF.Services.Web.Proxies/app.config