Skip to content

API Library Template

The ConnectSoft API Library Template is a comprehensive framework for creating robust, reusable, and scalable service agent libraries in .NET Core. Designed for modern cloud-native and enterprise architectures, this template provides developers with all the tools needed to streamline the development of API integrations, ensure code quality, and adhere to industry best practices.

Overview

The API Library Template generates a production-ready foundation for building API service agent libraries that can be shared across projects, published as NuGet packages, and integrated into larger solutions. It follows Microsoft's .NET library design guidelines and incorporates best practices for HTTP client management, resiliency, authentication, and observability.

When to Use This Template

Use the API Library Template when:

  • Creating service agent libraries for external API integrations
  • Building SDKs for third-party services (e.g., Google Analytics, Stripe, AWS)
  • Developing libraries for internal microservice communication
  • Creating tenant-aware libraries for SaaS platforms
  • Building libraries that require multiple authentication mechanisms
  • Developing libraries that need advanced resiliency patterns
  • Publishing API client libraries as NuGet packages with CI/CD automation

When to Use Library Template Instead

Use the Library Template when:

  • Building general-purpose utility libraries without HTTP client needs
  • Creating domain model or business logic libraries
  • Developing libraries that don't interact with external APIs
  • Building simple libraries without authentication or resiliency requirements

Key Features

Typed HTTP Client

  • HttpClientFactory Integration: Optimized connection pooling, DNS updates, and lifecycle management
  • Strongly-Typed Interfaces: Predictable API interactions with type safety
  • Connection Pooling: Efficient resource management and reuse
  • Proxy Support: Configurable web proxy for HTTP requests

Authentication Mechanisms

  • None: Public APIs without authentication
  • Basic Authentication: Username/password with Base64 encoding
  • API Key: Header-based API key authentication
  • OAuth2: Token-based authentication with client credentials flow
  • OpenID Connect: Identity provider integration with token validation

Resiliency Patterns

  • Standard Resilience Handler: Retry, circuit breaker, timeout, bulkhead, rate limiter
  • Standard Hedging Handler: Parallel request execution for slow dependencies
  • Polly Integration: Advanced resilience patterns via Polly.Core
  • Chaos Injection: Fault and latency injection for testing resiliency

Metrics and Observability

  • OpenTelemetry Metrics: Custom metrics implementation
  • Request Tracking: Counters and histograms for API calls
  • Failure Monitoring: Error tracking by status code
  • Performance Metrics: Request duration and throughput

Testing Support

  • Mock Server: WireMock.Net integration for API simulation
  • Unit Tests: MSTest-based unit testing
  • Integration Tests: End-to-end testing capabilities
  • Chaos Testing: Resiliency validation under failure conditions

Generated Structure

The template generates a complete solution with the following structure:

