ScopeBus 1.1.1

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

ScopeBus

ScopeBus is a clean and extensible mediator framework for .NET, supporting CQRS, domain events, pipelines, and flexible handler behaviors — with automatic handler registration, minimal ceremony, and maximum control.

Features

  • Modular Design: Easily extendable and customizable to fit your needs.
  • Mediator Pattern: Implements the mediator pattern to decouple components and promote clean architecture.
  • CQRS Support: Built-in support for Command Query Responsibility Segregation (CQRS) to separate read and write operations.
  • Domain-Driven Design (DDD): Facilitates the implementation of DDD principles for better organization and maintainability of your code.
  • Minimal Setup: Quick and easy to set up, allowing you to focus on building your application rather than configuring the framework.
  • Flexible Pipeline: Create custom pipelines to handle various scenarios, including validation, logging, and error handling.
  • Asynchronous Support: Built-in support for asynchronous operations, making it suitable for modern applications.
  • Dependency Injection: Seamless integration with popular dependency injection frameworks, such as Microsoft.Extensions.DependencyInjection.
  • Cross-Cutting Concerns: Easily manage cross-cutting concerns like logging, caching, and validation through middleware components.
  • Testable: Designed with testability in mind, making it easy to write unit tests for your components.
  • Open Source: Free to use and modify under the MIT License.
  • Documentation: Comprehensive documentation and examples to help you get started quickly.
  • Community Support: Active community and support channels to help you with any questions or issues you may encounter.
  • Performance: Optimized for performance, ensuring that your application runs smoothly even under heavy load.

Getting Started

To get started with ScopeBus, follow these steps:

  1. Install the NuGet package:

    dotnet add package ScopeBus
    
  2. Add the necessary using directives in your code:

     using ScopeBus;
     services.AddScopeBus();
    

Why ScopeBus?

  • You're building a clean architecture application and need a flexible mediator
  • You want CQRS without being locked into MediatR’s conventions
  • You need pre/post pipeline behaviors, auditing, and domain events
  • You want automatic handler registration — no manual DI
  • You need to support streaming, retries, and granular tracing in one pipeline

Define Your Request Handler

ScopeBus will automatically register the handler for you

public class MyRequest : IRequest<MyResponse>
{
    public string Name { get; set; }
}

public class MyRequestHandler : IRequestHandler<MyRequest, MyResponse>
{
    public Task<MyResponse> Handle(MyRequest request, CancellationToken cancellationToken)
    {
        return Task.FromResult(new MyResponse { Message = $"Hello, {request.Name}!" });
    }
}


  1. Send a Request

[ApiController]
[Route("api/[controller]")]
public class MyController : ControllerBase
{
    private readonly IMediator _bus;

    public MyController(IMediator bus)
    {
        _bus = bus;
    }

    [HttpPost]
    public async Task<IActionResult> Get(MyRequest request)
    {
        var response = await _bus.Send(request);
        return Ok(response);
    }
}

Define Your Audit Handler

How Audit Handlers Work

  1. PreAuditAsync: This method is called before the command handler executes. You can use it to log or perform any other actions before the main logic runs.
  2. PostAuditAsync: This method is called after the command handler executes. You can use it to log or perform any other actions after the main logic has completed. This allows you to separate the auditing logic from the main command handler, making your code cleaner and more maintainable. NB: ScopeBus will automatically register the handler for you


public class DeleteEmployeeRequest : ICommand<ApiResponse<string>>
{
    public string? EmployeeId { get; set; }
}

public class DeleteEmployeeAuditHandler : IAuditableCommandHandler<DeleteEmployeeRequest, ApiResponse<string>>
{
    private readonly ILogger<DeleteEmployeeAuditHandler> _logger;
    private readonly IHttpContextAccessor _context;

    public DeleteEmployeeAuditHandler(ILogger<DeleteEmployeeAuditHandler> logger, IHttpContextAccessor context)
    {
        _logger = logger;
        _context = context;
    }

