Siemens.AspNet.MinimalApi.Sdk 0.1.0-alpha.130

Prefix Reserved
This is a prerelease version of Siemens.AspNet.MinimalApi.Sdk.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package Siemens.AspNet.MinimalApi.Sdk --version 0.1.0-alpha.130
                    
NuGet\Install-Package Siemens.AspNet.MinimalApi.Sdk -Version 0.1.0-alpha.130
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Siemens.AspNet.MinimalApi.Sdk" Version="0.1.0-alpha.130" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Siemens.AspNet.MinimalApi.Sdk" Version="0.1.0-alpha.130" />
                    
Directory.Packages.props
<PackageReference Include="Siemens.AspNet.MinimalApi.Sdk" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Siemens.AspNet.MinimalApi.Sdk --version 0.1.0-alpha.130
                    
#r "nuget: Siemens.AspNet.MinimalApi.Sdk, 0.1.0-alpha.130"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Siemens.AspNet.MinimalApi.Sdk@0.1.0-alpha.130
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Siemens.AspNet.MinimalApi.Sdk&version=0.1.0-alpha.130&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Siemens.AspNet.MinimalApi.Sdk&version=0.1.0-alpha.130&prerelease
                    
Install as a Cake Tool

Siemens.AspNet.Minimal.Sdk

The Siemens.AspNet.Minimal.Sdk NuGet package offers a streamlined approach to building Minimal APIs in ASP.NET Core. It includes pre-configured defaults, opinionated helpers, and seamless integrations that accelerate development and simplify application setup.


📖 Overview

This SDK is designed to remove boilerplate code and help you focus on what matters: your business logic.

✅ Key Features

  • ⚙️ Pre-configured application startup
  • ☁️ AWS integration (optional)
  • 🗄️ Database connectivity (supports AWS DynamoDB)
  • 🔄 Consistent JSON serialization settings
  • 🔐 Security best practices (JWT, OAuth2, security headers)
  • ✔️ Custom validation support
  • 📘 Auto-configured OpenAPI/Swagger

📦 Installation

Using the .NET CLI

dotnet add package Siemens.AspNet.Minimal.Sdk

⚡ Quickstart Example

Below is a minimal setup using ServerlessMinimalWebApi, designed to get you started in seconds:

using Pulse.FieldingTool.Api;
using Siemens.AspNet.MinimalApi.Sdk;

// Create the minimal API host
var webApi = new ServerlessMinimalWebApi();

// Optionally set a global base path for all endpoints
webApi.BasePath = "api/fieldingtool";

// Register application services
webApi.RegisterServices = (services, config) =>
{
    services.AddApi(config);
};

// Map API endpoints
webApi.MapEndpoints = endpoints =>
{
    endpoints.MapApi();
};

// Run the application
webApi.Run(args);

// Enable testing via WebApplicationFactory<Program>
namespace Pulse.FieldingTool
{
    public partial class Program {}
}

🧠 Key Concepts

Component Description
ServerlessMinimalWebApi Opinionated builder for hosting, logging, and config setup
RegisterServices Delegate for adding services to the DI container
MapEndpoints Delegate for defining endpoint mappings using Minimal API routing
Run Starts the web application
partial Program Enables integration testing with WebApplicationFactory<Program>

Helpers and utils

Activator Usage

public class ExampleService
{
    private readonly IActivator _activator;

    public ExampleService(IActivator activator)
    {
        _activator = activator;
    }

    public async Task<MyClass> CreateMyClassAsync()
    {
        return await _activator.CreateInstanceAsync<MyClass>();
    }
}

JSON Differ Example

public void CheckJsonDifferences(IJsonDiffer jsonDiffer)
{
    var differences = jsonDiffer.FindDifferences("{\"name\":\"John\"}", "{\"name\":\"Jane\"}");
    foreach (var diff in differences)
    {
        Console.WriteLine($"Property: {diff.MemberPath}, Difference: {diff.MismatchType}");
    }
}

Custom Validation with Attributes

internal static class AddAlphaNumericValidatorExtension
{
    internal static void AddAlphaNumericValidator(this IServiceCollection services)
    {
        services.AddSingletonIfNotExists<ICustomValidator, AlphaNumericValidator>();
    }
}

public class AlphaNumericAttribute(params string[] sampleValues) : CustomValidationAttribute<AlphaNumericValidator>(string.Empty, sampleValues);

public sealed class AlphaNumericValidator : CustomValidatorBase<string, AlphaNumericAttribute>
{
    protected override IEnumerable<ValidationErrorDetailsBase> Validate(PropertyInfo propertyInfo,
                                                                        AlphaNumericAttribute attribute,
                                                                        string? source)
    {
        if (source == null)
        {
            yield break;
        }

        if (source.Any(ch => !char.IsLetterOrDigit(ch)))
        {
            var sampleValues = attribute.SampleValues.Any() ? attribute.SampleValues : ["sample123"];

            yield return new ValidationErrorDetailsBase
            {
                Errors = [$"{propertyInfo.Name} must be alphanumeric."],
                Samples = sampleValues
            };
        }
    }
}

