بنقرة واحدة
sdk-conventions
// Exact patterns generated code must follow to match the AWS SDK for .NET public API surface
// Exact patterns generated code must follow to match the AWS SDK for .NET public API surface
How to deserialize a Smithy model.json into typed C# records and navigate the shape graph
Rules for converting Smithy shape types to .NET types, including nullability and collection defaults
Use when creating, validating, or reasoning about DevConfig files for AWS SDK for .NET changes, including deciding whether Core or Services entries are required, choosing patch vs minor bumps, and writing changelog messages.
Use when working on the AWS SDK for .NET source code itself, including Core runtime changes, service client implementations, generator or model changes, repo-specific build and validation flows, and V3/V4 branch-targeting decisions.
| name | sdk-conventions |
| description | Exact patterns generated code must follow to match the AWS SDK for .NET public API surface |
Patterns the generated code must follow so its public API surface matches the existing AWS SDK for .NET. The generated files do NOT need to be byte-for-byte identical — whitespace, file naming (e.g. .g.cs suffix), internal implementation details, and code organization can differ as long as the public types, members, signatures, and attributes are equivalent.
[AWSProperty] attributes on public members (Required, Min, Max)partial modifier on all generated typesAmazon.{ServiceName}, Amazon.{ServiceName}.Model){TypeName}.g.cs to distinguish generated filesIsSet methods, backing fields, private helpers)using directive order#region blocks (purely cosmetic)The SDK builds with warnings-as-errors. Generated files must include #pragma warning disable for warnings that would otherwise break the build. The exact set doesn't need to match the current SDK file-for-file, but the output must compile cleanly. Common ones:
CS0612 / CS0618 — obsolete/deprecated member usage (generated code may reference deprecated shapes)CS1570 — malformed XML doc comments (common with complex HTML from @documentation traits)Every generated file starts with the full Apache 2.0 license block followed by a generation notice:
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/*
* Do not modify this file. This file is generated from the {model-filename} service model.
*/
The {model-filename} is the Smithy model file name (e.g. cloudtrail-data-2021-08-11.normal.json).
From the aws.api#service trait's sdkId value, using SdkNaming.NormalizeSdkId() in SmithyDotNet.Generator.Generation:
Examples: "CloudTrail Data" → "CloudTrailData", "AWS IoT 1-Click Projects" → "IoT1ClickProjects", "Amazon Pinpoint" → "Pinpoint"
Then prefix with Amazon. for namespace → Amazon.CloudTrailData
Model classes go in Amazon.{ServiceName}.Model.
eventData), .NET uses PascalCase (EventData)eventID → EventID (not EventId)IAmazon{ServiceName} (e.g. IAmazonCloudTrailData)Amazon{ServiceName}Client (e.g. AmazonCloudTrailDataClient)Amazon{ServiceName}ConfigAmazon{ServiceName}ExceptionAmazon{ServiceName}RequestGenerated files go under Generated/. Prefer .g.cs suffix:
Generated/
IAmazon{ServiceName}.g.cs
Amazon{ServiceName}Client.g.cs
Amazon{ServiceName}Config.g.cs # placeholder for now
Amazon{ServiceName}Exception.g.cs
Model/
Amazon{ServiceName}Request.g.cs # empty service request base
{OperationName}Request.g.cs
{OperationName}Response.g.cs
{ShapeName}.g.cs
{ExceptionName}.g.cs
| Generated class | Inherits from |
|---|---|
| Client interface | IAmazonService, IDisposable |
| Client class | AmazonServiceClient, IAmazon{ServiceName} |
| Service exception base | AmazonServiceException |
| Service request base | AmazonWebServiceRequest |
| Request classes | Amazon{ServiceName}Request (the service request base) |
| Response classes | AmazonWebServiceResponse |
| Structure classes | No base type (plain class) |
| Exception classes | Amazon{ServiceName}Exception (the service exception base) |
Config class (Amazon{ServiceName}Config) | ClientConfig (overrides are placeholder for now) |
Amazon{ServiceName}Exception — service-level exception base. Same 6-constructor pattern as operation exceptions, plus #if !NETSTANDARD serialization constructor. Inherits from AmazonServiceException.Amazon{ServiceName}Request — empty class extending AmazonWebServiceRequest. All operation request classes inherit from this, not directly from AmazonWebServiceRequest.Amazon{ServiceName}Config — placeholder for now. Will extend ClientConfig with ServiceId, ServiceVersion, AuthenticationServiceName, etc.partialEvery generated class and interface uses the partial modifier.
The public surface must match. Internal implementation can vary.
Required public surface:
/// <summary>
/// Gets and sets the property EventData.
/// <para>
/// The content of an audit event...
/// </para>
/// </summary>
[AWSProperty(Required=true)]
public string EventData { get; set; }
The current SDK uses explicit backing fields + IsSet methods internally. The generator can use auto-properties or backing fields — only the public signature matters.
[AWSProperty] attribute rules:
Required=true when member has @required traitMin=N when member has @length trait with min, or @range trait with minMax=N when member has @length trait with max, or @range trait with maxCollections default to null (SDK V4 convention):
public List<AuditEvent> AuditEvents { get; set; }
The current SDK uses AWSConfigs.InitializeCollections for backwards compatibility. The generator should match this behavior for AWS SDK use, but the internal mechanism can differ.
When implementing transformation logic (HTML sanitization, naming rules, type mapping, etc.), consult the existing C2J generator at generator/ServiceClientGeneratorLib/ to understand the correct behavior. Key files:
GeneratorHelpers.cs / Utils.cs — HTML processing, naming transformsMember.cs — property naming, type resolutionShape.cs / ExceptionShape.cs — shape naming conventionsGenerators/Marshallers/*.tt — T4 templates showing exact output patternsThe new generator is a clean reimplementation, not a port — but the existing generator defines what "correct" looks like.
The @documentation trait contains HTML. Transform before writing to XML doc comments:
<p>...</p> → <para>...</para><code>...</code> → <c>...</c><i>...</i> → keep as-is& → &)Service interface/class:
/// <summary>
/// <para>Interface for accessing CloudTrailData</para>
///
/// {service @documentation}
/// </summary>
Request class:
/// <summary>
/// Container for the parameters to the {OperationName} operation.
/// {operation @documentation}
/// </summary>
Response class:
/// <summary>
/// This is the response object from the {OperationName} operation.
/// </summary>
Structure class:
/// <summary>
/// {@documentation from the shape}
/// </summary>
Include <exception cref> for each error and a <seealso> link:
/// <exception cref="Amazon.CloudTrailData.Model.ChannelNotFoundException">
/// The channel could not be found.
/// </exception>
/// <seealso href="http://docs.aws.amazon.com/goto/WebAPI/{serviceId}-{apiVersion}/{OperationName}">REST API Reference for {OperationName} Operation</seealso>
Operation exceptions inherit from Amazon{ServiceName}Exception (not directly from AmazonServiceException).
Must expose these public constructors:
(string message)(string message, Exception innerException)(Exception innerException)(string message, Exception innerException, ErrorType, string errorCode, string requestId, HttpStatusCode)(string message, ErrorType, string errorCode, string requestId, HttpStatusCode)Operation exceptions also include a #if !NETSTANDARD block containing:
[Serializable] attribute on the classprotected serialization constructor (SerializationInfo, StreamingContext) — deserializes any additional exception members via info.GetValue for each property, then calls base(info, context)public override void GetObjectData(SerializationInfo, StreamingContext) with all three attributes (always emitted together as a unit from ExceptionSerialization.t4):
[System.Security.SecurityCritical]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2134:MethodsMustOverrideWithConsistentTransparencyFxCopRule")]
public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
{
base.GetObjectData(info, context);
// info.AddValue(...) for each additional exception member
}
The serialization constructor and GetObjectData are symmetric: both loop over the exception's members (from ExceptionSerialization.t4). For exceptions with additional properties, the constructor calls info.GetValue for each and GetObjectData calls info.AddValue for each. For exceptions with no extra members (e.g. all CloudTrail Data exceptions after filtering message), both bodies contain only the base call.The service-level exception base (Amazon{ServiceName}Exception) inherits from AmazonServiceException and includes [Serializable] plus the protected serialization constructor, but does not need its own GetObjectData override unless it adds serialized fields.
Must expose:
{Op}Response {Op}({Op}Request request) per operationTask<{Op}Response> {Op}Async({Op}Request request, CancellationToken cancellationToken = default)Endpoint DetermineServiceOperationEndpoint(AmazonWebServiceRequest request)#if NET8_0_OR_GREATER): CreateDefaultClientConfig() and CreateDefaultServiceClient(AWSCredentials, ClientConfig)Use #if directives to include sync methods only for .NET Framework targets (#if NETFRAMEWORK).
Must expose:
public virtual {Op}Response {Op}({Op}Request request) per operationpublic virtual Task<{Op}Response> {Op}Async(...) per operationDetermineServiceOperationEndpoint implementationCustomizeRuntimePipeline overrideServiceMetadata property overrideUse #if NETFRAMEWORK directives to include sync methods only for .NET Framework targets. Both sync and async methods are public virtual on the client class.