    public Task PreAuditAsync(DeleteEmployeeRequest request, CancellationToken cancellationToken)
    {
        var user = _context.HttpContext?.User?.Identity?.Name ?? "anonymous";
        _logger.LogInformation($"[PRE] {user} requested to delete employee {request.EmployeeId}");
        return Task.CompletedTask;
    }

    public Task PostAuditAsync(DeleteEmployeeRequest request, ApiResponse<string> response, CancellationToken cancellationToken)
    {
        var user = _context.HttpContext?.User?.Identity?.Name ?? "anonymous";
        _logger.LogInformation($"[POST] {user} deleted employee {request.EmployeeId} with result: {response.Code}");
        return Task.CompletedTask;
    }
}


Define Your Query Handler

ScopeBus will automatically register the handler for you Note: How Query Handlers Work QueryHandler is mostly intended for read operations. It is a simple interface that defines a single method, Handle, which takes a query object and returns a result. The query object can be any type that implements the IQuery<T> interface, where T is the type of the result.

The Query handler is used to retrieve data and cache it for later use. You can use it to implement caching strategies, such as in-memory caching or distributed caching, to improve performance and reduce database load. To Provide a custom implementation of ICachingProvider, Create a class that implements the ICachingProvider interface and register it with the DI container. Eg: builder.Services.AddScoped<ICacheProvider, RedisCacheProvider>();

if your Model or DTO extends IQuery<T>, Then caching provider will be automatically registered for you which uses immemory caching. Unless otherwise you specified your own Caching provider as stated above.

public class GetEmployeeQuery : IQuery<Employee>
{
    public int EmployeeId { get; set; }
}

public class GetEmployeeQueryHandler : IQueryHandler<GetEmployeeQuery, Employee>
{
    private readonly IEmployeeRepository _repository;

    public GetEmployeeQueryHandler(IEmployeeRepository repository)
    {
        _repository = repository;
    }

    public async Task<Employee> Handle(GetEmployeeQuery request, CancellationToken cancellationToken)
    {
        return await _repository.GetByIdAsync(request.EmployeeId);
    }
}


Auditing

Your request DTO should implement the ICommand<TResponse> interface, where TResponse is the type of the response you expect from the command handler. How Audit Handlers Work

  1. PreAuditAsync: This method is called before the command handler executes. You can use it to log or perform any other actions before the main logic runs.
  2. PostAuditAsync: This method is called after the command handler executes. You can use it to log or perform any other actions after the main logic has completed. This allows you to separate the auditing logic from the main command handler, making your code cleaner and more maintainable.

public class DeleteEmployeeRequest : ICommand<ApiResponse<string>>
{
    public int EmployeeId { get; set; }
}


public class DeleteEmployeeAuditHandler : IAuditableCommandHandler<DeleteEmployeeRequest, ApiResponse<string>>
{
    private readonly ILogger<DeleteEmployeeAuditHandler> _logger;
    private readonly IHttpContextAccessor _context;

    public DeleteEmployeeAuditHandler(ILogger<DeleteEmployeeAuditHandler> logger, IHttpContextAccessor context)
    {
        _logger = logger;
        _context = context;
    }

    public Task PreAuditAsync(DeleteEmployeeRequest request, CancellationToken cancellationToken)
    {
        var user = _context.HttpContext?.User?.Identity?.Name ?? "anonymous";
        _logger.LogInformation($"[PRE] {user} requested to delete employee {request.EmployeeId}");
        return Task.CompletedTask;
    }

    public Task PostAuditAsync(DeleteEmployeeRequest request, ApiResponse<string> response, CancellationToken cancellationToken)
    {
        var user = _context.HttpContext?.User?.Identity?.Name ?? "anonymous";
        _logger.LogInformation($"[POST] {user} deleted employee {request.EmployeeId} with result: {response.Code}");
        return Task.CompletedTask;
    }
}

Validation