Request Validator (sync)

This request validator shows a sample without attribute validation.

public static class AddCreateFormsConfigurationRequestValidatorExtension
{
    internal static void AddCreateFormsConfigurationRequestValidator(this IServiceCollection services,
                                                                     IConfiguration configuration)
    {
        services.AddLanguageValidator();
        services.AddFormsConfigurationSettings(configuration);

        services.AddSingletonIfNotExists<CreateFormsConfigurationRequestValidator>();
    }
}

internal sealed class CreateFormsConfigurationRequestValidator(LanguageValidator languageValidator,
                                                               FormsConfigurationSettings formsConfigurationSettings,
                                                               IAttributeValidator attributeValidator) : RequestValidator<CreateFormsConfigurationRequest>(IAttributeValidator attributeValidator)
{
    protected override IEnumerable<PropertyValidationResult> GetValidationErrors(CreateFormsConfigurationRequest request)
    {
        // Your validation code here
        if (request.FormsId.IsNull())
        {
            var errorDetails = new ValidationErrorDetails
                                {
                                    CurrentValue = request.FormsId,
                                    Errors = [$"{nameof(request.FormsId)} must not be null. Only GUID or a long is valid for the {nameof(request.FormsId)}"],
                                    Samples = ["a1b2c3d4-e5f6-7890-1234-567890abcdef", "1"]
                                };

            yield return new PropertyValidationResult(nameof(request.FormsId), errorDetails);
        }
    }
}

Async Request Validator

In this sample the async validator is used to validate a CreateDeploymentRequest object. The validator checks for the presence of required properties and validates them using the IAttributeValidator interface.

public sealed record CreateDeploymentRequest
{
    [ValidEnum]
    public required Stage Stage { get; init; }
};
internal static class AddCreateDeploymentRequestValidatorExtension
{
    internal static void AddCreateDeploymentRequestValidator(this IServiceCollection services)
    {
        services.AddSingletonIfNotExists<CreateDeploymentRequestValidator>();
    }
}

internal sealed class CreateDeploymentRequestValidator(IAttributeValidator attributeValidator) : AsyncRequestValidator<CreateDeploymentRequest>
{
    protected override async IAsyncEnumerable<PropertyValidationResult> GetValidationErrorsAsync(CreateDeploymentRequest request,
                                                                                                    [EnumeratorCancellation] CancellationToken cancellationToken = default)
    {
        var errors = await attributeValidator.ValidateAsync(request, cancellationToken).ConfigureAwait(false);
        foreach (var propertyValidationResult in errors)
        {
            yield return propertyValidationResult;
        }
    }
}

AWS DynamoDB Custom Converters

The Siemens.AspNet.MinimalApi.Sdk already provides out of the box some helpers for the most common types. You can use them directly or implement your own converters.

Converter Name Description
DateTimeOffsetConverter Converts DateTimeOffset values to and from string format (typically ISO 8601) for DynamoDB.
DictionaryStringObjectConverter Handles conversion of Dictionary<string, object> to a DynamoDB-compatible format.
DictionaryStringObjectNullableConverter Similar to DictionaryStringObjectConverter but allows nullable dictionary handling.
ImmutableDictionaryStringObjectNullableConverter Converts ImmutableDictionary<string, object?> to a format compatible with DynamoDB, supporting null values.
TimeSpanConverter Serializes TimeSpan values as string and deserializes them back. Useful for time duration storage in DynamoDB.

Sample:

[DynamoDBTable("Capability")]
public record CapabilityEntity
{
    [DynamoDBHashKey]
    public required Guid Id { get; init; }

    [DynamoDBRangeKey]
    public required string DeploymentId { get; init; } = CapabilityConstants.DefaultDeploymentId;

    [DynamoDBProperty(typeof(DateTimeOffsetConverter))]
    public required DateTimeOffset LastUpdatedDate { get; init; } = DateTimeOffset.UtcNow;
}

AWS Dynamo Entity Mapper (POC)

The IDynamoEntityMapper brings already most common converter with it (Siemens.AspNet.MinimalApi.Sdk). You can just use it. In exception cases, you can implement your own converter by implementing IDynamoTypeConverter or IAsyncDynamoTypeConverter.

