Skip to content

ASP.NET Core Integration

Mike Christensen edited this page Aug 28, 2026 · 2 revisions

ASP.NET Core integration

KitchenPC provides an IServiceCollection extension that initializes one root context and exposes identity-specific scoped contexts.

Install the integration package in addition to the engine and persistence packages:

dotnet add package KitchenPC.Core --version 2.0.0
dotnet add package KitchenPC.DB --version 2.0.0
dotnet add package KitchenPC.Core.AspNetCore --version 2.0.0

Keeping this integration separate means console applications, workers, and desktop tools do not acquire an ASP.NET Core framework dependency.

Register DBContext

using FluentNHibernate.Cfg.Db;
using KitchenPC.Core;
using KitchenPC.Core.Context;
using KitchenPC.Core.Middleware;
using KitchenPC.DB;

var connectionString = builder.Configuration
   .GetConnectionString("KPCContext")
   ?? throw new InvalidOperationException("Missing KPCContext connection string.");

builder.Services.AddKPCContext(
   Configuration<DBContext>.Build
      .Context(DBContext.Configure
         .Adapter(DatabaseAdapter.Configure
            .DatabaseConfiguration(
               PostgreSQLConfiguration.PostgreSQL82
                  .ConnectionString(connectionString))
            .SearchProvider(NHSearch.Instance))
         .Capabilities(DBContextCapabilities.IngredientParsing)
         .Identity(() => AuthIdentity.Anonymous))
      .Create());

Startup initializes the root context. A scoped DBContext can then be constructor-injected into services or controllers.

Authenticated identity mapping

For an authenticated request, AddKPCContext reads:

  • ClaimTypes.Sid as a GUID user ID;
  • ClaimTypes.Name as the KitchenPC alias.

When both are valid, the scoped context is an AsUserContext view. Otherwise it remains the configured anonymous context. Configure those claims in your authentication pipeline before using identity-scoped mutations.

public sealed class RecipeService
{
   private readonly DBContext context;

   public RecipeService(DBContext context) => this.context = context;

   public Task<SearchResults> SearchAsync(string query, CancellationToken token) =>
      context.Recipes.Search(q => q.Keywords(query)).ResultsAsync(token);
}

Capability selection

A public recipe browser generally needs no in-memory capability. Add IngredientParsing for natural-language shopping entries, IngredientAutocomplete for server-side type-ahead, and RecipeModeler only for modeling. The React Web App sample uses parsing only.

API boundary guidance

  • Do not expose KitchenPC persistence models directly as a long-lived public API contract; map them to request/response DTOs.
  • Pass CancellationToken to async fluent calls.
  • Validate paging, times, serving counts, IDs, raw ingredient length, and number of items.
  • Treat recipe method HTML as untrusted. Sanitize it with an allow-list before returning renderable HTML, or convert it to plain text.
  • Do not return connection strings, adapter exceptions, SQL, or stack traces to clients.
  • Keep InitializeStore() out of web startup.
  • Decide explicitly whether shopping state belongs in PostgreSQL, a browser, or another user store.

The Samples Web App demonstrates controllers, a domain service layer, DTOs, React/TypeScript, database search and details, recipe images, sanitized methods, and a browser-persisted aggregated shopping list.

Clone this wiki locally