# Client Matter — Execution flow

This page describes the step-by-step execution of ClientMatterInformationHandler.Execute(), the orchestrator that runs every time a Client Matter file is processed. Steps are numbered in execution order.

# 1. Input validation

If no CreateUpdateClientMatter object is present, execution stops immediately with a failure result.

# 2. Existing-matter lookup

When a MatterCode is present, the handler queries the MattersList to check whether this matter has been provisioned before. The query returns the matter's stored URL, site URL, and the ClientMatterDesign that was used to create it.

The result drives two decisions:

  • Design detection — if a design is stored in the MattersList entry (in the ClientMatterStructure column), it is applied to the current request before any other design resolution runs. This guarantees that updates always use the same structural design as the original provisioning.
  • New vs. existing distinction — see step 4 below.

If MatterCodeIsNotUnique is enabled in the configuration, matter codes are not globally unique — the same matter code can exist under different clients. In that case, the handler first queries the client list to obtain the client's list item ID, then uses the combination of that client ID and the matter code to find the correct matter entry in the MattersList.

# 3. MonitorDirectory routing

MonitorDirectory signals that the current service instance should not process this request locally — instead, it should forward the JSON file to a different service instance (one watching that directory) that owns the correct configuration for this matter.

Routing triggers under two conditions:

No MatterCode: If MatterCode is empty and MonitorDirectory is set, the handler clears the MonitorDirectory field, saves the JSON to that directory, and returns success. Since no code is present, the receiving instance handles code assignment and provisioning.

This path only applies to JSON requests; Excel rows always have a MatterCode.

MatterCode present: After the existing-matter lookup (step 2), if MonitorDirectory is set, the handler evaluates the matter's stored URL:

MattersList URL state Action
Not found (null) Calls ParseMatterStatus; if matter is Closed, stops with success — no point forwarding a closed matter that was never provisioned. Otherwise routes.
Empty string (no URL yet) Routes to MonitorDirectory.
Starts with http (already provisioned) Routes to MonitorDirectory — the receiving instance handles the update in the correct environment.
Non-HTTP local path (intermediate state) Routing is skipped. Execution continues locally on the current service instance.

When routing, the MonitorDirectory field is cleared from the request before saving, so the receiving instance processes it as a normal local request.

# 4. New vs. existing matter

The stored URL from the MattersList lookup (step 2) determines the processing path:

URL state Meaning Behaviour
null (not found) New matter Full provisioning path; config switching allowed
Empty string In MattersList but no URL yet Treated as new
Starts with http Already provisioned Update path; original SharepointCfg is kept
Other (local path) Intermediate state Local processing continues with current config

Update path: when a matter already has a provisioned URL, the SharepointCfg is locked to the one originally used (the one whose SharePoint environment contains the matter). Config switching (step 5) is skipped. This ensures updates always run against the original environment.

# 5. Configuration switching

If the request specifies a SharepointCfg name different from the current configuration, and the matter is new (not yet provisioned), the handler loads and clones that configuration and uses it for the rest of execution. This allows a single service instance to provision matters across multiple SharePoint environments based on per-matter input.

For existing (already-provisioned) matters, configuration switching is skipped — the original config is always kept so updates land in the correct environment.

# 6. Auto-numbering

If ClientCodeStartNumber is configured and no ClientCode was provided, the handler calls AutoNumber.GetNextID to assign the next available client code. The same applies to MatterCode when MatterCodeStartNumber is configured.

When either code is auto-assigned and the request was loaded from a JSON file, the file is overwritten with the assigned codes so the source file reflects what was actually used.

After this step, if both ClientCode and MatterCode are still empty, execution stops with a failure result.

See Auto-numbering for a full description of format strings, counter storage, and reset behaviour.

# 7. Dynamic ClientMatterStructure and URL resolution

