CarpaNet.AspNetCore
1.0.1
dotnet add package CarpaNet.AspNetCore --version 1.0.1
NuGet\Install-Package CarpaNet.AspNetCore -Version 1.0.1
<PackageReference Include="CarpaNet.AspNetCore" Version="1.0.1" />
<PackageVersion Include="CarpaNet.AspNetCore" Version="1.0.1" />
<PackageReference Include="CarpaNet.AspNetCore" />
paket add CarpaNet.AspNetCore --version 1.0.1
#r "nuget: CarpaNet.AspNetCore, 1.0.1"
#:package CarpaNet.AspNetCore@1.0.1
#addin nuget:?package=CarpaNet.AspNetCore&version=1.0.1
#tool nuget:?package=CarpaNet.AspNetCore&version=1.0.1
CarpaNet.AspNetCore
ASP.NET Core XRPC server endpoint support for CarpaNet. Generate abstract ATProtocol XRPC controllers from lexicon definitions and implement your own ATProtocol server endpoints.
Installation
dotnet add package CarpaNet.AspNetCore
You also need the core CarpaNet package (with source generator) to generate the controllers and data model types.
Quick Start
1. Enable XRPC endpoint generation
Set CarpaNet_EmitXrpcEndpoints to true in your ASP.NET Core project:
<PropertyGroup>
<CarpaNet_EmitXrpcEndpoints>true</CarpaNet_EmitXrpcEndpoints>
<CarpaNet_LexiconAutoResolve>true</CarpaNet_LexiconAutoResolve>
</PropertyGroup>
<ItemGroup>
<LexiconResolve Include="com.atproto.server.describeServer" />
<LexiconResolve Include="com.atproto.identity.resolveHandle" />
</ItemGroup>
This tells the CarpaNet source generator to produce abstract controller classes alongside the usual data model types.
2. Implement the generated controllers
The generator creates abstract controllers grouped by NSID namespace. Subclass them and implement the abstract methods:
using CarpaNet.AspNetCore;
using Microsoft.AspNetCore.Http.HttpResults;
public class MyServerController : Xrpc.ComAtproto.Server.ServerController
{
public override Task<Results<Ok<ComAtproto.Server.DescribeServerOutput>, ATErrorResult>> DescribeServerAsync(
CancellationToken cancellationToken = default)
{
var output = new ComAtproto.Server.DescribeServerOutput
{
AvailableUserDomains = new List<string> { ".example.com" },
Did = new CarpaNet.ATDid("did:web:example.com"),
};
return Task.FromResult<Results<Ok<ComAtproto.Server.DescribeServerOutput>, ATErrorResult>>(
TypedResults.Ok(output));
}
}
3. Wire up ASP.NET
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.Run();
Your endpoints are now available at /xrpc/{nsid} (e.g., /xrpc/com.atproto.server.describeServer).
How It Works
The CarpaNet source generator reads ATProtocol lexicon JSON files and produces:
- Data model classes — Records, objects, input/output types (generated by the existing pipeline)
- Abstract controllers — One per NSID namespace group (e.g.,
ServerControllerforcom.atproto.server.*)
Lexicon queries map to [HttpGet] with [FromQuery] parameters. Lexicon procedures map to [HttpPost] with [FromBody] input.
Generated Controller Pattern
Lexicon: com.atproto.identity.resolveHandle (query)
↓
Xrpc.ComAtproto.Identity.IdentityController (abstract)
→ ResolveHandleAsync([FromQuery] string handle, CancellationToken ct)
→ Returns Task<Results<Ok<ResolveHandleOutput>, ATErrorResult>>
Lexicon: com.atproto.repo.createRecord (procedure)
↓
Xrpc.ComAtproto.Repo.RepoController (abstract)
→ CreateRecordAsync([FromBody] CreateRecordInput input, CancellationToken ct)
→ Returns Task<Results<Ok<CreateRecordOutput>, ATErrorResult>>
Error Handling
Use ATErrorResult factory methods to return ATProtocol-compliant error responses:
// Returns { "error": "NotFound", "message": "Record not found" } with HTTP 404
return ATErrorResult.NotFound("Record not found");
// Returns { "error": "AuthMissing", "message": "Authentication Required" } with HTTP 401
return ATErrorResult.Unauthorized();
// Returns { "error": "BadRequest", "message": "Invalid handle format" } with HTTP 400
return ATErrorResult.BadRequest("Invalid handle format");
Available factory methods:
| Method | Status Code | Error Type |
|---|---|---|
BadRequest() |
400 | BadRequest |
Unauthorized() |
401 | AuthMissing |
Forbidden() |
403 | Forbidden |
NotFound() |
404 | NotFound |
PayloadTooLarge() |
413 | PayloadTooLarge |
TooManyRequests() |
429 | TooManyRequests |
InternalServerError() |
500 | InternalServerError |
NotImplemented() |
501 | NotImplemented |
BadGateway() |
502 | BadGateway |
ServiceUnavailable() |
503 | ServiceUnavailable |
GatewayTimeout() |
504 | GatewayTimeout |
MSBuild Properties
| Property | Description | Default |
|---|---|---|
CarpaNet_EmitXrpcEndpoints |
Enable XRPC controller generation | false |
| 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
- CarpaNet (>= 1.0.1)
-
net8.0
- CarpaNet (>= 1.0.1)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.5)
- System.Formats.Cbor (>= 10.0.5)
- System.Text.Json (>= 10.0.5)
-
net9.0
- CarpaNet (>= 1.0.1)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.5)
- System.Formats.Cbor (>= 10.0.5)
- System.Text.Json (>= 10.0.5)
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.1 | 84 | 3/30/2026 |
| 0.1.0-alpha.76 | 39 | 3/30/2026 |
| 0.1.0-alpha.71 | 52 | 3/24/2026 |