Skip to content

Get Active Directory user data or access

ActiveDirectoryServiceProxy wraps the ActiveDirectory SOAP service to answer three independent AD questions — a user's default printer, a cached role-access decision, and a mapped contact record — without exposing the generated clsADServicesSoapClient to callers.

Field Value
Operation ID OP-WP-01
Trigger A caller request; no in-repository code constructs this wrapper
Inputs userId, role, useExternalDomain
Outputs A printer name, a boolean access decision, or a SAIF.Core.Contracts.Contact
Primary components ActiveDirectoryServiceProxy.GetDefaultPrinter, ActiveDirectoryServiceProxy.HasAccess, ActiveDirectoryServiceProxy.GetContact
Entry point Services/SAIF.Services.Web.Proxies/ActiveDirectoryServiceProxy.cs

Steps

  1. Construct ActiveDirectoryServiceProxy(serviceUrl): guard serviceUrl with Enforce.ArgumentNotNullOrEmpty (WP-BR-001), then build a default BasicHttpBinding client with no explicit security.
  2. On failure: an argument exception is thrown before any wire client is created.
  3. GetDefaultPrinter(userId): guard userId is not null or empty (WP-BR-001), then call the wire GetDefaultPrinter operation and return its result unchanged.
  4. HasAccess(userId, role, useExternalDomain): (WP-BR-002)
  5. If useExternalDomain is true: call wire HasAccessCacheExternal(userId, role).
  6. Otherwise: call wire HasAccessCache(userId, role).
  7. The boolean result is returned unchanged in both branches.
  8. GetContact(userId): call wire GetUserInfo(userId), then map the returned USERINFOSTRUCT fields to a SAIF.Core.Contracts.Contact: (WP-BR-003)
  9. Address/City/State/Zip become PrimaryAddress.
  10. FaxNumber becomes PrimaryFax.
  11. First/Last/Middle become Name.
  12. Telephone becomes PrimaryPhone.
  13. Email and Gender are copied directly.
  14. Every null field is coalesced to "".
  15. On failure: there is no null guard on userId, and a null userInfo returned by the wire call throws NullReferenceException.
  16. Dispose() calls webService.Close() on the generated client without an Abort() fallback on the fault path.

Process flow

The following diagram visualizes the three independent request paths through this wrapper.

flowchart TD
    Start([Caller invokes wrapper method]) --> Which{Which method?}
    Which -->|GetDefaultPrinter| GP[Guard userId] --> GPCall[Call wire GetDefaultPrinter] --> GPRet([Return printer name])
    Which -->|HasAccess| HA{useExternalDomain?}
    HA -->|Yes| HAExt[Call HasAccessCacheExternal] --> HARet([Return boolean])
    HA -->|No| HAInt[Call HasAccessCache] --> HARet
    Which -->|GetContact| GC[Call wire GetUserInfo] --> GCMap["Map USERINFOSTRUCT to Contact<br>(nulls become empty strings)"] --> GCRet([Return Contact])

Failure and edge-case behavior

  • A null or empty serviceUrl or userId (for GetDefaultPrinter) throws an argument exception before any wire call is made.
  • A null userInfo returned from GetUserInfo throws NullReferenceException in GetContact, because there is no null guard on the wire result.
  • Dispose() calling Close() without Abort() can itself throw if the underlying channel has faulted*.

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts.

Sources

  • Services/SAIF.Services.Web.Proxies/ActiveDirectoryServiceProxy.cs