Bazlama.AsyncOperationSuite.Mvc 1.0.2

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

Bazlama.AsyncOperationSuite.Mvc

ASP.NET Core MVC extension for Bazlama.AsyncOperationSuite that provides ready-to-use REST API controllers and endpoints for managing asynchronous operations. This package makes it incredibly easy to add a complete operation management API to your web application with just a few lines of code.

Overview

The MVC extension package provides comprehensive REST API endpoints with built-in Swagger documentation, making it simple to integrate async operation management into your ASP.NET Core applications. No need to write controllers or API endpoints manually - everything is ready to use out of the box.

Key Features

  • Ready-to-Use API Controllers: Pre-built controllers for all operation management needs
  • Flexible Registration: Add all controllers at once or register them selectively
  • Automatic Swagger Integration: Built-in OpenAPI documentation
  • Authorization Support: Optional JWT/policy-based authorization
  • Custom Route Prefixes: Configurable API endpoint paths
  • JSON Schema Support: Automatic payload type schema generation
  • Real-time Operation Monitoring: Query active operations and progress
  • Operation Cancellation: Cancel running operations via API

Installation

Install via NuGet Package Manager:

dotnet add package Bazlama.AsyncOperationSuite.Mvc

Or via Package Manager Console:

Install-Package Bazlama.AsyncOperationSuite.Mvc

Quick Start

Basic Setup

Add all controllers to your application with a single method call:

using Bazlama.AsyncOperationSuite.Extensions;
using Bazlama.AsyncOperationSuite.Storage.MemoryStorage;
using Bazlama.AsyncOperationSuite.Mvc.Extensions;

var builder = WebApplication.CreateBuilder(args);

// Add AsyncOperationSuite services
builder.Services.AddAsyncOperationSuiteMemoryStorage();
builder.Services.AddAsyncOperationSuiteService(builder.Configuration);

// Add all MVC controllers
builder.Services.AddControllers();
builder.Services.AddAsyncOperationSuiteMvcAllControllers(requireAuthorization: false);

// Add Swagger
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

That's it! Your API is ready with all operation management endpoints.

Selective Controller Registration

Register only the controllers you need:

// Only operation publishing endpoints
builder.Services.AddAsyncOperationSuiteMvcOperationPublish(requireAuthorization: false);

// Only operation query endpoints
builder.Services.AddAsyncOperationSuiteMvcOperationQuery(requireAuthorization: false);

// Only payload type endpoints
builder.Services.AddAsyncOperationSuiteMvcOperationPayload(requireAuthorization: false);

Custom Route Prefix

Customize the API route prefix:

builder.Services.AddAsyncOperationSuiteMvcAllControllers(
    requireAuthorization: false,
    prefix: "api/operations"
);

// Endpoints will be available at: /api/operations/publish, /api/operations/query, etc.

API Endpoints

The MVC extension provides three main controllers with comprehensive endpoints:

Operation Publishing Controller

Base Route: /api/aos/publish

  • POST /api/aos/publish - Publish a new operation

    • Query parameters: payloadType, operationName, operationDescription, waitForQueueSpace, waitForPayloadSlotSpace
    • Body: JSON payload data
    • Returns: Published operation payload with operation ID
  • POST /api/aos/publish/cancel/{operationId} - Cancel a running operation

    • Query parameters: useThrowIfCancellationRequested, waitForCompletion, timeoutMs
    • Returns: 200 OK on success, 404 if not found

Operation Query Controller

Base Route: /api/aos/query

  • GET /api/aos/query/engine - Get engine information and statistics

    • Returns: Engine info (worker count, queue size, active operations)
  • GET /api/aos/query/active - Get all active operations

    • Returns: List of currently running operations
  • GET /api/aos/query/operations - Query operations with filters

    • Query parameters: startDate, endDate, status, ownerId, search, isDesc, pageNumber, pageSize
    • Returns: Paginated list of operations
  • GET /api/aos/query/operation/{operationId} - Get operation by ID

    • Returns: Operation details
  • GET /api/aos/query/operation/{operationId}/payload - Get operation payload

    • Returns: Operation payload data
  • GET /api/aos/query/operation/{operationId}/result - Get operation result

    • Returns: Operation result
  • GET /api/aos/query/operation/{operationId}/progress - Get latest operation progress

    • Returns: Latest progress update
  • GET /api/aos/query/operation/{operationId}/progress/all - Get all operation progress updates

    • Returns: Complete progress history
  • GET /api/aos/query/payload/{payloadId} - Get payload by ID

    • Returns: Payload data
  • GET /api/aos/query/payload/{payloadId}/progress - Get payload progress

    • Returns: Latest progress for payload
  • GET /api/aos/query/payload/{payloadId}/progress/all - Get all payload progress

    • Returns: Complete progress history for payload
  • GET /api/aos/query/result/{resultId} - Get result by ID

    • Returns: Result data