YourApiLibraryName/
├── src/
│   └── YourApiLibraryName/
│       ├── I{ServiceName}Service.cs          # Service interface
│       ├── {ServiceName}Service.cs            # Service implementation
│       ├── {ServiceName}ServiceException.cs  # Custom exception class
│       ├── {ServiceName}ServiceExtensions.cs # DI extension methods
│       ├── {ServiceName}Response.cs          # Response DTO (example)
│       ├── {ServiceName}Result.cs            # Result wrapper (example)
│       ├── {ServiceName}Error.cs              # Error DTO (example)
│       ├── GlobalSuppressions.cs             # Code analysis suppressions
│       ├── Options/
│       │   ├── {ServiceName}ServiceOptions.cs           # Main options class
│       │   ├── Validate{ServiceName}ServiceOptions.cs  # Options validator
│       │   ├── WebProxyOptions.cs                       # Proxy configuration
│       │   ├── ChaosInjectionOptions.cs                 # Chaos testing options
│       │   ├── BasicAuthenticationOptions.cs            # (if Basic auth selected)
│       │   └── ApiKeyAuthenticationOptions.cs           # (if ApiKey auth selected)
│       ├── Metrics/                                    # (if UseMetrics=true)
│       │   └── {ServiceName}ServiceMetrics.cs          # Metrics implementation
│       └── {ServiceName}Service.xml                    # XML documentation
├── tests/
│   └── YourApiLibraryName.UnitTests/
│       ├── {ServiceName}ServiceUnitTests.cs            # Standard unit tests
│       ├── {ServiceName}ServiceWithMockedServerUnitTests.cs  # WireMock tests
│       ├── {ServiceName}ResultAssertionExtensions.cs   # Test helpers
│       ├── Metrics/                                    # (if UseMetrics=true)
│       │   └── {ServiceName}ServiceMetricsUnitTests.cs
│       ├── appsettings.UnitTests.json                  # Test configuration
│       ├── appsettings.MockedServerUnitTests.json      # Mock server config
│       ├── GlobalSuppressions.cs                        # Test suppressions
│       └── {ProjectName}.UnitTests.xml                  # Test XML docs
├── Docs/                                                # MkDocs documentation
│   ├── Index.md
│   ├── Overview.md
│   ├── GettingStarted.md
│   ├── Installation.md
│   ├── Configuration.md
│   ├── Authentication.md
│   ├── Features.md
│   ├── Testing.md
│   ├── API Reference.md
│   └── Roadmap.md
├── .template.config/                                    # Template metadata (excluded)
├── azure-pipelines.yml                                  # CI/CD pipeline
├── azure-pipelines-template.yml                         # Pipeline template
├── Directory.build.props                                # Shared MSBuild properties
├── Directory.Packages.props                             # Central package management
├── ConnectSoft.ApiLibraryTemplate.nuspec                # NuGet package spec
├── ConnectSoft.ApiLibraryTemplate.runsettings           # Test run settings
├── mkdocs.yml                                           # MkDocs configuration
├── nuget.config                                         # NuGet feed configuration
├── YourApiLibraryName.slnx                              # Modern solution file
├── YourApiLibraryName.sln                               # Traditional solution file
└── README.md                                            # Project README

Key Structure Details

Source Project Structure

  • Service Files: Core service interface and implementation following the service agent pattern
  • Options Folder: Contains strongly-typed configuration classes with validation
  • Main options class includes resilience, proxy, and authentication settings
  • Authentication options are conditionally included based on AuthenticationType
  • Metrics Folder (conditional): Only included when UseMetrics=true
  • Contains metrics implementation using Microsoft.Extensions.Diagnostics
  • Tracks request counts, durations, and failures

Test Project Structure

  • Unit Tests: Standard unit tests using MSTest framework
  • Mocked Server Tests: Integration tests using WireMock.Net for API simulation
  • Test Configuration: Separate appsettings files for different test scenarios
  • Metrics Tests (conditional): Only included when UseMetrics=true

Documentation Structure

The template includes a complete MkDocs documentation structure with: - Getting started guides - Configuration documentation - Authentication setup guides - Feature documentation - API reference templates - Testing guides

Build and Configuration Files

  • Directory.build.props: Shared MSBuild properties including code analyzers
  • Directory.Packages.props: Central package version management
  • azure-pipelines.yml: Ready-to-use CI/CD pipeline for Azure DevOps
  • mkdocs.yml: Documentation site configuration

Template Parameters

Parameter Type Required Default CLI Long Name CLI Short Name Description
ApiServiceName string Yes ExchangeRate --api-service-name --api-srv-name Service name used in code (e.g., ExchangeRate). This value replaces ExchangeRate in file names and code.
ApiServiceDescription string Yes Exchange rate --api-service-description --api-srv-desc A short human-readable description of the API being wrapped.
AuthenticationType choice No None --authentication-type --auth-type Choose the type of authentication used by the target API. Options: None, Basic, OAuth, OpenIDConnect, ApiKey.
UseMetrics bool No true --use-metrics --metrics Enable built-in metrics support for custom metrics. When false, the Metrics folder and related code are excluded.
Framework choice No net8.0 --framework N/A The target framework for the project. Options: net8.0, net9.0.
buildDefinitionNumber string No "" (empty) --build-definition-number --bdn Custom Azure DevOps build definition number for CI/CD integration. Leave empty to use default. Replaces buildDefinitionNumber placeholder in README.md.

