Siemens.AspNet.MinimalApi.Sdk 7.5.1

Prefix Reserved
This package has a SemVer 2.0.0 package version: 7.5.1+1.
dotnet add package Siemens.AspNet.MinimalApi.Sdk --version 7.5.1
                    
NuGet\Install-Package Siemens.AspNet.MinimalApi.Sdk -Version 7.5.1
                    
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="7.5.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Siemens.AspNet.MinimalApi.Sdk" Version="7.5.1" />
                    
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 7.5.1
                    
#r "nuget: Siemens.AspNet.MinimalApi.Sdk, 7.5.1"
                    
#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@7.5.1
                    
#: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=7.5.1
                    
Install as a Cake Addin
#tool nuget:?package=Siemens.AspNet.MinimalApi.Sdk&version=7.5.1
                    
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 Siemens.AspNet.MinimalApi.Sdk;

var webApi = new ServerlessMinimalWebApi();

webApi.BasePath = "api/fieldingtool";

webApi.Versions = [1, 2];

webApi.RegisterServices = (service,
                           config) =>
// Domain service registrations
// service.AddApi(config);

webApi.Run(args);

// This is important that you are able to use
// API test via WebApplicationFactory<Program>
// https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-8.0
namespace Siemens.AspNet.ClientGenerator.Mcp.Server
{
#pragma warning disable CA1515 // Needed for testing
    public class Program;
#pragma warning restore CA1515 // Needed for testing
}

🧠 Key Concepts

Component Description
ServerlessMinimalWebApi Opinionated builder for hosting, logging, and config setup
RegisterServices Delegate for adding services to the DI container
Run Starts the web application
partial Program Enables integration testing with WebApplicationFactory<Program>
IEndpoint Use this interface to implement endpoints. Injectable Endpoint

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
            };
        }
    }
}

Complex-Custom Validation with Attributes

We provide another level of validation if you have an data historie to compare current value against your privious value. (Historical Validation)

internal static class AddIsNotChangeableAfterDeploymentValidatorExtension
    {
        internal static void AddIsNotChangeableAfterDeploymentValidator(this IServiceCollection services)
        {
            services.AddSingletonIfNotExists<IComplexCustomValidator, IsNotChangableAfterDeploymentValidator>();
        }
    }

    internal sealed class IsNotChangeableAfterDeploymentAttribute() : ComplexCustomValidationAttribute<IsNotChangableAfterDeploymentValidator>(string.Empty, [])
    {
    }

    internal sealed class IsNotChangableAfterDeploymentValidator() : ComplexCustomValidator<AwsS3Bucket, string?, IsNotChangeableAfterDeploymentAttribute>
    {
        protected override IEnumerable<ValidationErrorDetailsBase> Validate(PropertyInfo propertyInfo,
                                                                            IsNotChangeableAfterDeploymentAttribute attribute,
                                                                            AwsS3Bucket capability,
                                                                            string? currentValue,
                                                                            string? lastValue)
        {
            if (capability.IsDeployed.IsFalse())
            {
                yield break;
            }

            if (currentValue != lastValue)
            {
                yield return new ValidationErrorDetailsBase
                {
                    Errors = [$"You are not allowed to change the: {propertyInfo.Name} after the capability was deployed ! This would cause in critical male function of your project"],
                    Samples = [currentValue]
                };
            }
        }
    }

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;
        }
    }
}

Injectable Endpoint

The Injectable Endpoint feature introduces a clean, modular way to register Minimal API endpoints directly through dependency injection. Instead of mapping endpoints manually inside Program.cs, you can now inject them into your application as services.

This makes your API endpoints:

  • Discoverable – any registered IEndpoint implementation will be automatically picked up.
  • Modular – endpoints are defined in self-contained classes.
  • No application.Map calls necessary in Program.cs or somewhere else → resolved automatically
  • Provides the option in future to configure which endpoints are available and which not.

Interface:

public interface IEndpoint
{
    void Map(IEndpointRouteBuilder versionBasePath);
}

Sample:

internal static class AddCreateCapabilityEndpointExtension
{
    internal static void AddCreateCapabilityEndpoint(this IServiceCollection services)
    {
        services.AddSingletonIfNotExists<IEndpoint, CreateCapabilityEndpoint>();
    }
}
    
internal class CreateCapabilityEndpoint(CapabilityProvider capabilityProvider) : IEndpoint
{
    public void Map(IEndpointRouteBuilder endpoints)
    {
        // Your endpoint registration logic here :)
        endpoints.MapPost("/capabilities", async (CreateCapabilityRequest request, CancellationToken cancellationToken) =>
        {
            var capability = await capabilityProvider.CreateAsync(request, cancellationToken);
            return Results.Created($"/capabilities/{capability.Id}", capability);
        })
    }
}

Registration:

As you can see no Map necessary. We just register the endpoint

