Skip to main content

Improved .NET SDK Code Quality and Language Alignment

· 6 min read

Enhancements have been applied to improve code quality and align the generated .NET SDKs with established C# conventions and best practices. Updates include consistent naming, reduced code noise, and elimination of unnecessary build-time warnings, resulting in cleaner and more maintainable SDKs.

Non-Breaking Changes

Removed and Organized Imports

Eliminated unused using directives across the generated SDKs to reduce noise, improve readability, and prevent unnecessary build-time warnings.
Additionally, all remaining imports are now sorted in alphabetical order, ensuring consistent and cleaner file structure.

Example from a Controller class

using APIMatic.Core;
using APIMatic.Core.Types;
using APIMatic.Core.Utilities;
using ServerSdk.Standard.Exceptions;
using ServerSdk.Standard.Http.Response;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

...

Improved Parameter Naming

Updated automatically generated parameter names to follow standard C# naming conventions (camelCase for parameters).
This enhances code clarity, reduces style violations, and aligns with common .NET coding guidelines.
Parameter naming has been enhanced across key areas, including client builders and Controller CreateApiCall lambda parameters, ensuring consistency throughout the SDK.

Example from a Controller class

public async Task<ApiResponse<Models.Order>> CreateOrderAsync(
Models.CreateOrderInput input,
CancellationToken cancellationToken = default)
=> await CreateApiCall<Models.Order>()
.RequestBuilder(requestBuilder => requestBuilder
.Setup(HttpMethod.Post, "/v2/checkout/orders")
.WithAuth("Oauth2")
.Parameters(parameters => parameters
.Body(b => b.Setup(input.Body))
.Header(header => header.Setup("Content-Type", "application/json"))
.Header(header => header.Setup("PayPal-Mock-Response", input.PaypalMockResponse))
.Header(header => header.Setup("PayPal-Request-Id", input.PaypalRequestId))
.Header(header => header.Setup("PayPal-Partner-Attribution-Id", input.PaypalPartnerAttributionId))
.Header(header => header.Setup("PayPal-Client-Metadata-Id", input.PaypalClientMetadataId))
.Header(header => header.Setup("Prefer", input.Prefer))
.Header(header => header.Setup("PayPal-Auth-Assertion", input.PaypalAuthAssertion))))
.ResponseHandler(responseHandler => responseHandler
.ErrorCase("400", CreateErrorCase("Request is not well-formed, syntactically incorrect, or violates schema.", (errorReason, context) => new ErrorException(errorReason, context)))
.ErrorCase("401", CreateErrorCase("Authentication failed due to missing authorization header, or invalid authentication credentials.", (errorReason, context) => new ErrorException(errorReason, context)))
.ErrorCase("422", CreateErrorCase("The requested action could not be performed, semantically incorrect, or failed business validation.", (errorReason, context) => new ErrorException(errorReason, context)))
.ErrorCase("0", CreateErrorCase("The error response.", (errorReason, context) => new ErrorException(errorReason, context))))
.ExecuteAsync(cancellationToken).ConfigureAwait(false);

Example from SDK Client Builder class

public class Builder
{
private Environment _environment = PaypalServerSdk.Standard.Environment.Sandbox;
private ClientCredentialsAuthModel _clientCredentialsAuthModel = new ClientCredentialsAuthModel();
private HttpClientConfiguration.Builder _httpClientConfig = new HttpClientConfiguration.Builder();
private HttpCallback _httpCallback;
private SdkLoggingConfiguration _sdkLoggingConfiguration;

...
}

Build-Time Warning Cleanup

A general cleanup pass has been applied across the generated SDKs to make the code more idiomatic and cleaner. These improvements provide a clearer development experience, streamline focus, and enhance long-term maintainability.

Refactored Utility Calls to Use CoreHelper Directly

builder.Environment(CoreHelper.JsonDeserialize<Environment>($"\"{environment}\""));

Added Explicit new to ToString in Derived Exception Classes

public class Error : ApiException
{
...

protected new void ToString(List<string> toStringOutput){ ... }
}

Breaking Changes (Opt-In)

These changes are currently opt-in and disabled by default. However, we strongly recommend that all teams enable these settings in their next SDK upgrade cycle, as they introduce enhanced capabilities and align the SDK more closely with .NET best practices.

Important Timeline:

  • Current Status: Opt-in via configuration flags (see below)
  • Future Default: These will become the default behaviour by May 2026
  • Opt-in Period: Available for at least 6 months to give teams time to evaluate their impact and incorporate these changes in the next SDK release.

Before enabling these settings:

  • Review the specific impacts outlined below for each setting
  • Regenerate your SDKs and review code changes to determine if your SDK is impacted by these changes.
  • In case of breaking changes, plan your next release accordingly.

These changes improve semantics, better align with .NET conventions, and provide long-term benefits for code maintainability and correctness.

CSharpSkipEqualityMethods

(default: false)

Disables automatic generation of Equals and GetHashCode for:

  • Models
  • OneOf/AnyOf cases
  • Webhooks and Callbacks ParsingResult

Impact

  • Prevents incorrect equality and hashing on mutable models, avoiding invalid comparisons or issues with hash-based collections
  • Equality falls back to reference comparison unless implemented manually
  • Value-based equality checks (Equals, ==, Dictionary, HashSet) may change

CSharpResolveExceptionPropertyCollisions

(default: false)

Resolves naming conflicts in generated exception models by postfixing properties instead of overriding System.Exception members.

Common conflicting properties include: Message, Source, StackTrace, InnerException, HelpLink, Data

Impact

  • Exception property names may change (e.g., MessageMessageProperty)
  • Existing code accessing original names may require updates
  • Prevents hiding base exception members and removes related compiler warnings

Why These Are Considered Breaking

Even though these settings are opt-in, enabling them can:

  • Change runtime behavior (e.g., equality semantics)
  • Modify the public API surface (e.g., exception property names)

Existing integrations may need adjustments to accommodate these changes.