CLI Usage

The template can be instantiated using the .NET CLI with various parameter formats. All parameters support both long names (kebab-case) and short names (aliases).

Basic Usage

dotnet new connectsoft-api-library \
  --name ConnectSoft.GoogleAnalytics \
  --api-service-name "GoogleAnalytics" \
  --api-service-description "Google Analytics Measurement Protocol API" \
  --authentication-type "ApiKey"

Using Short Names

dotnet new connectsoft-api-library \
  --name ConnectSoft.GoogleAnalytics \
  --api-srv-name "GoogleAnalytics" \
  --api-srv-desc "Google Analytics Measurement Protocol API" \
  --auth-type "ApiKey"

Framework Selection

# Target .NET 8.0 (default)
dotnet new connectsoft-api-library \
  --name ConnectSoft.MyService \
  --api-service-name "MyService" \
  --api-service-description "My Service API" \
  --framework net8.0

# Target .NET 9.0
dotnet new connectsoft-api-library \
  --name ConnectSoft.MyService \
  --api-service-name "MyService" \
  --api-service-description "My Service API" \
  --framework net9.0

With Azure DevOps Build Definition

dotnet new connectsoft-api-library \
  --name ConnectSoft.MyService \
  --api-service-name "MyService" \
  --api-service-description "My Service API" \
  --authentication-type "OAuth" \
  --build-definition-number "123"

Disabling Metrics

dotnet new connectsoft-api-library \
  --name ConnectSoft.MyService \
  --api-service-name "MyService" \
  --api-service-description "My Service API" \
  --use-metrics false

Complete Example with All Parameters

dotnet new connectsoft-api-library \
  --name ConnectSoft.StripeIntegration \
  --api-service-name "Stripe" \
  --api-service-description "Stripe Payment Processing API" \
  --authentication-type "ApiKey" \
  --use-metrics true \
  --framework net9.0 \
  --build-definition-number "456"

Template Symbols and Replacements

The template uses several mechanisms to customize the generated code based on your parameters.

Source Name Replacement

The template's source name ConnectSoft.ApiLibraryTemplate is automatically replaced with your project name (specified via --name parameter). This affects:

  • Solution file names: ConnectSoft.ApiLibraryTemplate.slnYourProjectName.sln
  • Project folder names: src/ConnectSoft.ApiLibraryTemplate/src/YourProjectName/
  • Namespace names throughout the codebase
  • Assembly names and package references

Service Name Replacement

The service name placeholder ExchangeRate is replaced with your ApiServiceName parameter value. This affects:

  • File names: ExchangeRateService.cs{ApiServiceName}Service.cs
  • Class names: ExchangeRateService{ApiServiceName}Service
  • Interface names: IExchangeRateServiceI{ApiServiceName}Service
  • Options class names: ExchangeRateServiceOptions{ApiServiceName}ServiceOptions
  • Extension method names: AddExchangeRateService()Add{ApiServiceName}Service()
  • Configuration section names: ExchangeRateService{ApiServiceName}Service
  • Comments and documentation: All references to "Exchange rate" are replaced with your ApiServiceDescription

Generated Symbols

The template includes several generated symbols that are automatically replaced:

Symbol Type Replacement Value Purpose
currentYear Generated Current year (e.g., 2024) Copyright year in file headers
IfDebug Generated #if DEBUG Conditional compilation directive start
ElseDirective Generated #else Conditional compilation directive else
EndIf Generated #endif Conditional compilation directive end
AuthoringMode Generated false Used during template development to include all conditional code

Computed Symbols

Computed symbols are derived from parameter values and control conditional compilation:

