Rystem.RepositoryFramework.Api.Server 10.0.7

dotnet add package Rystem.RepositoryFramework.Api.Server --version 10.0.7
                    
NuGet\Install-Package Rystem.RepositoryFramework.Api.Server -Version 10.0.7
                    
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="Rystem.RepositoryFramework.Api.Server" Version="10.0.7" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Rystem.RepositoryFramework.Api.Server" Version="10.0.7" />
                    
Directory.Packages.props
<PackageReference Include="Rystem.RepositoryFramework.Api.Server" />
                    
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 Rystem.RepositoryFramework.Api.Server --version 10.0.7
                    
#r "nuget: Rystem.RepositoryFramework.Api.Server, 10.0.7"
                    
#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 Rystem.RepositoryFramework.Api.Server@10.0.7
                    
#: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=Rystem.RepositoryFramework.Api.Server&version=10.0.7
                    
Install as a Cake Addin
#tool nuget:?package=Rystem.RepositoryFramework.Api.Server&version=10.0.7
                    
Install as a Cake Tool

What is Rystem?

Rystem.RepositoryFramework.Api.Server

NuGet NuGet Downloads

Minimal-API endpoint generation for repositories and CQRS registrations created through the Rystem repository framework.

This package reads the runtime repository registry and turns registered repositories, commands, and queries into HTTP endpoints without controllers.

Resources


Installation

dotnet add package Rystem.RepositoryFramework.Api.Server

The current package metadata in src/Repository/RepositoryFramework.Api.Server/RepositoryFramework.Api.Server.csproj is:

  • package id: Rystem.RepositoryFramework.Api.Server
  • version: 10.0.6
  • target framework: net10.0
  • framework reference: Microsoft.AspNetCore.App
  • Swagger package: Swashbuckle.AspNetCore 10.1.4

Package architecture

Area Purpose
AddApiFromRepositoryFramework() Collect API-level settings such as path, version, Swagger, CORS, and diagnostics
UseApiFromRepositoryFramework() Read RepositoryFrameworkRegistry and map endpoints
Authorization builder Apply endpoint-level auth rules by repository method group
Repository authorization handlers Add repository-specific authorization logic via IRepositoryAuthorization<T, TKey>
Map/models diagnostics Expose generated endpoint metadata and generated TypeScript model definitions
Swagger/OpenID helpers Configure Swagger UI and OpenID metadata for the generated API

Mental model

This package does not replace repository registration. It sits on top of it.

The flow is:

  1. Register repositories, commands, or queries through the abstractions layer.
  2. Optionally mark methods as exposable or hidden on each repository registration.
  3. Configure API behavior with AddApiFromRepositoryFramework().
  4. Map the generated endpoints with UseApiFromRepositoryFramework().

The package discovers what to expose from RepositoryFrameworkRegistry, so there is no controller layer to keep in sync.


Quick start

This is the real shape used in the sample host under src/Repository/RepositoryFramework.Test/RepositoryFramework.WebApi/Program.cs.

builder.Services.AddRepository<SuperUser, string>(repositoryBuilder =>
{
    repositoryBuilder.WithInMemory(inMemoryBuilder =>
    {
        inMemoryBuilder
            .PopulateWithRandomData(120, 5)
            .WithPattern(x => x.Value!.Email, @"[a-z]{5,10}@gmail\.com");
    });
});

builder.Services.AddApiFromRepositoryFramework()
    .WithDescriptiveName("Repository Api")
    .WithSwagger()
    .WithMapApi()
    .WithModelsApi()
    .WithDocumentation()
    .WithDefaultCorsWithAllOrigins();

var app = builder.Build();
await app.Services.WarmUpAsync();

app.UseAuthentication();
app.UseAuthorization();

app.UseApiFromRepositoryFramework()
    .WithNoAuthorization();

app.Run();

Service-side configuration

AddApiFromRepositoryFramework() returns IApiBuilder.

builder.Services.AddApiFromRepositoryFramework()
    .WithDescriptiveName("My API")
    .WithPath("api")
    .WithVersion("v2")
    .WithSwagger()
    .WithMapApi()
    .WithModelsApi();

Configuration methods

Method What it does
WithDescriptiveName(string) Sets the API name used by Swagger UI
WithPath(string) Sets the base path segment, default api
WithVersion(string) Adds a version segment after the base path
WithName<T>(string) Overrides the route segment used for model T
WithSwagger() Registers Swagger/OpenAPI services and UI support
WithDocumentation() Enables extra Swagger UI customization and PDF export support
WithMapApi() Enables the repository map endpoint
WithModelsApi() Enables the generated-model endpoint
WithDefaultCors(params string[] domains) Registers a default named CORS policy for the provided origins
WithDefaultCorsWithAllOrigins() Registers a permissive named CORS policy
WithCors(Action<CorsOptions>) Lets you configure CORS directly
WithOpenIdAuthentication(...) Configures OpenID metadata for Swagger UI and returns IIdentityApiBuilder
ConfigureAzureActiveDirectory(IConfiguration) Shortcut that reads AzureAd:* settings and configures OpenID metadata

