Pinqponq.Contracts
1.1.0
Prefix Reserved
dotnet add package Pinqponq.Contracts --version 1.1.0
NuGet\Install-Package Pinqponq.Contracts -Version 1.1.0
<PackageReference Include="Pinqponq.Contracts" Version="1.1.0" />
<PackageVersion Include="Pinqponq.Contracts" Version="1.1.0" />
<PackageReference Include="Pinqponq.Contracts" />
paket add Pinqponq.Contracts --version 1.1.0
#r "nuget: Pinqponq.Contracts, 1.1.0"
#:package Pinqponq.Contracts@1.1.0
#addin nuget:?package=Pinqponq.Contracts&version=1.1.0
#tool nuget:?package=Pinqponq.Contracts&version=1.1.0
Pinqponq.Contracts
Response envelope, paging models, common error codes and the request error feature shared by every Pinqponq API and by the Pinqponq.ErrorHandling / Pinqponq.Observability middlewares.
Install
dotnet add package Pinqponq.Contracts
Response envelope
BaseResponseModel is the shape of every response, serialized camelCase:
{ "status": false, "statusCode": 400, "message": "The request was invalid.", "responseCode": "general_error" }
| Field | Type | Notes |
|---|---|---|
status |
bool | true on success, false on an error. |
statusCode |
int | HTTP status code. |
message |
string | Human-readable text. Always set on an error. |
responseCode |
string | Stable machine-readable code. |
Compatibility with deveng-networking-kmp
The mobile apps decode every non-2xx body into deveng-networking-kmp's
ErrorResponse(val message: String) with ignoreUnknownKeys = true, and hand message to the
app's exception handler. So an error body is compatible when:
- it is a JSON object with a non-null string
message(a missing or nullmessagefails the decode and the app shows its generic "Unknown error"); - it may have other fields, such as
status,statusCodeandresponseCode. Pinqponq.ErrorHandling always addstraceId. The client ignores unknown fields, so adding it is safe.
ErrorResponse of Pinqponq.ErrorHandling writes the same four fields in the same order, plus
traceId. So APIs using either type stay compatible.
Paging
[HttpGet]
public ActionResult<PagedResponseModel<List<OrderDto>>> List([FromQuery] PagedRequestModel paging) =>
orders.ToPagedResponse(paging.Page, paging.Size, page => page.Select(ToDto).ToList(),
orderBy: rows => rows.OrderByDescending(order => order.CreatedAt));
PagedRequestModelbinds?PageNumber=(default 1) and?PageSize=(default 10).PagedResponseModel<T>extendsBaseResponseModelwithpage,size,rowCount,pageCount,hasNextPage,firstRowOnPage,lastRowOnPageanddata.ToPagedResponseon anIEnumerable<T>takes the requested page from rows that are already in memory. On anIQueryable<T>it counts the rows of the query and reads only the requested page.- For a database query, page it in the database. Do not load all rows into memory first.
- A page number under 1 throws
ArgumentExceptionwithapi_page_number_invalidas the message. A page size under 1 throws it withapi_page_size_invalid.
Limits and the page after the last page
PaginationOptions (optional last argument) sets the service's limits:
| Property | Default | Notes |
|---|---|---|
MaxPageSize |
100 |
A larger page size is lowered to it; size in the response shows the value used. |
PastLastPage |
ReturnLastPage |
What a request for the page after the last page returns. ReturnLastPage returns the last page; the response's page field holds the last page number, not the requested one. When there are no rows, there is no last page, so the response is an empty page with the requested number. ReturnEmptyPage returns an empty page; the page field keeps the requested number, hasNextPage is false, and firstRowOnPage and lastRowOnPage are 0. |
private static readonly PaginationOptions LogPaging = new()
{
MaxPageSize = 200,
PastLastPage = PastLastPageBehavior.ReturnEmptyPage,
};
Paging an async query
PageWindow works out which rows belong to the requested page. With it, an async query (EF Core,
Dapper, a MongoDB find) is paged by the same rules as ToPagedResponse:
PageWindow.ValidateRequest(paging.Page, paging.Size);
var orders = dbContext.Orders.OrderByDescending(order => order.CreatedAt);
var window = PageWindow.Resolve(paging.Page, paging.Size, await orders.LongCountAsync(cancellationToken), options);
var pageRows = await orders.Skip(window.Skip).Take(window.Size).ToListAsync(cancellationToken);
return window.ToResponse(pageRows, page => page.Select(ToDto).ToList());
Pinqponq.Database.Mongo wraps this for a MongoDB find (ToPagedResponseAsync).
Common error codes
CommonErrorCodes: general_error, api_client_closed_request,
api_body_required, api_page_size_invalid, api_page_number_invalid, too_many_requests. Product-specific codes
stay in the product. Pinqponq.ErrorHandling ships the localized messages of the codes it can
return.
Request error feature
IRequestErrorFeature (default implementation RequestErrorFeature) is an ASP.NET Core
HttpContext.Features entry: Pinqponq.ErrorHandling sets it when it answers a failed request
(EventName, e.g. exception_KeyNotFoundException, and a Detail dictionary), and
Pinqponq.Observability's request logging reads it, so a failed request still produces one log
record. It lives here so neither middleware package depends on the other.
Repository
| Product | Versions 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 is compatible. 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 is compatible. 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. |
-
net10.0
- No dependencies.
-
net8.0
- No dependencies.
-
net9.0
- No dependencies.
NuGet packages (3)
Showing the top 3 NuGet packages that depend on Pinqponq.Contracts:
| Package | Downloads |
|---|---|
|
Pinqponq.ErrorHandling
Global exception middleware plus a standard error response contract; optional localized error messages and pluggable exception resolvers; log output uses Pinqloq's structured format (correlation/trace id, field names). |
|
|
Pinqponq.Database.Mongo
MongoDB (MongoDB.Driver) connection setup, health-check layer and paging of a find into the shared Pinqponq.Contracts paged response. Does not include repositories or entities. |
|
|
Pinqponq.Observability
Pinqloq logging for ASP.NET Core: one structured record per request (redacted request/response bodies, route-based event names, error detail from Pinqponq.ErrorHandling), and an ILogService for application and job logs with stack trace trimming. |
GitHub repositories
This package is not used by any popular GitHub repositories.