Symbol Condition Purpose
AuthenticationTypeNone AuthenticationType == "None" Controls authentication-related code
UseBasicAuthenticationType AuthenticationType == "Basic" Includes BasicAuthenticationOptions.cs
UseOAuthAuthenticationType AuthenticationType == "OAuth" Includes OAuth2 authentication code
UseOpenIDConnectAuthenticationType AuthenticationType == "OpenIDConnect" Includes OpenID Connect authentication code
UseApiKeyAuthenticationType AuthenticationType == "ApiKey" Includes ApiKeyAuthenticationOptions.cs

These symbols are used in conditional compilation directives like #if UseMetrics and control which files are included in the generated project.

Conditional Features

The template uses conditional logic to include or exclude features based on your parameter selections. This ensures the generated code only contains what you need.

Authentication Type-Based File Exclusion

Based on the AuthenticationType parameter, specific authentication option files are excluded:

  • When AuthenticationType != "Basic": BasicAuthenticationOptions.cs is excluded
  • When AuthenticationType != "ApiKey": ApiKeyAuthenticationOptions.cs is excluded
  • When AuthenticationType == "None": All authentication option files are excluded
  • When AuthenticationType == "OAuth" or "OpenIDConnect": OAuth2 authentication code is included via ConnectSoft.Extensions.Http.OAuth2 package

Metrics Feature Conditional Inclusion