How Validation Handlers Work

  1. ValidationHandler is a simple interface that defines a single method, ValidateAsync, which takes a request object and returns a list of validation errors.
  2. The request object can be any type that implements the IValidatable interface, which contains the properties to be validated.
  3. The validation handler is used to validate the request object before it is processed by the command handler.
  4. If the validation fails, the command handler will not be executed, and the validation errors will be returned to the client.
  5. You can use any validation library, such as FluentValidation or DataAnnotations, to implement the validation logic.
  6. You can also create custom validation attributes to validate specific properties of the request object.
  7. The validation handler is registered with the DI container, and ScopeBus will automatically resolve it when processing the request.

NB: ScopeBus will automatically register the handler for you


public class EmployeeRequestValidator : IValidator<EmployeeRequest>
{
    public Task<IEnumerable<ErrorResponse>> ValidateAsync(EmployeeRequest request, CancellationToken cancellationToken)
    {
        var errors = new List<ErrorResponse>();

        if (string.IsNullOrWhiteSpace(request.FirstName))
            errors.Add(new ErrorResponse(nameof(request.FirstName), "First name is required"));

        if (string.IsNullOrWhiteSpace(request.LastName))
            errors.Add(new ErrorResponse(nameof(request.LastName), "Last name is required"));

        return Task.FromResult<IEnumerable<ErrorResponse>>(errors);
    }
}

INotification

How Notification Handlers Work

  1. NotificationHandler is a simple interface that defines a single method, Handle, which takes a notification object and returns a Task.
  2. The notification object can be any type that implements the INotification interface, which contains the properties to be notified.
  3. The notification handler is used to notify other components of an event that has occurred in the system.
  4. You can use it to implement event-driven architectures, where components communicate with each other through events.
  5. The notification handler is registered with the DI container, and ScopeBus will automatically resolve it when processing the notification.

In the handler for creating employee, after creating the employee, call the OnCreated method to trigger the domain event. This will send the notification to the registered handlers.

NB: ScopeBus will automatically register the handler for you


public class Employee:EventEntity
{
    public string? Id { get; set; } = Guid.NewGuid().ToString("N");
    public DateTime CreatedAt { get; set; }= DateTime.UtcNow;
    public string? FirstName { get; set; }
    public string? LastName { get; set; }
    public string? Email { get; set; }
    
    public void OnCreated()
    {
        AddDomainEvent(new EmployeeCreatedEvent
        {
            Employee =this
        });
    }
    
  
}

public class EmployeeCreatedNotification : INotification
{
    public Employee? Employee { get; set; }
}

public class EmployeeCreatedNotificationHandler : INotificationHandler<EmployeeCreatedNotification>
{
    private readonly ILogger<EmployeeCreatedNotificationHandler> _logger;

    public EmployeeCreatedNotificationHandler(ILogger<EmployeeCreatedNotificationHandler> logger)
    {
        _logger = logger;
    }

    public Task Handle(EmployeeCreatedNotification notification, CancellationToken cancellationToken)
    {
        _logger.LogInformation($"Employee created: {notification.Employee?.FirstName} {notification.Employee?.LastName}");
        return Task.CompletedTask;
    }
}

Roles And Permissions

How Roles And Permissions Handlers Work

  1. Roles and permissions handlers are used to manage user roles and permissions in the system.
  2. They provide methods to check if a user has a specific role or permission, and to assign roles and permissions to users.
  3. You can use them to implement role-based access control (RBAC) in your application.
  4. The roles and permissions handlers are registered with the DI container, and ScopeBus will automatically resolve them when processing the request.
  5. You can also create custom roles and permissions to fit your application's needs.
  6. You can use any authentication and authorization library, such as ASP.NET Core Identity or IdentityServer, to implement the roles and permissions logic.
  7. Roles are extracted from the JWT token and stored in the ClaimsIdentity of the user.
  8. The roles are checked against the permissions defined in the system.
  9. The roles and permissions handlers will only work if you enable authentication and authorization in your application.
  10. Your request DTO should extend the IAuthorizedRequest interface, which contains the properties to be checked for authorization.
   public class EmployeeRequest:IRequest<ApiResponse<Employee>>,IAuthorizedRequest
   {
       public string? FirstName { get; set; }
       public string? LastName { get; set; }
       public string? Email { get; set; }
       
       /*
       This property is used to specify the required roles for the command
       It is used to check if the user has the required roles before executing the command
       If the user does not have the required roles, an access denied exception will be raised preventing the execution of the command
       */
       public string[] RequiredRoles => ["HR.Manager", "Admin"];
   }

