# Flexbase 10

This page contains self-contained upgrade instructions for FlexBase 10 dev builds.

## Upgrade Builds

* [10.0.0-Dev-Build026](#1000-dev-build026) (January 2026)
* [FlexBase 9 to 10 Migration Steps](#flexbase-9-to-10-migration-steps)

***

## 10.0.0-Dev-Build026

### What This Upgrade Changes

* Consolidates exception handling into `FlexExceptionFilter` + `UseFlexExceptionHandler()`
* Adds optional rate limiting support
* Adds optional OpenTelemetry configuration
* Standardizes EF Core feature configuration (Audit Trail, Soft Delete, Async Query Executor)
* Updates generated queries/handlers to use true async (`*AsyncFlex`)
* Adds optional Subscriber Idempotency configuration

***

### Upgrade Steps

#### Step 1: Exception Handling Improvements

**What to change**

1. Replace `FlexStandardExceptionFilter` with `FlexExceptionFilter` in your MVC filter registration.
2. Add `app.UseFlexExceptionHandler()` after CORS.

**Example**

```csharp
builder.Services.AddControllers(config =>
{
    // ... other config
    config.Filters.Add<FlexStandardResponseFilter>();
    config.Filters.Add<FlexExceptionFilter>();
});

var app = builder.Build();

app.UseCors(MyAllowSpecificOrigins);
app.UseFlexExceptionHandler();
```

***

#### Step 2: Rate Limiting Support (Optional)

**What to change**

If you want rate limiting:

```csharp
// builder.Services.AddFlexRateLimiting(builder.Configuration);

var app = builder.Build();

// app.UseFlexRateLimiting();
```

> Keep it commented out if you don't need rate limiting.

***

#### Step 3: OpenTelemetry Configuration (Optional)

**What to change**

If you want OpenTelemetry, wire it from your WebAPI startup (exact method names vary by template):

```csharp
// builder.Services.AddOpenTelemetryForAspNetCore(builder.Configuration, "EndPoint.WebAPI");
```

> Keep it commented out if you don't have an OTLP backend.

***

#### Step 4: EF Core Features Configuration

**What to change**

Create `EfCoreFeaturesConfig.cs` (if you don't already have it) and register it from wherever you build your DB services.

Typical wiring points:

* If you use `*.EndPoint.CommonConfigs/CommonHostConfig.cs`, add:
  * `services.AddFlexEfCoreFeatures(hostingContext.Configuration);`
* Otherwise, add it in your DB configuration method (often `DbEndPointConfig.AddFlexBaseDbServices(...)`).

***

#### Step 5: Async Query Executor

**What to change**

Ensure your EF Core feature registration includes the async query executor, and update queries/handlers to use `*AsyncFlex` methods.

Examples:

```csharp
var customers = await query.ToListAsyncFlex();
var customer = await query.FirstOrDefaultAsyncFlex();
var exists = await query.AnyAsyncFlex();
```

***

#### Step 6: Query Template Updates

**What to change**

In existing generated queries/handlers, update these patterns:

* `.ToList()` + `Task.FromResult(...)` → `await ... .ToListAsyncFlex()` and return directly
* `.FirstOrDefault()` + `Task.FromResult(...)` → `await ... .FirstOrDefaultAsyncFlex()` and return directly

***

#### Step 7: AppSettings Changes Summary

Add these sections if missing (merge into your environment-specific appsettings).

**OpenTelemetry**

```json
"OpenTelemetry": {
  "Enabled": true,
  "ServiceVersion": "1.0.0",
  "OtlpExporter": {
    "Enabled": false,
    "Endpoint": "http://localhost:4317"
  }
}
```

**FlexEfCore**

```json
"FlexEfCore": {
  "AuditTrail": {
    "Enabled": true,
    "IncludeAdded": true,
    "IncludeModified": true,
    "IncludeDeleted": true,
    "CaptureOldValues": true,
    "CaptureNewValues": true
  },
  "SoftDelete": {
    "Enabled": true
  }
}
```

**RateLimiting (Optional)**

```json
"RateLimiting": {
  "Enabled": true,
  "FixedWindow": {
    "Enabled": true,
    "PermitLimit": 100,
    "WindowSeconds": 60,
    "QueueLimit": 0
  },
  "PerUser": {
    "Enabled": true,
    "PermitLimit": 50,
    "WindowSeconds": 60
  },
  "PerIp": {
    "Enabled": true,
    "PermitLimit": 30,
    "WindowSeconds": 60
  }
}
```

***

#### Step 8: Subscriber Idempotency (Optional)

Subscriber idempotency ensures each subscriber processes a given event only once (even if the bus retries delivery).

**Configuration**

```json
"FlexIdempotency": {
  "Enabled": true,
  "StoreType": "Cache",
  "DefaultTimeToLiveDays": 7,
  "KeyPrefix": "flex:idempotency",
  "EnableAutoCleanup": false,
  "CleanupBatchSize": 1000
}
```

```json
"FlexCache": {
  "MaxPayloadBytes": 1048576,
  "DefaultExpirationMinutes": 60
}
```

**Startup wiring**

Call this during service registration (where you register other Flex services):

```csharp
services.AddFlexIdempotency(configuration);
```

> If your solution does not have the EF Core idempotency package/namespace available yet, keep `StoreType` as `Cache`.

***

#### Step 9: AI-Assisted Upgrade Prompt

```
You are upgrading an existing FlexBase application to FlexBase 10.0.0-Dev-Build026.

Goal: Apply ONLY the changes described in this page, and ensure the solution builds.

Tasks:
1) Update appsettings files:
   - Add OpenTelemetry, FlexEfCore.
   - (Optional) Add RateLimiting.
   - (Optional) Add FlexIdempotency and FlexCache.

2) Apply code changes:
   - Exception handling: use FlexExceptionFilter and add app.UseFlexExceptionHandler() after CORS.
   - (Optional) Add rate limiting registration and middleware.
   - Ensure EF Core features are registered via AddFlexEfCoreFeatures(configuration).
   - Update generated queries/handlers to use *AsyncFlex methods.
   - (Optional) Add subscriber idempotency by wiring services.AddFlexIdempotency(configuration).

3) Validate:
   - Run dotnet build for the full solution.
   - If build fails, report the exact error and fix only what’s required for this upgrade.

Constraints:
- Do not add unrelated features.
- Keep changes minimal and consistent with existing solution structure.
```

***

## FlexBase 9 to 10 Migration Steps

These steps help you align an existing FlexBase 9 solution with the FlexBase 10 solution structure.

> The older folder structure is still supported, so you can upgrade and run without doing these immediately. That said, adopting the newer structure typically improves navigation, consistency across modules, and the overall visual organization of the solution.

### Step 1: Folder Structure Alignment

FlexBase 10 introduces a cleaner application structure that groups related concerns together (contracts vs orchestration vs business logic). This is the first recommended step when moving from FlexBase 9 to 10.

#### Target Folder Layout (FlexBase 10)

Below is the recommended **FlexBase 10 folder structure**. Replace `{YourApplication}` with your application name.

```
{SolutionRoot}/
  DevNotes/                       (optional)

  {YourApplication}.Application/
    ControlContracts/
      {YourApplication}.DTOs/
        {YourApplication}.DTOs.csproj
      {YourApplication}.Messages/
        {YourApplication}.Messages.csproj
      {YourApplication}.SharedEvents/
        {YourApplication}.SharedEvents.csproj

    ControlHub/
      {YourApplication}.CronJobs/
        {YourApplication}.CronJobs.csproj
      {YourApplication}.WebControllers/
        {YourApplication}.WebControllers.csproj

    Domain/
      {YourApplication}.CommonLib/
        {YourApplication}.CommonLib.csproj
      {YourApplication}.DomainModels/
        {YourApplication}.DomainModels.csproj
      {YourApplication}.DomainModels.Tests/
        {YourApplication}.DomainModels.Tests.csproj
      {YourApplication}.Mappers/
        {YourApplication}.Mappers.csproj

    DomainHandler/
      {YourApplication}.Handlers/
        {YourApplication}.Handlers.csproj
      {YourApplication}.Handlers.Tests/
        {YourApplication}.Handlers.Tests.csproj
      {YourApplication}.PreBus/
        {YourApplication}.PreBus.csproj
      {YourApplication}.PreBus.Tests/
        {YourApplication}.PreBus.Tests.csproj
      {YourApplication}.Queries/
        {YourApplication}.Queries.csproj
      {YourApplication}.Queries.Tests/
        {YourApplication}.Queries.Tests.csproj
      {YourApplication}.RESTClients/
        {YourApplication}.RESTClients.csproj

    EndPoints/
      DbMigrations/
        {YourApplication}.Migrations.SqlServer/
          {YourApplication}.Migrations.SqlServer.csproj
        {YourApplication}.Migrations.PostgreSql/
          {YourApplication}.Migrations.PostgreSql.csproj
        {YourApplication}.Migrations.Tenant.SqlServer/
          {YourApplication}.Migrations.Tenant.SqlServer.csproj
        {YourApplication}.Migrations.Tenant.PostgreSql/
          {YourApplication}.Migrations.Tenant.PostgreSql.csproj

      {YourApplication}.EndPoint.CommonConfigs/
        {YourApplication}.EndPoint.CommonConfigs.csproj
      {YourApplication}.EndPoint.CronJob/
        {YourApplication}.EndPoint.CronJob.csproj
      {YourApplication}.EndPoint.Handlers.Default/
        {YourApplication}.EndPoint.Handlers.Default.csproj
      {YourApplication}.EndPoint.Subscribers.Default/
        {YourApplication}.EndPoint.Subscribers.Default.csproj
      {YourApplication}.EndPoint.WebAPI/
        {YourApplication}.EndPoint.WebAPI.csproj

    Infrastructure/
      Bus/
        {YourApplication}.Nsb/
          {YourApplication}.Nsb.csproj
      Db/
        {YourApplication}.BaseEF/
          {YourApplication}.BaseEF.csproj
        {YourApplication}.BaseEF.SqlServer/
          {YourApplication}.BaseEF.SqlServer.csproj
        {YourApplication}.BaseEF.PostgreSql/
          {YourApplication}.BaseEF.PostgreSql.csproj
      Providers/
        {YourApplication}.DataStoreProviders/
          {YourApplication}.DataStoreProviders.csproj

  {YourApplication}.Framework/
    Bridge/
      {YourApplication}.AspNetCoreBridge/
        {YourApplication}.AspNetCoreBridge.csproj
      {YourApplication}.CoreBridge/
        {YourApplication}.CoreBridge.csproj
      {YourApplication}.EFCoreBridge/
        {YourApplication}.EFCoreBridge.csproj

    PostBus/
      {YourApplication}.HandlerInterfaces/
        {YourApplication}.HandlerInterfaces.csproj
      {YourApplication}.Handlers.Default.Nsb/
        {YourApplication}.Handlers.Default.Nsb.csproj
      {YourApplication}.Subscribers.Default.Nsb/
        {YourApplication}.Subscribers.Default.Nsb.csproj
```

> Note: Your solution may not include every database-specific project (e.g., only SqlServer migrations, no PostgreSql), and provider projects can vary by implementation. Keep the folder structure consistent and include only the projects that apply to your application.

#### Recommended Folder Moves / Renames

Use these mappings as guidance (project names are equivalent; focus on structure):

1. **Queries**

* Old: `Application/Domain/{ProjectName}.Queries/`
* New: `Application/DomainHandler/{ProjectName}.Queries/`

2. **DTOs / Messages / Shared Events**

* Old: `Application/Dto/...`
* New: `Application/ControlContracts/...`

3. **Orchestration**

* Old: `Application/Orchestration/...`
* New: `Application/ControlHub/...`

4. **PreBus + REST Clients**

* Old: `Application/PreBus/...` and `Application/Orchestration/{ProjectName}.RESTClients/...`
* New: `Application/DomainHandler/{ProjectName}.PreBus/...` and `Application/DomainHandler/{ProjectName}.RESTClients/...`

5. **Handlers**

* Old: `Application/PostBus/{ProjectName}.Handlers.Plugins/...`
* New: `Application/DomainHandler/{ProjectName}.Handlers/`
  * Suggested subfolders: `CommandHandlers/` and `Subscribers/`

6. **Infrastructure Providers**

* Ensure `Application/Infrastructure/Providers/` exists for provider-related code (and keep `Bus/` and `Db/` alongside it).

#### Naming Convention Update (NSB Handlers)

* Old pattern: `*CommandHandler.cs`
* New pattern: `*NsbHandler.cs`

This typically means renaming both the file and class suffix from `CommandHandler` → `NsbHandler`.