Converter Name Description
EnumToStringConverter Converts enum values to their string representation and vice versa. Useful for storing enums as strings in DynamoDB.
EnumerableToImmutableConverter Converts IEnumerable<T> to ImmutableList<T> for safe, immutable handling of collections during mapping.
ImmutableToListConverter Converts ImmutableList<T> to List<T> to support serialization or mutable collection use cases.
TimeSpanToStringConverter Serializes TimeSpan values as ISO 8601-like strings and parses them back. Enables human-readable time span storage.
public sealed class MyHandler(IDynamoEntityMapper mapper)
{
    public async Task<MyDto> HandleAsync(object rawData, CancellationToken cancellationToken)
    {
        return await mapper.ConvertAsync<MyDto>(rawData, cancellationToken);
    }
}

Custom property converter example:

internal static class AddTimeSpanToStringConverterExtension
{
    internal static void AddTimeSpanToStringConverter(this IServiceCollection services)
    {
        services.AddSingletonIfNotExists<IDynamoTypeConverter, TimeSpanToStringConverter>();
    }
}

internal sealed class TimeSpanToStringConverter : IDynamoTypeConverter
{
    public bool CanConvert(Type source,
                            Type target)
    {
        var canConvert = source == typeof(TimeSpan) &&
                            target == typeof(string);

        return canConvert;
    }

    public object? ConvertObject(object? source,
                                    Type targetType)
    {
        return source?.ToString();
    }
}

📌 Usage & Best Practices

  • Leverage IActivator for instance creation with dependency injection.
  • Leverage IAsyncActivator for instance creation with dependency injection in asynchronous contexts.
  • Utilize IJsonDiffer for tracking JSON changes in PATCH requests.
  • Implement custom validation logic by extending provided base validator classes.
  • Implement IAttributeValidator custom for attribute-driven validation scenarios.
  • Simplified attribut-based validation by the IAttributeValidator interface.
  • Use IDynamoTypeConverter or IAsyncDynamoTypeConverter to encapsulate DynamoDB-safe conversions.
  • Register custom converters and provide an implementation of IDynamoEntityMapper to centralize conversion logic.

📚 Documentation

Additional details and examples are available in the repository documentation and upcoming online resources.


📢 Contributing

Your contributions and feedback are welcomed! Please create issues or pull requests to enhance this package.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on Siemens.AspNet.MinimalApi.Sdk:

Package Downloads
Siemens.AspNet.MsTest.Sdk

A library which contains following functions: - Siemens.AspNet.MsTest.Sdk

Siemens.AspNet.DbProvider