Payload Controller

Base Route: /api/aos/payload

  • GET /api/aos/payload - Get all registered payload types

    • Returns: Dictionary of payload and operation type mappings
  • GET /api/aos/payload/type - Get all payload types with JSON schemas

    • Returns: Dictionary of payload types with their JSON schemas
  • GET /api/aos/payload/type/{name} - Get specific payload type schema

    • Returns: JSON schema for the specified payload type

Usage Examples

Publishing an Operation

POST /api/aos/publish?payloadType=DelayOperationPayload
Content-Type: application/json

{
  "Name": "My Test Operation",
  "Description": "Testing the async operation",
  "DelaySeconds": 5,
  "StepCount": 10
}

Response:

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "operationId": "op-123456",
  "name": "My Test Operation",
  "description": "Testing the async operation",
  "delaySeconds": 5,
  "stepCount": 10,
  "createdAt": "2025-10-27T10:30:00Z"
}

Querying Operations

GET /api/aos/query/operations?status=Running&status=Completed&pageSize=20&pageNumber=1

Response:

[
  {
    "id": "op-123456",
    "status": "Running",
    "payloadId": "550e8400-e29b-41d4-a716-446655440000",
    "startedAt": "2025-10-27T10:30:00Z",
    "progress": 45
  }
]

Getting Active Operations

GET /api/aos/query/active

Response:

{
  "activeOperations": 3,
  "operations": [
    {
      "operationId": "op-123456",
      "payloadType": "DelayOperationPayload",
      "status": "Running",
      "progress": 45
    }
  ]
}

Getting Payload Types

GET /api/aos/payload/type

Response:

{
  "DelayOperationPayload": {
    "type": "object",
    "properties": {
      "delaySeconds": { "type": "integer" },
      "stepCount": { "type": "integer" },
      "name": { "type": "string" },
      "description": { "type": "string" }
    }
  }
}

Canceling an Operation

POST /api/aos/publish/cancel/op-123456?waitForCompletion=true&timeoutMs=5000

Authorization

The MVC extension supports flexible authorization configurations:

No Authorization (Development)

builder.Services.AddAsyncOperationSuiteMvcAllControllers(requireAuthorization: false);

JWT Authentication (Production)

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;

// Configure JWT authentication
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidAudience = builder.Configuration["Jwt:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(
                Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
        };
    });

// Require authorization for all controllers
builder.Services.AddAsyncOperationSuiteMvcAllControllers(requireAuthorization: true);

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

Policy-Based Authorization

// Define policies
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("OperationAdmin", policy =>
        policy.RequireRole("Admin", "OperationManager"));
});

// Apply policy to controllers
builder.Services.AddAsyncOperationSuiteMvcOperationPublish(
    requireAuthorization: true,
    policyName: "OperationAdmin"
);

builder.Services.AddAsyncOperationSuiteMvcOperationQuery(
    requireAuthorization: false
);

Selective Authorization

// Public read access, protected write access
builder.Services.AddAsyncOperationSuiteMvcOperationQuery(requireAuthorization: false);
builder.Services.AddAsyncOperationSuiteMvcOperationPayload(requireAuthorization: false);
builder.Services.AddAsyncOperationSuiteMvcOperationPublish(requireAuthorization: true);

Swagger Integration

The MVC extension works seamlessly with Swagger/OpenAPI:

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
    options.SwaggerDoc("v1", new OpenApiInfo
    {
        Title = "Async Operation Suite API",
        Version = "v1",
        Description = "API for managing asynchronous operations"
    });

    // Add JWT authentication to Swagger
    options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Description = "JWT Authorization header using the Bearer scheme",
        Name = "Authorization",
        In = ParameterLocation.Header,
        Type = SecuritySchemeType.ApiKey,
        Scheme = "Bearer"
    });

    options.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type = ReferenceType.SecurityScheme,
                    Id = "Bearer"
                }
            },
            Array.Empty<string>()
        }
    });
});