When UseMetrics is set to false:

  • The entire Metrics/ folder is excluded from the source project
  • The Metrics/ folder is excluded from the test project
  • All metrics-related code is excluded via conditional compilation (#if UseMetrics)
  • The Microsoft.Extensions.Diagnostics package reference is excluded
  • Extension methods like Add{ServiceName}Metrics() are not generated

When UseMetrics is true (default):

  • Metrics classes are generated in src/{ProjectName}/Metrics/
  • Metrics unit tests are generated in tests/{ProjectName}.UnitTests/Metrics/
  • Service classes include metrics tracking code
  • Metrics extension methods are available for dependency injection

Conditional Compilation Directives

The template uses C# preprocessor directives to conditionally compile code:

#if UseMetrics
using {ProjectName}.Metrics;
#endif

public class {ServiceName}Service
{
#if UseMetrics
    private readonly {ServiceName}ServiceMetrics metrics;
#endif

    public {ServiceName}Service(
        HttpClient httpClient,
        ILogger<{ServiceName}Service> logger,
#if UseMetrics
        {ServiceName}ServiceMetrics metrics,
#endif
        IOptions<{ServiceName}ServiceOptions> options)
    {
        // ...
    }
}

Authoring Mode

The template includes an AuthoringMode symbol that is set to false by default. When developing or testing the template itself, you can enable AuthoringMode to include all conditional code paths simultaneously. This is useful for:

  • Template development and testing
  • Ensuring all code paths compile correctly
  • Validating template structure

In AuthoringMode, all authentication types and metrics are included, allowing template authors to verify the complete template structure.

Solution Format Support

The template generates both modern .slnx (XML-based) and traditional .sln solution formats to ensure compatibility across different development environments.

Primary Format: .slnx

The template uses .slnx as the primary solution format. This modern XML-based format offers:

  • Improved IDE Performance: Faster solution loading and better IntelliSense performance
  • Better Build Performance: Faster builds with improved caching
  • Modern Tooling: Better support in Visual Studio 2022 17.14+ and JetBrains Rider

Requirements for .slnx support: - .NET SDK 9.0.200 or later - Visual Studio 2022 17.14 or later (for full IDE support) - JetBrains Rider (current versions support .slnx)

Fallback Format: .sln

The template also generates a traditional .sln file for compatibility:

  • Use when working with older IDEs or tools
  • Required for VS Code (unless configured for .slnx)
  • Compatible with all .NET SDK versions
  • All functionality remains the same

IDE Support

IDE .slnx Support .sln Support Notes
Visual Studio 2022 17.14+ ✅ Full ✅ Full Prefer .slnx for best performance
Visual Studio 2022 < 17.14 ❌ No ✅ Full Use .sln file
JetBrains Rider ✅ Full ✅ Full .slnx recommended
VS Code ⚠️ Configurable ✅ Full Configure dotnet.defaultSolution setting

VS Code Configuration

To use .slnx in VS Code, add this to your workspace settings:

{
  "dotnet.defaultSolution": "YourProjectName.slnx"
}

Command Line Usage

Both solution formats work with standard .NET CLI commands:

# Restore packages
dotnet restore YourProjectName.slnx  # or .sln

# Build solution
dotnet build YourProjectName.slnx -c Release

# Run tests
dotnet test YourProjectName.slnx --no-build

Configuration Options

The template implements the .NET Options pattern with comprehensive validation and strongly-typed configuration.

Options Pattern Implementation

The template generates a main options class {ServiceName}ServiceOptions that includes:

  • Base URL: The API endpoint base address
  • Default Timeout: Request timeout duration (1 second to 5 minutes)
  • Web Proxy: Configurable proxy settings for HTTP requests
  • Resilience Options: Configuration for retry, circuit breaker, and timeout strategies
  • Standard Resilience Handler options
  • Standard Hedging Handler options
  • Chaos Injection: Options for fault and latency injection during testing
  • Authentication Options: Type-specific authentication configuration (conditionally included)

Configuration Section Naming

The options class defines a constant for the configuration section name:

public const string {ServiceName}ServiceOptionsSectionName = "{ServiceName}Service";

This means your appsettings.json should have a section named {ServiceName}Service:

{
  "{ServiceName}Service": {
    "BaseUrl": "https://api.example.com",
    "DefaultTimeout": "00:00:30",
    "EnableHttpStandardResilience": true,
    "HttpStandardResilience": {
      // Resilience configuration
    },
    "ApiKeyAuthentication": {
      "ApiKey": "your-api-key",
      "HeaderName": "X-API-Key"
    }
  }
}

Validation

The template implements comprehensive validation using:

  1. Data Annotations: Required fields, data types, and ranges are validated
  2. Custom Validator: Validate{ServiceName}ServiceOptions class implements IValidateOptions<T>
  3. Startup Validation: Options are validated when the application starts via ValidateOnStart()
  4. Object Member Validation: Nested options are validated using ValidateObjectMembers

Example validation attributes:

[Required]
[DataType(DataType.Url)]
required public string BaseUrl { get; set; }

[Required]
[Range(typeof(TimeSpan), "00:00:01", "00:05:00")]
required public TimeSpan DefaultTimeout { get; set; }

Service Registration Extension Methods

The template generates extension methods for easy dependency injection setup:

1. Add Options

services.Add{ServiceName}Options(configuration);

This method: - Binds configuration to the options class - Validates data annotations - Registers the custom validator - Validates options at startup - Throws OptionsValidationException if validation fails

2. Add Metrics (if UseMetrics=true)

services.Add{ServiceName}Metrics();

This method: - Adds metrics infrastructure - Registers the metrics implementation as a singleton

3. Add Service

services.Add{ServiceName}Service();

This method: - Registers the service as a typed HTTP client - Configures the HTTP client with base URL and timeout - Sets up authentication headers (based on authentication type) - Configures resilience handlers (if enabled) - Sets up chaos injection (if enabled) - Configures connection pooling and proxy settings

Important: You must call Add{ServiceName}Options() before Add{ServiceName}Service().

Complete Registration Example

// In Program.cs or Startup.cs
var builder = WebApplication.CreateBuilder(args);

// Step 1: Add and validate options
builder.Services.AddGoogleAnalyticsOptions(builder.Configuration);

// Step 2: Add metrics (if enabled)
builder.Services.AddGoogleAnalyticsMetrics();

// Step 3: Add the service
builder.Services.AddGoogleAnalyticsService();

var app = builder.Build();

Configuration Binding

The template uses BindConfiguration() with strict error handling:

.BindConfiguration(optionsPath, options =>
{
    options.ErrorOnUnknownConfiguration = true;
})

This ensures that: - Unknown configuration keys cause errors (helping catch typos) - Configuration is strongly-typed - Type mismatches are caught early

Quick Start

Step 1: Create a New API Library

Create a new API library using the template with all recommended parameters:

dotnet new connectsoft-api-library \
  --name ConnectSoft.GoogleAnalytics \
  --api-service-name "GoogleAnalytics" \
  --api-service-description "Google Analytics Measurement Protocol API" \
  --authentication-type "ApiKey" \
  --use-metrics true \
  --framework net9.0 \
  --build-definition-number "123"

Parameter explanations: - --name: The project/solution name (replaces ConnectSoft.ApiLibraryTemplate) - --api-service-name: Service name used in code (replaces ExchangeRate in file names and classes) - --api-service-description: Human-readable description for documentation - --authentication-type: Choose None, Basic, OAuth, OpenIDConnect, or ApiKey - --use-metrics: Enable metrics support (set to false to exclude metrics) - --framework: Target framework (net8.0 or net9.0) - --build-definition-number: Azure DevOps build definition ID (optional, for CI/CD badges)

Step 2: Configure the Library

Update appsettings.json with your API configuration. The configuration section name matches your service name:

{
  "GoogleAnalyticsService": {
    "BaseUrl": "https://www.google-analytics.com",
    "DefaultTimeout": "00:00:30",
    "EnableHttpStandardResilience": true,
    "HttpStandardResilience": {
      "Retry": {
        "MaxRetryAttempts": 3,
        "BackoffType": "ExponentialWithJitter"
      },
      "CircuitBreaker": {
        "FailureRatio": 0.5,
        "MinimumThroughput": 10
      }
    },
    "EnableHttpStandardHedgingResilience": false,
    "EnableChaosInjection": false,
    "WebProxy": {
      "UseProxy": false
    },
    "ApiKeyAuthentication": {
      "ApiKey": "your-api-key-here",
      "HeaderName": "X-API-Key"
    }
  }
}

Step 3: Register Services

Register the service and options in your Program.cs or Startup.cs:

using ConnectSoft.GoogleAnalytics;

var builder = WebApplication.CreateBuilder(args);

// Step 1: Add and validate options (required first)
builder.Services.AddGoogleAnalyticsOptions(builder.Configuration);

// Step 2: Add metrics (if UseMetrics=true was used)
builder.Services.AddGoogleAnalyticsMetrics();

// Step 3: Add the service
builder.Services.AddGoogleAnalyticsService();

var app = builder.Build();

Important: Always call Add{ServiceName}Options() before Add{ServiceName}Service().

Step 4: Use the Service

Inject and use the service in your controllers or services:

using ConnectSoft.GoogleAnalytics;

public class AnalyticsController : ControllerBase
{
    private readonly IGoogleAnalyticsService _service;

    public AnalyticsController(IGoogleAnalyticsService service)
    {
        _service = service;
    }

    [HttpPost("track")]
    public async Task<IActionResult> TrackEvent([FromBody] AnalyticsEvent evt)
    {
        var result = await _service.TrackEventAsync(evt);

        if (result.IsSuccess)
        {
            return Ok(result);
        }

        return BadRequest(result.Error);
    }
}

Alternative: Minimal Example

For a quick start with minimal configuration:

dotnet new connectsoft-api-library \
  --name ConnectSoft.MyService \
  --api-service-name "MyService" \
  --api-service-description "My Service API"

This uses defaults: - Authentication: None - Metrics: true - Framework: net8.0 - Build Definition: empty (uses default)

Architecture

Design Principles

  • Service Agent Pattern: Encapsulates API interaction logic
  • HttpClientFactory Pattern: Proper HTTP client lifecycle management
  • Options Pattern: Strongly-typed, validated configuration
  • Resilience First: Built-in fault tolerance mechanisms
  • Observability: Comprehensive logging, metrics, and tracing support

Integration with AI Factory

The API Library Template is used by:

  • API Library Generator Agent: Generates API library projects
  • Backend Developer Agent: Uses libraries in microservice development
  • Integration Agents: Creates libraries for external service integration