Kanject.Core.Api

View .md

ASP.NET Core building blocks that give every Kanject HTTP service the same baseline: a consistent Response<T> envelope from BaseController, exception-to-error middleware, and x-tenant-id tenant resolution. Free under the Community licence.

Install

bash
dotnet add package Kanject.Core.Api

Register

csharp
using Kanject.Core.Api.Extensions;var builder = WebApplication.CreateBuilder(args);builder.Services.AddControllers();builder.Services.AddCoreExceptionHandlerMiddleware();   // consistent error envelopebuilder.Services.AddTenantMiddleware();                 // x-tenant-id resolutionvar app = builder.Build();app.UseRouting();app.UseCoreExceptionHandlerMiddleware();app.UseTenantMiddleware();app.MapControllers();app.Run();

Two middlewares, registered as services and then used in the pipeline: CoreExceptionHandler turns uncaught exceptions into a consistent JSON error envelope, and TenantMiddleware resolves the caller's tenant from the x-tenant-id header into the request context.

Controllers

Derive from BaseController and return through ApiResponse(...), which wraps your payload (and optional PayloadMetadata for pagination) in the shared Response<T> envelope. Errors come back in the same Response<string> shape, so every endpoint — success or failure — has one predictable body:

csharp
using Kanject.Core.Api.Controller;using Kanject.Core.Api.Models;[ApiController][Route("api/orders")]public sealed class OrdersController(OrderService orders) : BaseController{    [HttpGet]    [ProducesResponseType(typeof(Response<ApiResponseDataset<OrderDto>>), StatusCodes.Status200OK)]    [ProducesResponseType(typeof(Response<string>), StatusCodes.Status400BadRequest)]    public async Task<IActionResult> ListAsync(        [FromQuery] int pageSize = 20,        [FromQuery] string? pageToken = null,        CancellationToken cancellationToken = default)    {        var page = await orders.ListAsync(pageSize, pageToken, cancellationToken);        var metadata = new PayloadMetadata(            pageSize: pageSize,            pageItemCount: page.Items.Count,            hasNextPage: page.NextToken is not null,            pageToken: page.NextToken);        // BaseController.ApiResponse wraps the payload in Response<T>.        return ApiResponse(page.Items, metadata, "Orders retrieved.");    }}

What ships with it

  • BaseController + ApiResponse(...) → a consistent Response<T> / ApiResponseDataset<T> envelope, with PayloadMetadata for pagination
  • AddCoreExceptionHandlerMiddleware / UseCoreExceptionHandlerMiddleware — uncaught exceptions become a uniform JSON error response
  • AddTenantMiddleware / UseTenantMiddlewarex-tenant-id resolved into the request-scoped tenant context
  • Distributed as a public NuGet Community package (free under the $250K threshold)
Was this page helpful?