Important note about WithDocumentation()

WithDocumentation() does not load XML doc comments.

In the current implementation it enhances Swagger UI by injecting custom UI content and a RapiPDF-based export button. It only has visible effect when Swagger is also enabled.


Route generation

The main generated route shape is:

  • default registration: /{path}/{version?}/{modelName}/{method}
  • named registration: /{path}/{version?}/{modelName}/{factoryName}/{method}

Examples:

  • /api/v1/SuperUser/Get
  • /api/v1/SuperUser/Insert
  • /api/v1/SuperUser/inmemory/Get

If you override a name with WithName<T>(...), that custom segment is used instead of typeof(T).Name.


Mapping all repositories or one repository

Map every registered repository

app.UseApiFromRepositoryFramework()
    .WithNoAuthorization();

Map a single entity type

app.UseApiFromRepositoryFramework<WebApplication, SuperUser, string>()
    .WithNoAuthorization();

Map a specific named registration

app.UseApiFromRepositoryFramework<WebApplication, SuperUser, string>(name: "inmemory")
    .WithNoAuthorization();

Request shapes by method

The generated HTTP shape depends not only on the repository method, but also on whether TKey is JSON-serializable according to KeySettings<TKey>.

Non-JSON keys

For primitive/string/IKey-style keys, the generated endpoints are:

Method HTTP Shape
Get GET ?key=...
Exist GET ?key=...
Delete GET ?key=...
Insert POST query key + body T
Update POST query key + body T
Query POST body SerializableFilter?
Operation POST query op, optional query returnType, body SerializableFilter?
Batch POST body BatchOperations<T, TKey>

JSON-style keys

For keys treated as JSONable by KeySettings<TKey>, the generated endpoints switch to request bodies for key-based methods.

Method HTTP Shape
Get POST body TKey
Exist POST body TKey
Delete POST body TKey
Insert POST body Entity<T, TKey>
Update POST body Entity<T, TKey>

Stream endpoints

Two methods also generate streaming variants:

  • POST .../Query/Stream
  • POST .../Batch/Stream

These return the underlying async stream instead of materializing everything into a list first.


Repository methods and exposure

The API server only maps methods that are both:

  • implemented by the registered service
  • allowed by the repository's ExposedMethods

That means abstractions-layer settings such as these directly affect the generated API:

  • SetExposable(...)
  • SetOnlyQueryExposable()
  • SetOnlyCommandExposable()
  • SetNotExposable()

For custom storages that are not marked as default integrations, the mapper also skips methods whose body is just throw new NotImplementedException(...).


Diagnostics endpoints

Two optional endpoints provide metadata about the generated API.

Repository map

Enable it with:

builder.Services.AddApiFromRepositoryFramework()
    .WithMapApi();

Route:

/Repository/Map/All

This endpoint is not placed under your configured API base path. It is a fixed diagnostic route.

It returns:

  • every generated API entry
  • route URIs
  • repository method names
  • authentication/policy metadata
  • sample request and response payloads

If you registered repository examples with SetExamples(...), those values are used. Otherwise the package falls back to random sample generation.

Models endpoint

Enable it with:

builder.Services.AddApiFromRepositoryFramework()
    .WithModelsApi();

Current route:

/Repository/Models/Typescript

This route returns generated TypeScript definitions for repository models and non-primitive keys. It is also outside the main API base path.


Authorization at endpoint-mapping time

UseApiFromRepositoryFramework() returns IApiAuthorizationBuilder.

No authorization

app.UseApiFromRepositoryFramework()
    .WithNoAuthorization();

Require authentication on all endpoints

app.UseApiFromRepositoryFramework()
    .WithDefaultAuthorization();

This maps endpoints and applies RequireAuthorization() without naming a specific policy.

Query vs command policies

app.UseApiFromRepositoryFramework()
    .SetPolicyForQuery().With("ReadUser")
    .And()
    .SetPolicyForCommand().With("WriteUser")
    .Build();

Specific methods

app.UseApiFromRepositoryFramework()
    .SetPolicyForAll().With("AuthenticatedUser")
    .And()
    .SetPolicy(RepositoryMethods.Insert, RepositoryMethods.Update, RepositoryMethods.Delete).With("AdminUser")
    .Build();

Builder methods

Method Purpose
WithNoAuthorization() Map endpoints without auth requirements
WithDefaultAuthorization() Require authentication on all mapped endpoints
SetPolicyForAll() Target every repository method
SetPolicyForCommand() Target Insert, Update, Delete, Batch
SetPolicyForQuery() Target Exist, Get, Query, Operation
SetPolicy(...) Target specific RepositoryMethods
Build() Finalize endpoint mapping

Policy chaining methods

Method Purpose
With(params string[]) Attach ASP.NET policy names
Empty() Require auth but clear explicit policy names
And() Return to the main authorization builder
Build() Finalize mapping

Repository-specific authorization handlers