namespace Sdc.Console.Api.Capabilities.V1
{
    internal static class CreateStartup
    {
        internal static void AddCreate(this IServiceCollection services,
                                       IConfiguration configuration)
        {
            services.AddCreateCapabilityCommand(configuration);
            services.AddCreateCapabilityEndpoint();
        }
    }
}

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();
    }
}

🔖 Available Validation Attributes

The SDK provides a comprehensive set of validation attributes for common validation scenarios:

Attribute Description
AlphaNumericAttribute Validates that the value contains only letters and digits
ConsecutivePeriodsAttribute Validates against consecutive periods in a string
ContainsAllOfAttribute Validates that the value contains all specified substrings
ContainsAnyOfAttribute Validates that the value contains at least one of the specified substrings
ContainsAttribute Validates that the value contains a specific substring
ContainsNoNullAttribute Validates that a collection contains no null values
ContainsNoneOfAttribute Validates that the value contains none of the specified substrings
DateTimeIsUtcAttribute Validates that the DateTime value is in UTC timezone
DateTimeOffsetIsUtcAttribute Validates that the DateTimeOffset value is in UTC timezone
DoesNotContainAttribute Validates that the value does not contain a specific substring
EmailAttribute Validates email address format and optional domain
EndWithDigitOrLetterAttribute Validates that the value ends with a digit or letter
EndWithLetterAttribute Validates that the value ends with a letter
EndsWithAttribute Validates that the value ends with a specific suffix
EnumIsDefinedAttribute Validates that the enum value is a defined member of its enum type
EvenAttribute Validates that the numeric value is even
FileExtensionsAttribute Validates file extensions against an allowed list
ForbiddenCharactersAttribute Validates against forbidden characters
GuidIsNotEmptyAttribute Validates that the GUID value is not empty
IsInRangeAttribute Validates that the value is within a specified range
IsNotContainingAttribute Validates that a string or collection does not contain a specified value
IsNotEmptyAttribute Validates that the value is not empty
IsNotNullAttribute Validates that the value is not null
IsNotWhitespaceAttribute Validates that the value is not whitespace
LengthAttribute Validates string length within a min/max range
LettersOnlyAttribute Validates that the value contains only letters
MaxLengthAttribute Validates the maximum length of a string
MaxValueAttribute Validates the maximum numeric value
MinLengthAttribute Validates the minimum length of a string
MinLetterCountAttribute Validates the minimum number of letters
MinValueAttribute Validates the minimum numeric value
NegativeAttribute Validates that the numeric value is negative
NoDuplicateValuesAttribute Validates that a collection contains no duplicate values
NoLeadingWhitespacesAttribute Validates that the value has no leading whitespace
NoTrailingWhitespacesAttribute Validates that the value has no trailing whitespace
NoValidationAttribute Skips validation for the property
NonZeroAttribute Validates that the numeric value is not zero
NumbersOnlyAttribute Validates that the value contains only digits
OddAttribute Validates that the numeric value is odd
OnlyLowerLettersAttribute Validates that all letter characters are lowercase
PeriodsAdjacentHyphensAttribute Validates against periods adjacent to hyphens
PhoneAttribute Validates phone number format
PositiveAttribute Validates that the numeric value is positive
RegexAttribute Validates against a custom regular expression pattern
RegularExpressionAttribute Validates against a regular expression
SpecialCharactersNotAllowedAttribute Validates that only alphanumeric, underscore, and hyphen characters are used
StartWithDigitOrLetterAttribute Validates that the value starts with a digit or letter
StartWithLetterAttribute Validates that the value starts with a letter
StartsWithAttribute Validates that the value starts with a specific prefix
StringLengthAttribute Validates string length within a min/max range
UrlAttribute Validates URL format
UseLettersAttribute Validates that the value contains at least one letter

📌 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 net10.0 is compatible.  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 (1)

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

Package Downloads
Siemens.AspNet.MsTest.Sdk

Provides base classes, argument checking, and helper utilities for writing Siemens-style MSTest tests.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
7.5.1 1,394 6/2/2026
7.5.0 141 5/12/2026
7.5.0-alpha.16 65 5/18/2026
7.5.0-alpha.15 53 5/18/2026
7.5.0-alpha.12 53 5/12/2026
7.5.0-alpha.11 55 5/12/2026
7.5.0-alpha.10 55 5/12/2026
7.5.0-alpha.3 61 5/11/2026
7.4.6 33 6/2/2026
7.4.5 554 5/24/2026
7.4.4 41 5/18/2026
7.4.3 34 5/18/2026
7.4.2 2,493 5/11/2026
7.4.1 40 5/11/2026
7.4.0 5,996 5/6/2026
7.3.4 1,297 5/4/2026
7.3.3 947 5/4/2026
7.3.2 1,796 4/28/2026
7.3.1 2,043 4/24/2026
7.3.0 1,066 4/22/2026
Loading failed