eng/packages/http-client-csharp-mgmt/docs/OperationContext.md
The Operation Context system is a core component of the Azure Management SDK generator that determines which parameters for an operation can be derived contextually from the identifier (Id) of the operation's carrier (resource, resource collection, or mockable resource) and which must be supplied by the caller.
When generating methods for Azure management operations, the generator needs to understand:
Id property (e.g., subscriptionId, resourceGroupName, parent resource names)This document explains how the system works in detail.
The contextual path is the request path pattern that defines the identity of a resource or resource collection. It represents "where you are" in the Azure resource hierarchy.
Example:
/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{vmName}
This path identifies a specific virtual machine resource. The parameters in this path (subscriptionId, resourceGroupName, vmName) can be derived from the resource's Id property.
The operation path is the request path for a specific API operation being invoked on the resource.
Example:
/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{vmName}/extensions/{extensionName}
This operation gets a specific extension for a virtual machine. Some parameters match the contextual path, while extensionName is new and must be provided by the caller.
A contextual parameter represents a parameter whose value can be derived contextually, either from:
Id property (e.g., subscriptionId, resourceGroupName, parent resource names)It contains:
virtualMachines)vmName)Id (e.g., Id.Name, Id.Parent.Name, Id.SubscriptionId) or from a fieldA parameter context mapping links an operation parameter name to its contextual source (if available). For each parameter in the operation path, it indicates:
ContextualParameterContextualParameter is null (indicating a pass-through parameter)When a resource or resource collection is created, the system analyzes its contextual path and builds a list of ContextualParameter objects by walking up the path hierarchy.
Example for VM Resource:
Path: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{vmName}
Contextual Parameters:
1. Key: "subscriptions", Variable: "subscriptionId" → Id.SubscriptionId
2. Key: "resourceGroups", Variable: "resourceGroupName" → Id.ResourceGroupName
3. Key: "virtualMachines", Variable: "vmName" → Id.Name
An OperationContext is created for each resource or resource collection. It encapsulates:
When generating a method for an operation, the system calls BuildParameterMapping(operationPath) to create a ParameterContextRegistry.
Common Scenario - Parameter Name Mismatch:
A common use case is when the operation path uses a different parameter name than the contextual path for the same logical parameter.
For example:
/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Example/resources/{resourceName}/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Example/resources/{name}/childResourcesThe operation path uses {name} while the contextual path uses {resourceName}. A naive name-based matching would fail to recognize these as the same parameter.
The Solution:
The parameter mapping process:
This position-based matching correctly identifies that {name} at the same position as {resourceName} represents the same logical parameter.
Example:
Contextual Path: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{vmName}
Operation Path: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{vmName}/extensions/{extensionName}
Shared segments: 8 (all segments up to and including {vmName})
Parameter Mappings:
- subscriptionId → Contextual (Id.SubscriptionId) [position 1]
- resourceGroupName → Contextual (Id.ResourceGroupName) [position 3]
- vmName → Contextual (Id.Name) [position 7]
- extensionName → Pass-through (must be provided by caller) [position 9, beyond shared area]
The OperationMethodParameterHelper uses the parameter mapping to filter out contextual parameters from the method signature:
// Without parameter filtering (incorrect):
GetExtensionsAsync(string subscriptionId, string resourceGroupName, string vmName, string extensionName, ...)
// With parameter filtering (correct):
GetExtensionsAsync(string extensionName, CancellationToken cancellationToken = default)
The contextual parameters are automatically supplied from Id when invoking the REST API.
When building the method body, ParameterContextRegistry.PopulateArguments() generates the argument list for the REST client call:
// Generated code:
_restClient.GetExtensions(
Id.SubscriptionId, // from contextual parameter
Id.ResourceGroupName, // from contextual parameter
Id.Name, // from contextual parameter (vmName)
extensionName, // from method parameter
context
);
Some resource collections require multiple parameters from their parent context. For example, a resource might be identified by both a location and a name rather than just a name.
In these cases:
GetAll/list operation)The OperationContext handles this by building two sets of contextual parameters and merging them appropriately when mapping operation parameters.
Extension resources have a flexible scope (can extend any resource). Their contextual path starts with a single variable segment:
/{resourceUri}/providers/Microsoft.Example/extensions/{extensionName}
The system handles these specially, treating resourceUri as a contextual parameter derived from the parent resource's Id.
Singleton resources have a fixed name (e.g., /placementScores/spot). The constant name segment increases the parent layer count so that parameters are extracted from the correct level in the Id hierarchy.
The Operation Context system is a sophisticated parameter resolution mechanism that:
This ensures generated SDKs are both ergonomic and correct, handling complex real-world scenarios while maintaining a simple programming model for SDK users.