Fluent builder
Chain state, links, curies and embedded resources. Each stage only offers what is valid next.
ResourceBuilder .WithState(new { id = 123 }) .AddSelf().AddLinkObject("/orders/123") .Build();
Chatter.Rest.Hal — HAL for .NET. Fluent builders, System.Text.Json, source generators.
$ dotnet add package Chatter.Rest.HalOne method per HAL fragment. The JSON assembles as you type.
var hal = ResourceBuilder
.WithState(new { currentlyProcessing = 14 })
.AddSelf().AddLinkObject("/orders")
.AddCuries()
.AddLinkObject("http://example.com/docs/rels/{rel}", "ea")
.AddLink("next").AddLinkObject("/orders?page=2")
.AddLink("ea:find")
.AddLinkObject("/orders{?id}").Templated()
.AddEmbedded("ea:order")
.AddResource(new { total = 30.00F, status = "shipped" })
.AddSelf().AddLinkObject("/orders/123")
.Build();Chain state, links, curies and embedded resources. Each stage only offers what is valid next.
ResourceBuilder .WithState(new { id = 123 }) .AddSelf().AddLinkObject("/orders/123") .Build();
Read responses into your own types, a Resource, or source-generated classes. [HalResponse] adds the _links and _embedded plumbing for you.
[HalResponse] public partial class OrderCollection { public int CurrentlyProcessing { get; set; } }
Opt in to AlwaysUseArrayForLinks and a single link never flips between object and array again.
{ "_links": { "self": [{ "href": "/orders" }] } }
Levels 1–3 template parsing and expansion are built in, so templated links resolve without string glue.
"ea:find": { "href": "/orders{?id}", "templated": true } // → /orders?id=123