Streams Request

How Streams Request Handlers Work

  1. Streams request handlers are used to process large amounts of data in a streaming fashion.
  2. They provide methods to read and write data in a streaming manner, allowing you to process data as it arrives.
  3. You can use them to implement streaming APIs, where data is sent and received in chunks rather than all at once.
  4. The streams request handlers are registered with the DI container, and ScopeBus will automatically resolve them when processing the request. The StreamRequestHandler interface is used to process the request and return a stream of data. The StreamHandler will invoke any handler that is registered for the request type.

Example:

   public class StreamEmployeesRequest : IStreamRequest<Employee>
   {
       public int Count { get; set; } = 5;
   }
   
    public class StreamEmployeesRequestHandler : IStreamRequestHandler<StreamEmployeesRequest, Employee>
    {
         public async IAsyncEnumerable<Employee> Handle(StreamEmployeesRequest request, [EnumeratorCancellation] CancellationToken cancellationToken)
         {
              for (int i = 0; i < request.Count; i++)
              {
                yield return new Employee
                {
                     Id = Guid.NewGuid().ToString("N"),
                     FirstName = $"FirstName {i}",
                     LastName = $"LastName {i}",
                     Email = $"Email {i}"
                };
              }
         }
    }
    
    //Controller Call
    [ApiController]
    [Route("api/[controller]")]
    public class EmployeeController : ControllerBase
    {
        private readonly IMediator _bus;

        public EmployeeController(IMediator bus)
        {
            _bus = bus;
        }
        
       [HttpGet("stream")]
       public async Task<IActionResult> StreamEmployees([FromQuery] StreamEmployeesRequest request)
       {
           var stream = _bus.Stream(request);
           //Do something with the stream
       }
    }
    

Retry Flaky Requests

How Retry Handlers Work

  1. Retry handlers are used to automatically retry failed requests in a configurable manner.
  2. They provide methods to specify the number of retries, the delay between retries, and the conditions under which to retry.
  3. You can use them to implement retry policies for transient failures, such as network errors or timeouts.
  4. The retry handlers are registered with the DI container, and ScopeBus will automatically resolve them when processing the request.

Example.

   public class RetryRequest : IRequest<ApiResponse<string>>
   {
       public string? Name { get; set; }
   }

   public class RetryRequestHandler : IRequestHandler<RetryRequest, ApiResponse<string>>
   {
       private static int _attempt = 0;

       public async Task<string> Handle(RetryRequest request, CancellationToken cancellationToken)
       {
           await Task.CompletedTask;
           _attempt++;
   
           Console.WriteLine($"Attempt #{_attempt} at handling FlakyRequest");
   
           if (_attempt < 3)
           {
               throw new InvalidOperationException("Simulated transient failure");
           }
   
           return $"Recovered successfully after {_attempt} attempts. Message: {request.Message}";
       }
   }

PreProcessing and PostProcessing

How PreProcessing and PostProcessing Handlers Work

  1. PreProcessing and PostProcessing handlers are used to perform actions before and after the request is processed.
  2. They provide methods to specify the actions to be performed, such as logging, caching, or modifying the request or response.
  3. You can use them to implement cross-cutting concerns, such as logging, caching, or validation.
  4. The pre-processing and post-processing handlers are registered with the DI container, and ScopeBus will automatically resolve them when processing the request.
  5. Your PreProcessing and PostProcessing handlers should implement the IRequestPreProcessor<TRequest> and IRequestPostProcessor<TRequest, TResponse> interfaces, respectively. Example.

    //PreProcessing
   public class EmployeePreProcessHandler : IRequestPreProcessor<EmployeeRequest>
   {
       private readonly ILogger<EmployeePreProcessHandler> _logger;
   
       public EmployeePreProcessHandler(ILogger<EmployeePreProcessHandler> logger)
       {
           _logger = logger;
       }
   
       public Task Process(EmployeeRequest request, CancellationToken cancellationToken)
       {
           _logger.LogInformation($"[PRE] Processing EmployeeRequest at {DateTime.UtcNow}");
           return Task.CompletedTask;
       }
   }
   
   //PostProcessing
   public class EmployeePostProcessHandler : IRequestPostProcessor<EmployeeRequest, ApiResponse<Employee>>
   {
       private readonly ILogger<EmployeePostProcessHandler> _logger;
   
       public EmployeePostProcessHandler(ILogger<EmployeePostProcessHandler> logger)
       {
           _logger = logger;
       }
   
       public Task Process(EmployeeRequest request, ApiResponse<Employee> response, CancellationToken cancellationToken)
       {
           _logger.LogInformation($"[POST] EmployeeRequest returned {response.GetType().Name} with status: {response.Code}");
           return Task.CompletedTask;
       }
   }

