![]() |
VOOZH | about |
dotnet add package BaseLib.Core --version 3.1.3
NuGet\Install-Package BaseLib.Core -Version 3.1.3
<PackageReference Include="BaseLib.Core" Version="3.1.3" />
<PackageVersion Include="BaseLib.Core" Version="3.1.3" />Directory.Packages.props
<PackageReference Include="BaseLib.Core" />Project file
paket add BaseLib.Core --version 3.1.3
#r "nuget: BaseLib.Core, 3.1.3"
#:package BaseLib.Core@3.1.3
#addin nuget:?package=BaseLib.Core&version=3.1.3Install as a Cake Addin
#tool nuget:?package=BaseLib.Core&version=3.1.3Install as a Cake Tool
BaseLib.Core is a foundational library for building backend services in .NET. It simplifies the creation of services by providing base classes that implement common patterns and functionalities.
BaseLib.Core services are platform-agnostic, meaning they can run in various environments, such as containers, Azure Functions, or AWS Lambdas.
A service represents a single backend operation and follows a Request/Response pattern.
Requests are derived from CoreRequestBase.
Example:
public class CheckoutRequest : CoreRequestBase
{
public int CustomerId { get; set; }
public string CustomerName { get; set; }
public string IdentificationNumber { get; set; }
public CreditCard? CreditCard { get; set; }
public Product[] Items{ get; set; }
}
Responses are derived from CoreResponseBase and contain a Succeeded property to indicate success.
Example:
public class CheckoutResponse : CoreResponseBase
{
public long OrderId { get; set; }
}
Services inherit from CoreServiceBase<TRequest,TResponse>, where TRequest and TResponse are your custom request and response types. The core logic is implemented in the RunAsync() method.
Example:
public class CheckoutService : CoreServiceBase<CheckoutRequest, CheckoutResponse>
{
protected override async Task<CheckoutResponse> RunAsync()
{
// Implementation logic here...
var order = await CreateOrderAsync(this.Request.CustomerId, this.Request.Items);
return new CheckoutResponse { Succeeded = true, OrderId = order.Id };
}
}
Responses include a ReasonCode, which consists of an integer value and a string description.
The ReasonCode can be assigned from Enum types. It maps the integer value from the enum's integer value and the description from the Description attribute, if present; otherwise, it uses the label of the enum value.
This approach offers a convenient way to handle Reason Codes as enums within the application.
Example:
enum EcommerceReasonCode
{
[Description("Product is not available at this time")]
NoItemsAvailable = 10448
}
public class CheckoutService : CoreServiceBase<CheckoutRequest, CheckoutResponse>
{
protected override async Task<CheckoutResponse> RunAsync()
{
if (!CheckForAvailability(this.Request.Products))
{
return new CheckoutResponse
{
Succeeded = false,
ReasonCode = EcommerceReasonCode.NoItemsAvailable
};
}
// Implementation logic here...
}
}
The ICoreStatusEventSink interface provides support for event-driven choreography between services. This capability enables the asynchronous triggering of actions in response to events.
A typical implementation of ICoreStatusEventSink publishes the event to an external publish/subscribe messaging system, subscribers of the messaging system will react to events published by the service.
In the diagram below, a CheckoutService publish an event to a Topic on a messaging system. The subscribers of this Topic receive the events and subsequently execute the 'create order' and 'create invoice' services, respectively.
flowchart LR;
s(CheckoutService) -- event --> Topic;
Topic -- event --> s1-->CreateOrderService;
Topic -- event -->s2-->CreateInvoiceService;
Service required to report events need to use the build in constructor passing the ICoreStatusEventSink.
Example:
public class CheckoutService : CoreServiceBase<CheckoutRequest, CheckoutResponse>
{
// A Constructor with the eventsink
public CheckoutService(ICoreStatusEventSink? eventsink)
: base(eventSink: eventsink)
{
}
// Implementation Logic here...
}
Some operations need to fan out work to child services and wait for all of them to complete before producing a final result. CoreLongRunningServiceBase<TRequest, TResponse> handles this pattern.
FireAsync or FireManyAsync.RunAsync completes, the framework detects pending children, serialises the service state, and suspends with status Suspended.ICoreLongRunningServiceManager triggers ResumeAsync on the parent with the saved operationId.ResumeAsync() to produce the final response.sequenceDiagram
participant Client
participant Parent as ParentService (LongRunning)
participant Fire as ICoreServiceFireOnly
participant Store as ICoreServiceStateStore
participant Manager as ICoreLongRunningServiceManager
participant Child as ChildService
Client->>Parent: RunAsync(request)
Parent->>Fire: FireManyAsync<ChildService>(requests)
Fire-->>Child: (async, fire-and-forget)
Parent->>Store: WriteAsync(operationId, state)
Parent-->>Client: Response (Suspended)
Child-->>Manager: StatusEvent (Finished)
Manager->>Parent: ResumeAsync(operationId)
Parent->>Store: ReadAsync(operationId)
Parent-->>Client: Final Response (Finished)
public class BatchInvoiceService : CoreLongRunningServiceBase<BatchInvoiceRequest, BatchInvoiceResponse>
{
private int[] _orderIds = [];
public BatchInvoiceService(
ICoreServiceFireOnly fireOnly,
ICoreServiceStateStore stateStore,
ICoreStatusEventSink? eventSink = null)
: base(fireOnly, stateStore, eventSink: eventSink) { }
protected override async Task<BatchInvoiceResponse> RunAsync()
{
_orderIds = this.Request.OrderIds;
// Fire one child per order — service suspends until all complete
await FireManyAsync<CreateInvoiceService>(
_orderIds.Select(id => new CreateInvoiceRequest { OrderId = id }));
return new BatchInvoiceResponse { Succeeded = true };
}
protected override Task<BatchInvoiceResponse> ResumeAsync()
{
// All children finished — produce final result
return Task.FromResult(new BatchInvoiceResponse
{
Succeeded = true,
InvoiceCount = _orderIds.Length
});
}
}
| Dependency | Purpose |
|---|---|
ICoreServiceFireOnly |
Dispatches child service invocations without blocking |
ICoreServiceStateStore |
Persists/restores service field state across suspension |
ICoreStatusEventSink |
(Optional) Publishes lifecycle events |
AWS implementations:
SqsCoreServiceFireOnly(fire),S3CoreServiceStateStore(state).
Pass a FluentValidation.IValidator<TRequest> to the base constructor. If validation fails, the service returns a failed response with ReasonCode = ValidationResultNotValid — RunAsync() is never called.
The WithReasonCode extension maps a domain enum value as the FluentValidation error code and message:
public class CheckoutValidator : AbstractValidator<CheckoutRequest>
{
public CheckoutValidator()
{
RuleFor(r => r.Items)
.NotEmpty()
.WithReasonCode(EcommerceReasonCode.NoItemsAvailable);
}
}
public class CheckoutService : CoreServiceBase<CheckoutRequest, CheckoutResponse>
{
public CheckoutService(ICoreStatusEventSink? eventSink = null)
: base(validator: new CheckoutValidator(), eventSink: eventSink) { }
protected override async Task<CheckoutResponse> RunAsync()
{
// Only reached when validation passes
}
}
PolymorphicConverter<T> enables serialization of polymorphic object graphs (e.g. CoreRequestBase subclasses stored in CoreStatusEvent). It embeds a ___type discriminator property with the assembly-qualified type name.
Usage — register on JsonSerializerOptions:
var options = new JsonSerializerOptions();
options.Converters.Add(new PolymorphicConverter<CoreRequestBase>());
var json = JsonSerializer.Serialize<CoreRequestBase>(myRequest, options);
var restored = JsonSerializer.Deserialize<CoreRequestBase>(json, options);
// restored is the correct concrete subclass
PolymorphicConverteris used internally byCoreSerializerwhen serialisingCoreStatusEventpayloads. You normally do not need to configure it manually.
Secure variant — SecurePolymorphicConverter<T> works the same way but encrypts properties decorated with [CoreSecret] using an IEncryptionKeyProvider:
options.Converters.Add(new SecurePolymorphicConverter<CoreRequestBase>(encryptionKeyProvider));
| Class | Description |
|---|---|
CoreSerializer |
Static helper using System.Text.Json with PolymorphicConverter pre-registered for CoreRequestBase and CoreResponseBase. Used internally by the framework. |
CoreJsonSerializer |
ICoreSerializer implementation backed by System.Text.Json. |
CoreSecureJsonSerializer |
ICoreSerializer implementation that encrypts [CoreSecret] annotated fields using IEncryptionKeyProvider. |
CoreServiceBase exposes two convenience methods for building responses:
// Fail with a reason code and optional messages
return this.Fail(EcommerceReasonCode.NoItemsAvailable, "No stock remaining");
// Succeed with an optional reason code
return this.Succeed();
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 net8.0 is compatible. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 was computed. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 was computed. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
Showing the top 3 NuGet packages that depend on BaseLib.Core:
| Package | Downloads |
|---|---|
|
FacturaE.Sdk
Package Description |
|
|
BaseLib.Core.AmazonCloud
Package Description |
|
|
BaseLib.Core.MySql
Package Description |
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 3.1.3 | 171 | 4/5/2026 |
| 3.1.1 | 163 | 2/25/2026 |
| 3.1.1-alpha-003 | 251 | 9/14/2025 |
| 3.1.1-alpha-001 | 200 | 9/13/2025 |
| 3.1.0 | 514 | 9/8/2025 |
| 3.0.0-beta-004 | 228 | 5/7/2025 |
| 3.0.0-beta-003 | 268 | 5/7/2025 |
| 2.1.0.5 | 677 | 3/19/2025 |
| 2.1.0.4 | 1,697 | 5/22/2024 |
| 2.1.0.3 | 314 | 5/15/2024 |
| 2.1.0.2 | 962 | 1/16/2024 |
| 2.1.0.1 | 292 | 12/30/2023 |
| 2.1.0 | 705 | 12/28/2023 |
| 2.0.2 | 1,184 | 11/22/2023 |
| 2.0.1 | 352 | 11/21/2023 |
| 2.0.0 | 421 | 11/1/2023 |
| 1.1.0 | 289 | 10/16/2023 |
| 1.1.0-beta-004 | 3,633 | 11/22/2022 |
| 1.1.0-beta-003 | 649 | 11/16/2022 |
| 1.1.0-beta-002 | 382 | 11/15/2022 |