Overview
Codebelt.Extensions.Carter.AspNetCore.Text.Yaml adds a Carter negotiator that serializes response models as YAML. It extends Codebelt.Extensions.Carter when an API must answer YAML clients through Carter's negotiation pipeline instead of returning ad hoc text results from each endpoint.
The negotiator is intentionally narrow. It reuses the shared negotiation flow from the core package, selects a YamlFormatter, and takes its default response encoding directly from YamlFormatterOptions.
Key APIs
YamlResponseNegotiator is the package's central type. It derives from ConfigurableResponseNegotiator<YamlFormatterOptions>, so the inherited CanHandle, GetEncoding, and Handle<T> behavior becomes a concrete YAML negotiator for Carter.
YamlResponseNegotiator(IOptions<YamlFormatterOptions>) pulls formatter configuration from dependency injection, which lets the negotiator use the application's supported media types and YAML writer settings.
YamlResponseNegotiator.GetDefaultEncoding returns Options.Encoding, which makes the configured YAML formatter encoding the fallback when the request does not select a charset explicitly.
Basic usage
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Codebelt.Extensions.Carter.AspNetCore.Text.Yaml;
using Codebelt.Extensions.Xunit;
using Codebelt.Extensions.YamlDotNet.Formatters;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Microsoft.Net.Http.Headers;
using Xunit;
namespace MyProject.Tests;
public class YamlNegotiationTest : Test
{
public YamlNegotiationTest(ITestOutputHelper output) : base(output) { }
[Fact]
public async Task ShouldSerializeNegotiatedYamlResponse()
{
var context = new DefaultHttpContext();
context.Response.Body = new MemoryStream();
var negotiator = new YamlResponseNegotiator(Options.Create(new YamlFormatterOptions()));
Assert.True(negotiator.CanHandle(MediaTypeHeaderValue.Parse("application/yaml")));
await negotiator.Handle(context.Request, context.Response, new WorkItem { Id = 3, State = "ready" }, CancellationToken.None);
context.Response.Body.Position = 0;
var body = await new StreamReader(context.Response.Body).ReadToEndAsync();
TestOutput.WriteLine(body);
Assert.StartsWith("application/yaml", context.Response.ContentType);
Assert.Contains("ready", body);
}
private sealed class WorkItem { public int Id { get; init; } public string State { get; init; } }
}
Use this pattern when a Carter endpoint needs first-class YAML responses instead of a JSON-only contract. It matters because the negotiator centralizes media-type matching, encoding, and YAML serialization in one reusable registration.
Installation
dotnet add package Codebelt.Extensions.Carter.AspNetCore.Text.Yaml
Usage guidance
Adopt this package when external clients or downstream tools require YAML output and you want that format negotiated through Carter rather than composed manually in handlers. If your API contract is JSON-first or XML-first, the JSON and XML sibling negotiators are a better fit than introducing YAML negotiation.