Auditing

How Audit Handlers Work

  1. Audit handlers are used to log and track the actions performed in the system.
  2. They provide methods to specify the actions to be logged, such as the request and response data, the user who performed the action, and the timestamp.
  3. You can use them to implement auditing and logging for compliance and security purposes.
  4. The audit handlers are registered with the DI container, and ScopeBus will automatically resolve them when processing the request.
  5. The Auditing handlers provides you with two methods: PreAuditAsync and PostAuditAsync.

Example: Implementing Audit for Employee Delete

Your request DTO should implement the ICommand<TResponse> interface, where TResponse is the type of the response you expect from the command handler. The ICommand<TResponse> interface is used to define a command that can be executed by the command handler. The PreAuditAsync method is called before the handler of your request executes, and the PostAuditAsync method is called after the command handler executes. The PostAuditAsync method is called after the Handler for your request is executed.

   public class DeleteEmployeeRequest : ICommand<ApiResponse<string>>
   {
       public string? EmployeeId { get; set; }
   }

   public class DeleteEmployeeAuditHandler : IAuditableCommandHandler<DeleteEmployeeRequest, ApiResponse<string>>
   {
       private readonly ILogger<DeleteEmployeeAuditHandler> _logger;
       private readonly IHttpContextAccessor _context;
   
       public DeleteEmployeeAuditHandler(ILogger<DeleteEmployeeAuditHandler> logger, IHttpContextAccessor context)
       {
           _logger = logger;
           _context = context;
       }
   
       public Task PreAuditAsync(DeleteEmployeeRequest request, CancellationToken cancellationToken)
       {
           var user = _context.HttpContext?.User?.Identity?.Name ?? "anonymous";
           _logger.LogInformation($"[PRE] {user} requested to delete employee {request.EmployeeId}");
           return Task.CompletedTask;
       }
   
       public Task PostAuditAsync(DeleteEmployeeRequest request, ApiResponse<string> response, CancellationToken cancellationToken)
       {
           var user = _context.HttpContext?.User?.Identity?.Name ?? "anonymous";
           _logger.LogInformation($"[POST] {user} deleted employee {request.EmployeeId} with result: {response.Code}");
           return Task.CompletedTask;
       }
   }

This ensures that the auditing logic is separated from the main command handler, making your code cleaner and more maintainable.

Telemetry and Logging: CorrelationHandler

How Correlation Handlers Work

  1. Correlation handlers are used to track and correlate requests and responses in the system.
  2. They provide methods to specify the correlation ID, which is used to identify and track requests and responses across different components and services.
  3. You can use them to implement distributed tracing and logging for better observability and debugging.
  4. The correlation handlers are registered with the DI container, and ScopeBus will automatically resolve them when processing the request.
  5. The Correlation handlers provides you with two methods: OnStartAsync and OnCompleteAsync.
  6. The OnStartAsync method is called before the handler of your request executes, and the OnCompleteAsync method is called after the command handler executes.
  7. Your Correlation handler should implement the ICorrelationHandler interface, which contains the methods to be called for tracking requests and responses.

