Raycynix.Extensions.Contracts
1.0.0
dotnet add package Raycynix.Extensions.Contracts --version 1.0.0
NuGet\Install-Package Raycynix.Extensions.Contracts -Version 1.0.0
<PackageReference Include="Raycynix.Extensions.Contracts" Version="1.0.0" />
<PackageVersion Include="Raycynix.Extensions.Contracts" Version="1.0.0" />
<PackageReference Include="Raycynix.Extensions.Contracts" />
paket add Raycynix.Extensions.Contracts --version 1.0.0
#r "nuget: Raycynix.Extensions.Contracts, 1.0.0"
#:package Raycynix.Extensions.Contracts@1.0.0
#addin nuget:?package=Raycynix.Extensions.Contracts&version=1.0.0
#tool nuget:?package=Raycynix.Extensions.Contracts&version=1.0.0
Raycynix.Extensions.Contracts
Raycynix.Extensions.Contracts contains reusable contract models and versioning conventions for shared .NET APIs.
What it contains
MoneyQuantityUoMPagingRequestPageInfoPagedResult<TItem>ErrorContractValidationErrorContractVersionContractMetadataVersionedContract<TContract>ContractHeadersContractIntroducedAttributeContractDeprecatedAttribute- DTO and contract versioning conventions for cross-service APIs
- validation-friendly annotations for common contracts
- a shared transport error model for reusable APIs
What it does not contain
master datasources- reference data synchronization
- service-specific DTOs
- API gateway contracts
- transport-specific ASP.NET Core middleware
Contract Rules
- shared DTOs must be backward compatible within the same major contract version
- new fields must be additive and optional for existing consumers
- existing public fields must not be removed or renamed inside the same major contract version
- breaking changes require a new contract version
Majorchanges are breaking changesMinorchanges are additive, backward-compatible changesPatchchanges are non-breaking fixes that do not alter the contract shape- contract models must stay serialization-friendly and avoid behavior-heavy logic
- cross-service reusable types belong here, service-local DTOs do not
- contract identifiers and versions should be explicit at transport boundaries when contracts are shared across services
- public contracts should expose validation metadata that common frameworks can consume consistently
Change Rules
- do not remove or rename public contract fields inside the same major version
- deprecate old fields before removal instead of deleting them immediately
- introduce replacement fields as additive optional members first
- use a new major contract version only when compatibility cannot be preserved
- keep deprecated members readable long enough for existing consumers to migrate
- document when a field was introduced and when it became deprecated
Usage
var price = new Money
{
Amount = 149.99m,
Currency = "USD"
};
var quantity = new Quantity
{
Value = 12.5m,
UoM = new UoM
{
Code = "kg",
Name = "Kilogram"
}
};
var result = new PagedResult<Money>
{
Items = new[] { price },
PageInfo = new PageInfo
{
Page = 1,
PageSize = 20,
TotalCount = 1,
TotalPages = 1,
HasPreviousPage = false,
HasNextPage = false
}
};
var versioned = new VersionedContract<PagedResult<Money>>
{
Metadata = new ContractMetadata
{
Name = "catalog.prices",
Version = new ContractVersion
{
Major = 1,
Minor = 0,
Patch = 0
}
},
Payload = result
};
Contract Headers
Use the shared header names when contracts cross transport boundaries explicitly:
var headers = new Dictionary<string, string?>
{
[ContractHeaders.ContractName] = "catalog.prices",
[ContractHeaders.ContractVersion] = "1.2.0"
};
Versioning
Use ContractVersion to express the current shared contract version:
var version = new ContractVersion
{
Major = 1,
Minor = 2,
Patch = 0
};
var parsed = ContractVersion.Parse("1.2.0");
var isCompatibleLine = parsed >= version;
When contract metadata must cross process boundaries explicitly, use:
ContractHeaders.ContractNameContractHeaders.ContractVersion
This package only defines the common contract model and conventions. It does not enforce transport-specific version negotiation by itself.
ContractVersion also supports parsing, comparison, and equality to help consumers implement consistent compatibility checks in their own services.
Error Contracts
Use ErrorContract as the shared transport shape for failures:
var error = new ErrorContract
{
Code = "validation_failed",
Message = "One or more validation errors occurred.",
TraceId = "00-7d9f6f8f53fd8a8ce6d4cfd21483ca5f-b9d0f6f6bd2f5f61-01",
ValidationErrors =
[
new ValidationError
{
Field = "pageSize",
Code = "out_of_range",
Message = "Page size must be greater than zero."
}
]
};
This package intentionally keeps the error contract generic so it can be reused in HTTP APIs, messaging, and internal service boundaries.
Validation Metadata
The built-in contract models expose System.ComponentModel.DataAnnotations attributes and lightweight IsValid() checks so consumers can use them with ASP.NET Core, manual validation flows, or custom guards without introducing transport-specific behavior into the contracts themselves.
ASP.NET Core
If you want HTTP header integration, endpoint metadata, controller/minimal API helpers, or ModelState conversion helpers, use the companion package Raycynix.Extensions.Contracts.AspNetCore.
In that package:
- declare a contract on a Minimal API endpoint with
.WithContract(...) - declare a contract on MVC actions/controllers with
[Contract(...)] - enable
UseRaycynixContracts()so the declared contract is written to HTTP headers - return
httpContext.VersionedContract(...)orthis.VersionedContract(...)when you want the response body wrapped intoVersionedContract<T>without duplicating metadata inside the handler
Marking Contract Evolution
Use the attributes in this package to mark contract evolution directly on shared DTOs:
public class CatalogPriceDto
{
[ContractIntroduced("1.0.0")]
public string ProductId { get; set; } = string.Empty;
[ContractIntroduced("1.2.0")]
public Money? DiscountPrice { get; set; }
[ContractDeprecated("1.3.0", RemovalVersion = "2.0.0", Reason = "Use DiscountPrice instead.")]
public decimal? DiscountAmount { get; set; }
}
Recommended evolution flow:
- add a new optional field
- keep the old field for compatibility
- mark the old field as deprecated
- remove it only in the next breaking contract version
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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.
NuGet packages (3)
Showing the top 3 NuGet packages that depend on Raycynix.Extensions.Contracts:
| Package | Downloads |
|---|---|
|
Raycynix.Extensions.Messaging.Abstractions
Transport-agnostic messaging contracts, codecs, handlers, outbox abstractions, and direct communication primitives for Raycynix applications. |
|
|
Raycynix.Extensions.Messaging
Transport-agnostic messaging registration, dispatch, direct requests, observability, scoped envelope factories, and outbox/inbox reliability foundations for Raycynix applications. |
|
|
Raycynix.Extensions.Contracts.AspNetCore
ASP.NET Core integration for Raycynix contracts, including endpoint metadata, contract headers, and contract-aware result helpers. |
GitHub repositories
This package is not used by any popular GitHub repositories.
See the repository changelog and release history for package-specific changes and breaking updates.