Two values are resolved through the GetDynamicNameValue pipeline, which evaluates dynamic placeholders (tokens from the matter's properties) against the configuration:

  • ClientMatterStructure — resolves the matter structure/design name. If the resolved value matches a known ClientMatterDesign enum, it overrides the design for this execution.
  • ClientMatterServerRelativeUrl — resolves the root server-relative URL under which the matter site or library will be created.

Both values can be static strings or dynamic expressions referencing matter properties such as client code, matter type, or area of law.

After dynamic resolution, explicit overrides from the request are applied:

  • If ClientMatterDesign is set on the request, it overrides the configuration's design value.
  • If ServerRelativeUrl is set on the request, it overrides the resolved server-relative URL.

# 8. Matter status parsing

ParseMatterStatus reads the matter's status value from its properties and maps it to either Open or Closed using the configuration below. If the feature is not configured, the status remains unset and all operations proceed unconditionally.

Configuration property Description
SettingsCfg.Provisioning.MatterStatusColumnName Name of the column in the MattersList that holds the status value. Leave empty to disable status-based behaviour entirely.
SettingsCfg.Provisioning.MatterStatusOpenedValues Array of column values that mean the matter is open (e.g. ["Opened", "Geopend"]).
SettingsCfg.Provisioning.MatterStatusClosedValues Array of column values that mean the matter is closed (e.g. ["Closed", "Gesloten"]). At least one value must be configured here for status parsing to activate.

The status value is read from the matter's properties using MatterStatusColumnName. It is matched case-insensitively against MatterStatusClosedValues first, then MatterStatusOpenedValues. If no match is found the status remains unset.

The resolved status is used in two places:

  • Step 3 (MonitorDirectory routing): if a matter is not in the MattersList and is Closed, execution stops immediately — there is no point routing a matter that was already closed before it was ever provisioned.
  • Design handler execution (step 10): when a matter is Closed, design handlers set SkipIfNotExists = true on the matter list and site/library operations. This means a closed matter can only update structures that already exist — it cannot create new sites, libraries, or list items.

# 9. Design handler selection

The handler selects an IClientMatterDesignHandler based on ClientMatterDesign:

Design SharePoint structure
MatterSiteCollection Matter gets its own top-level site collection
MatterSite Matter is a sub-site within an existing site collection
MatterDocLib Matter is a document library within an existing site
ClientSiteCollection_MatterSite Client has its own site collection; matter is a sub-site within it
ClientSiteCollection_MatterDocLib Client has its own site collection; matter is a document library within it
ClientSite_MatterSite Client has a site (not a full site collection); matter is a sub-site within it
ClientSite_MatterDocLib Client has a site; matter is a document library within it
MatterOffice365Group Matter is a Microsoft 365 Group/Team (SharePoint Online only)

If no handler is found for the configured design, an exception is thrown.

# Round-robin URL selection

When SharepointRootServerRelativeUrl is configured as a semicolon-separated list of multiple URLs, the handler distributes matters across those URL prefixes using a round-robin algorithm (GetSharepointRootServerRelativeUrl). The algorithm counts existing sites under each URL and picks the one with the fewest matters, refreshing its counts when they become stale. Access is serialised per configuration to prevent two concurrent requests from selecting the same target URL.

# 10. Design handler execution

The selected design handler runs and returns an ActionResult. The handler flags (ClientCreated, MatterCreated, ClientListItemCreated, MatterListItemCreated) are propagated back to the caller after execution.

# 11. Post-success steps

The following steps run only when the design handler reports success.

# My Matters list

The matter's entry in the My Matters list is renamed if the matter name changed. The previous name is read from the MatterName column of the existing matter list item (falling back to Title with the code prefix stripped if MatterName is empty). The previous title is then stripped of any client name prefix before the rename to avoid double-prefixing (e.g. Acme - Contract reviewContract review).

See Matter list title columns for how MatterName, Title, and NormalizedTitle relate and how the title format is configured.

# Extranet integration

If an extranet is configured, ICreateUpdateExtranet builds a duplicate provisioning request targeting the extranet environment (adjusting codes, names, design, and URL), dispatches it to the correct service instance, and writes the assigned extranet matter code back into the original matter's list entry.

See Extranet integration for the full description of both extranet modes, column mapping, external dispatch, and all configuration properties.

# Client and matter URL write-back

The absolute URLs of the matter site and document library (URL, SiteURL, Epona365URL) are written back into the matter's properties so subsequent steps and list updates can use the final SharePoint addresses.

For designs with a client site or site collection, the client SiteURL is also written back.

# Master monitor directory (optional)

If SettingsCfg.Provisioning.MatterListMonitorDirectory is configured, the handler writes two JSON files to that directory:

  • ClientList_<ClientCode>.json — client properties for the master environment's client list
  • MatterList_<ClientCode>_<MatterCode>.json — matter properties for the master environment's matter list

This allows a secondary service instance (watching the master directory) to keep its own client/matter lists in sync after the matter is provisioned in the primary environment.

# Update default values (optional)

If SettingsCfg.Provisioning.UpdateDefaultValuesOnDocumentsMonitorDirectory is configured, the handler writes an AssignDefaultValuesInDocLib_<ClientCode>_<MatterCode>.json file to that directory. This triggers the Update Default Values job to apply the matter's metadata as default column values on all existing documents in the matter's document libraries.

If a file with identical content already exists at that path, the write is skipped to avoid unnecessary reprocessing.

# 12. Finally: post-handlers and lock release

Regardless of success or failure, the finally block runs:

  1. Post-handlers — all registered IClientMatterPostHandler implementations are invoked in sequence. Each receives the connection, the action result, and the CreateUpdateClientMatter object. Errors in individual post-handlers are caught and logged but do not affect the overall result.
  2. Lock release — concurrency locks held for the client code and the client/matter code pair are released, allowing any queued requests for the same matter to proceed.

# Client and matter identifiers

Each client and matter has two separate identifiers that serve different purposes.

ClientCode / MatterCode are the functional codes used throughout provisioning: SharePoint list lookups, site URL generation, filenames, log output, and concurrency lock keys.

ClientID / MatterID are external system identifiers supplied by the originating system (case management, ERP, etc.). They are stored in the ExternalID column of the client list and matter list respectively.

# Lookup priority

When CreateOrUpdateItem runs against a SharePoint list:

  1. If ClientID/MatterID is provided and the list has an ExternalID column — the list item is looked up by ExternalID. The Code column is still written but is not used for matching.
  2. Otherwise — the list item is looked up by Code (ClientCode/MatterCode).
  3. If Code is empty, ExternalID is used as the code value as a fallback.

This means a matter is found by its external system ID even if its code changes over time — as long as the ExternalID column exists in the list and the ID is supplied on each request.

Last Updated: 4/23/2026, 10:40:37 AM