Example: Create Your CorrelationHandler to Track Requests and Responses

   public class DefaultCorrelationHandler : ICorrelationHandler
   {
       private readonly ILogger<DefaultCorrelationHandler> _logger;
   
       public DefaultCorrelationHandler(ILogger<DefaultCorrelationHandler> logger)
       {
           _logger = logger;
       }
   
       public Task OnStartAsync(string traceId, object request, CancellationToken cancellationToken)
       {
           _logger.LogInformation("[Global TRACE Start] {TraceId} for {RequestType}", traceId, request.GetType().Name);
           return Task.CompletedTask;
       }
   
       public Task OnCompleteAsync(string traceId, object request, object response, long durationMs, CancellationToken cancellationToken)
       {
           _logger.LogInformation("[Global TRACE End] {TraceId} ({Duration} ms)", traceId, durationMs);
           return Task.CompletedTask;
       }
   }

This ensures that the correlation logic is separated from the main command handler, making your code cleaner and more maintainable.

ScopeBus Logging

ScopeBus supports a flexible and extensible logging pipeline using a built-in LoggingBehavior<TRequest, TResponse>. Logging is opt-in, meaning it only activates for requests that implement a custom hook interface, giving you full control over what and how you log.

  • Hook-based logging – opt-in per request
  • Full access to request, response, and exception data
  • No boilerplate logging in your handlers
  • Works for commands, queries, or any request type

🧩 How It Works

ScopeBus includes a default logging pipeline behavior: To enable logging for a request, implement the ILoggingHook interface,

public interface ILoggingHook<TRequest, TResponse>
{
    Task OnLogStartAsync(TRequest request, CancellationToken cancellationToken);
    Task OnLogCompleteAsync(TRequest request, TResponse response, CancellationToken cancellationToken);
    Task OnLogExceptionAsync(TRequest request, Exception ex, CancellationToken cancellationToken);
}

This interface provides three methods:

  1. OnLogStartAsync: Called before the request is sent to the handler.
  2. OnLogCompleteAsync: Called after the request is completed successfully.
  3. OnLogExceptionAsync: Called if an exception occurs during request processing.

Example:

   public class CreateEmployeeLoggingHook : ILoggingHook<CreateEmployeeRequest, ApiResponse<Employee>>
   {
       private readonly ILogger<CreateEmployeeLoggingHook> _logger;
   
       public CreateEmployeeLoggingHook(ILogger<CreateEmployeeLoggingHook> logger)
       {
           _logger = logger;
       }
   
       public Task OnLogStartAsync(CreateEmployeeRequest request, CancellationToken cancellationToken)
       {
           _logger.LogInformation("[LOGGING] Starting CreateEmployeeRequest for: {Email}", request.Email);
           return Task.CompletedTask;
       }
   
       public Task OnLogCompleteAsync(CreateEmployeeRequest request, ApiResponse<Employee> response, CancellationToken cancellationToken)
       {
           _logger.LogInformation("[LOGGING] Completed CreateEmployeeRequest with status {Status}", response.Code);
           return Task.CompletedTask;
       }
   
       public Task OnLogExceptionAsync(CreateEmployeeRequest request, Exception ex, CancellationToken cancellationToken)
       {
           _logger.LogError(ex, "[LOGGING] Exception during CreateEmployeeRequest for: {Email}", request.Email);
           return Task.CompletedTask;
       }
   }

🧪 Testing

ScopeBus is testable by design. You can mock IMediator, inject handlers directly, or use test doubles for pipeline behaviors.

We recommend creating a custom TestScopeBus helper for integration testing command/response flow.

License

This project is licensed under the MIT License.

Architecture

alternate text is missing from this package README image

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 (1)

Showing the top 1 NuGet packages that depend on ScopeBus:

Package Downloads
DotnetCqrsPgTemplate.Api

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.1 101 7/16/2025
1.1.0 85 7/15/2025
1.0.31 89 7/12/2025
1.0.3 83 7/12/2025
1.0.2 122 7/10/2025
1.0.1 129 5/4/2025
1.0.0 204 4/13/2025

Version 1.1.1 Added PBAC to IAuthorized Request