This package also supports custom authorization handlers that run with repository-specific context.

Register directly on a repository builder

repositoryBuilder
    .ConfigureSpecificPolicies()
    .WithAuthorizationHandler<PolicyHandlerForSuperUser>();

Scan assemblies for handlers

builder.Services.ScanAuthorizationForRepositoryFramework();

Handlers implement:

public interface IRepositoryAuthorization<in T, in TKey>
{
    Task<AuthorizedRepositoryResponse> HandleRequirementAsync(
        IHttpContextAccessor httpContextAccessor,
        AuthorizationHandlerContext context,
        RepositoryRequirement requirement,
        RepositoryMethods method,
        TKey? key,
        T? value);
}

This gives the handler access to:

  • the current repository method
  • the current request
  • the parsed key when available
  • the parsed entity body for insert/update when available

ScanAuthorizationForRepositoryFramework() attaches discovered handlers to repositories with the matching model/key pair and registers the backing ASP.NET authorization policies automatically.


Swagger and OpenID notes

Swagger

builder.Services.AddApiFromRepositoryFramework()
    .WithDescriptiveName("Repository Api")
    .WithSwagger();

Swagger UI is activated when the endpoints are mapped through UseApiFromRepositoryFramework(...).

OpenID metadata for Swagger UI

builder.Services.AddApiFromRepositoryFramework()
    .WithSwagger()
    .WithOpenIdAuthentication(settings =>
    {
        settings.AuthorizationUrl = new Uri("https://login.example.com/oauth2/authorize");
        settings.TokenUrl = new Uri("https://login.example.com/oauth2/token");
        settings.ClientId = "client-id";
        settings.Scopes.Add(new ApiIdentityScopeSettings
        {
            Value = "api.read",
            Description = "Read access"
        });
    })
    .WithAuthorization(options =>
    {
        options.AddPolicy("AdminOnly", policy => policy.RequireRole("Admin"));
    });

Important: WithOpenIdAuthentication(...) and ConfigureAzureActiveDirectory(...) configure Swagger/OpenAPI authentication metadata. They do not register your runtime ASP.NET authentication handler.

You still need the normal server-side authentication setup, for example:

builder.Services
    .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));

Azure Active Directory shortcut

builder.Services.AddApiFromRepositoryFramework()
    .WithSwagger()
    .ConfigureAzureActiveDirectory(builder.Configuration);

This reads:

  • AzureAd:Instance
  • AzureAd:TenantId
  • AzureAd:ClientId
  • AzureAd:Scopes

and converts them into the OpenID settings used by Swagger UI.


Warm-up and bootstrap

If your repositories rely on startup work such as in-memory data population or other bootstrap actions, keep calling:

await app.Services.WarmUpAsync();

before serving requests.

The API package can also expose repository Bootstrap endpoints when that method is exposable.

One source-backed nuance: the current bootstrap endpoint still flows through the same key-binding pipeline as other key-based methods, even though the key is ignored by the implementation.


Practical examples from the repo

Rename an entity route segment

The API tests configure custom names like this:

builder.Services.AddApiFromRepositoryFramework()
    .WithName<ExtremelyRareUser>("extremelyrareuserrefresh")
    .WithName<CalamityUniverseUser>("calamityuser")
    .WithPath("SuperApi")
    .WithVersion("v2");

That produces routes like:

/SuperApi/v2/extremelyrareuserrefresh/Get

Map endpoint metadata and models

The same API tests also enable:

builder.Services.AddApiFromRepositoryFramework()
    .WithSwagger()
    .WithMapApi()
    .WithModelsApi()
    .WithDocumentation();

Clear no-auth mapping in tests and samples

The tests and sample host generally use the explicit no-auth mapping form:

app.UseApiFromRepositoryFramework()
    .WithNoAuthorization();

Package Purpose
Rystem.RepositoryFramework.Abstractions Repository registration, exposure flags, keys, filters, and business hooks
Rystem.RepositoryFramework.Api.Client .NET client for the generated server endpoints
rystem.repository.client TypeScript/npm client for the generated server endpoints

If you are continuing through the repository area, this package is the bridge between repository registrations and HTTP exposure.

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

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
10.0.7 64 3/26/2026
10.0.6 148,218 3/3/2026
10.0.5 94 2/22/2026
10.0.4 112 2/9/2026
10.0.3 147,913 1/28/2026
10.0.1 209,161 11/12/2025
9.1.3 311 9/2/2025
9.1.2 764,568 5/29/2025
9.1.1 97,849 5/2/2025
9.0.33 269 4/30/2025
9.0.32 186,699 4/15/2025
9.0.31 5,885 4/2/2025
9.0.30 88,919 3/26/2025
9.0.29 9,060 3/18/2025
9.0.28 272 3/17/2025
9.0.27 282 3/16/2025
9.0.26 281 3/13/2025
9.0.25 52,189 3/9/2025
9.0.21 419 3/6/2025
9.0.20 19,638 3/6/2025
Loading failed