app.UseSwagger();
app.UseSwaggerUI(options =>
{
    options.SwaggerEndpoint("/swagger/v1/swagger.json", "Async Operation Suite API v1");
    options.RoutePrefix = "swagger";
});

Navigate to /swagger to access the interactive API documentation.

Configuration

Extension Method Options

All registration methods support the following parameters:

  • requireAuthorization (bool): Enable authorization for the controllers (default: false)
  • policyName (string?): Optional authorization policy name
  • prefix (string): API route prefix (default: "api/aos")

Available Registration Methods

// Register all controllers
AddAsyncOperationSuiteMvcAllControllers(requireAuthorization, policyName, prefix)

// Register publish controller only
AddAsyncOperationSuiteMvcOperationPublish(requireAuthorization, policyName, prefix)

// Register query controller only
AddAsyncOperationSuiteMvcOperationQuery(requireAuthorization, policyName, prefix)

// Register payload controller only
AddAsyncOperationSuiteMvcOperationPayload(requireAuthorization, policyName, prefix)

CORS Configuration

For frontend integration, configure CORS:

builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowFrontend", policy =>
    {
        policy.WithOrigins("http://localhost:3000", "https://yourdomain.com")
              .AllowAnyMethod()
              .AllowAnyHeader();
    });
});

app.UseCors("AllowFrontend");

Frontend Integration

The API works seamlessly with any frontend framework. Example using JavaScript/TypeScript:

// Publish an operation
const response = await fetch('/api/aos/publish?payloadType=DelayOperationPayload', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer YOUR_JWT_TOKEN'
    },
    body: JSON.stringify({
        Name: 'My Operation',
        DelaySeconds: 5,
        StepCount: 10
    })
});

const result = await response.json();
console.log('Operation ID:', result.operationId);

// Poll for progress
const progressResponse = await fetch(`/api/aos/query/operation/${result.operationId}/progress`);
const progress = await progressResponse.json();
console.log('Progress:', progress.percentage);

Error Handling

The API returns standard HTTP status codes:

  • 200 OK: Successful operation
  • 400 Bad Request: Invalid payload or parameters
  • 404 Not Found: Operation/payload/result not found
  • 408 Request Timeout: Operation cancellation timeout
  • 429 Too Many Requests: Queue full or payload limit exceeded
  • 500 Internal Server Error: Server error

Example error response:

{
    "message": "Queue is full. Please try again later."
}

Best Practices

Production Deployment

  1. Enable Authorization: Always require authorization in production
builder.Services.AddAsyncOperationSuiteMvcAllControllers(requireAuthorization: true);
  1. Use HTTPS: Ensure SSL/TLS is configured
app.UseHttpsRedirection();
  1. Configure Rate Limiting: Protect against abuse
builder.Services.AddRateLimiter(options => { /* configuration */ });
  1. Enable Logging: Monitor API usage
{
  "Logging": {
    "LogLevel": {
      "Bazlama.AsyncOperationSuite.Mvc": "Information"
    }
  }
}

Performance Optimization

  1. Use Pagination: Always use pagination for operation queries
  2. Filter Results: Use date ranges and status filters
  3. Cache Payload Types: Cache the payload type schemas on the frontend
  4. Use SQL Storage: For production, use SQL Server storage instead of memory

Sample Application

The repository includes a complete sample application demonstrating all features:

cd sample/api
dotnet run

Visit https://localhost:5292/swagger to explore the API.

Troubleshooting

Controllers Not Registered

Make sure you've called AddControllers() before adding AsyncOperationSuite controllers:

builder.Services.AddControllers();
builder.Services.AddAsyncOperationSuiteMvcAllControllers();

Routes Not Working

Ensure MapControllers() is called:

app.MapControllers();

Authorization Issues

Check that authentication middleware is added before authorization:

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

Swagger Not Showing Endpoints

Make sure controllers are registered before Swagger:

builder.Services.AddControllers();
builder.Services.AddAsyncOperationSuiteMvcAllControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

Requirements

  • .NET 8.0 or later
  • ASP.NET Core 8.0 or later
  • Bazlama.AsyncOperationSuite (core package)

Dependencies

  • Microsoft.AspNetCore.App framework
  • NJsonSchema (for JSON schema generation)
  • Bazlama.AsyncOperationSuite (core package)

License

This project is licensed under the MIT License.

Author

Murat Budun - GitHub

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  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
1.0.2 249 10/27/2025
1.0.1 221 10/27/2025