A library which contains following functions: - Siemens.AspNet.DbProvider

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0-alpha.281 66 9/16/2025
0.1.0-alpha.280 36 9/16/2025
0.1.0-alpha.279 33 9/16/2025
0.1.0-alpha.278 35 9/16/2025
0.1.0-alpha.275 8,134 9/3/2025
0.1.0-alpha.274 356 9/2/2025
0.1.0-alpha.273 205 9/1/2025
0.1.0-alpha.272 120 9/1/2025
0.1.0-alpha.271 170 8/29/2025
0.1.0-alpha.270 154 8/29/2025
0.1.0-alpha.269 154 8/29/2025
0.1.0-alpha.268 161 8/29/2025
0.1.0-alpha.267 166 8/27/2025
0.1.0-alpha.266 188 8/27/2025
0.1.0-alpha.264 266 8/22/2025
0.1.0-alpha.263 75 8/22/2025
0.1.0-alpha.262 77 8/22/2025
0.1.0-alpha.261 88 8/22/2025
0.1.0-alpha.260 98 8/22/2025
0.1.0-alpha.259 98 8/22/2025
0.1.0-alpha.258 254 8/19/2025
0.1.0-alpha.257 193 8/18/2025
0.1.0-alpha.246 156 8/14/2025
0.1.0-alpha.245 123 8/14/2025
0.1.0-alpha.244 156 8/14/2025
0.1.0-alpha.243 126 8/14/2025
0.1.0-alpha.238 126 8/12/2025
0.1.0-alpha.237 481 8/6/2025
0.1.0-alpha.236 228 8/5/2025
0.1.0-alpha.235 201 8/5/2025
0.1.0-alpha.234 202 8/5/2025
0.1.0-alpha.233 166 8/4/2025
0.1.0-alpha.232 177 8/4/2025
0.1.0-alpha.231 72 8/1/2025
0.1.0-alpha.230 72 8/1/2025
0.1.0-alpha.229 95 7/31/2025
0.1.0-alpha.228 96 7/31/2025
0.1.0-alpha.227 95 7/31/2025
0.1.0-alpha.225 92 7/31/2025
0.1.0-alpha.224 94 7/30/2025
0.1.0-alpha.222 277 7/16/2025
0.1.0-alpha.219 166 7/14/2025
0.1.0-alpha.217 84 7/11/2025
0.1.0-alpha.212 173 7/8/2025
0.1.0-alpha.211 179 7/3/2025
0.1.0-alpha.207 120 7/3/2025
0.1.0-alpha.206 301 6/30/2025
0.1.0-alpha.205 101 6/27/2025
0.1.0-alpha.202 95 6/27/2025
0.1.0-alpha.200 102 6/27/2025
0.1.0-alpha.198 101 6/27/2025
0.1.0-alpha.196 108 6/27/2025
0.1.0-alpha.195 99 6/27/2025
0.1.0-alpha.194 100 6/27/2025
0.1.0-alpha.193 109 6/27/2025
0.1.0-alpha.192 103 6/27/2025
0.1.0-alpha.191 98 6/27/2025
0.1.0-alpha.189 119 6/26/2025
0.1.0-alpha.188 173 6/26/2025
0.1.0-alpha.187 122 6/26/2025
0.1.0-alpha.186 142 6/26/2025
0.1.0-alpha.185 123 6/26/2025
0.1.0-alpha.184 121 6/26/2025
0.1.0-alpha.183 120 6/26/2025
0.1.0-alpha.182 121 6/26/2025
0.1.0-alpha.181 142 6/25/2025
0.1.0-alpha.180 130 6/24/2025
0.1.0-alpha.179 123 6/23/2025
0.1.0-alpha.178 204 6/23/2025
0.1.0-alpha.176 122 6/23/2025
0.1.0-alpha.174 139 6/19/2025
0.1.0-alpha.173 162 6/19/2025
0.1.0-alpha.172 128 6/17/2025
0.1.0-alpha.171 205 6/16/2025
0.1.0-alpha.169 124 6/16/2025
0.1.0-alpha.165 384 6/13/2025
0.1.0-alpha.164 230 6/13/2025
0.1.0-alpha.163 237 6/13/2025
0.1.0-alpha.160 273 6/12/2025
0.1.0-alpha.159 364 6/11/2025
0.1.0-alpha.158 273 6/11/2025
0.1.0-alpha.143 270 6/11/2025
0.1.0-alpha.142 269 6/11/2025
0.1.0-alpha.140 272 6/11/2025
0.1.0-alpha.139 316 6/10/2025
0.1.0-alpha.138 259 6/9/2025
0.1.0-alpha.137 55 6/7/2025
0.1.0-alpha.136 51 6/7/2025
0.1.0-alpha.135 81 6/6/2025
0.1.0-alpha.134 76 6/6/2025
0.1.0-alpha.130 130 6/5/2025
0.1.0-alpha.129 125 6/4/2025
0.1.0-alpha.128 130 6/4/2025
0.1.0-alpha.122 185 6/3/2025
0.1.0-alpha.121 144 6/1/2025
0.1.0-alpha.120 89 6/1/2025
0.1.0-alpha.118 136 5/28/2025
0.1.0-alpha.117 127 5/28/2025
0.1.0-alpha.116 155 5/28/2025
0.1.0-alpha.115 129 5/26/2025
0.1.0-alpha.114 156 5/22/2025
0.1.0-alpha.112 129 5/21/2025
0.1.0-alpha.111 124 5/20/2025
0.1.0-alpha.108 180 5/19/2025
0.1.0-alpha.104 490 5/18/2025
0.1.0-alpha.102 355 5/14/2025
0.1.0-alpha.101 209 5/14/2025
0.1.0-alpha.100 212 5/12/2025
0.1.0-alpha.99 238 5/12/2025
0.1.0-alpha.98 53 5/10/2025
0.1.0-alpha.97 53 5/10/2025
0.1.0-alpha.86 154 5/8/2025
0.1.0-alpha.85 122 5/8/2025
0.1.0-alpha.84 122 5/8/2025
0.1.0-alpha.82 131 5/7/2025
0.1.0-alpha.81 122 5/6/2025
0.1.0-alpha.76 55 5/3/2025
0.1.0-alpha.75 73 5/2/2025
0.1.0-alpha.74 80 5/2/2025
0.1.0-alpha.56 142 4/28/2025
0.1.0-alpha.55 137 4/28/2025
0.1.0-alpha.54 210 4/14/2025
0.1.0-alpha.53 195 4/14/2025
0.1.0-alpha.48 453 4/14/2025
0.1.0-alpha.47 186 4/9/2025
0.1.0-alpha.46 250 4/9/2025
0.1.0-alpha.44 139 4/7/2025
0.1.0-alpha.41 138 4/7/2025
0.1.0-alpha.40 140 4/7/2025
0.1.0-alpha.39 96 4/4/2025
0.1.0-alpha.38 104 4/4/2025
0.1.0-alpha.37 110 4/4/2025
0.1.0-alpha.33 144 4/4/2025
0.1.0-alpha.29 144 4/3/2025
0.1.0-alpha.28 146 4/3/2025
0.1.0-alpha.27 140 4/3/2025
0.1.0-alpha.26 233 4/2/2025