Codebelt

Codebelt.Extensions.Carter.AspNetCore.Xml

XML response negotiation for Carter endpoints.

.NET 10.0 MIT v1.0.4 562 downloads

Overview

Codebelt.Extensions.Carter.AspNetCore.Xml adds a Carter negotiator that serializes response models as XML. It extends Codebelt.Extensions.Carter when an API must negotiate XML responses for integrations that expect XML payloads instead of JSON or YAML.

The package contributes one focused type. That negotiator reuses the shared negotiation flow from the core package, selects an XmlFormatter, and derives its default encoding from the configured XML writer settings.

Key APIs

XmlResponseNegotiator is the package's central type. It derives from ConfigurableResponseNegotiator<XmlFormatterOptions>, which turns the inherited CanHandle, GetEncoding, and Handle<T> lifecycle into a concrete XML negotiator for Carter.

XmlResponseNegotiator(IOptions<XmlFormatterOptions>) connects the negotiator to dependency-injected XmlFormatterOptions, so supported media types and writer settings come from the application's XML configuration.

XmlResponseNegotiator.GetDefaultEncoding returns Options.Settings.Writer.Encoding, which keeps the fallback response charset aligned with the configured XML writer.

Basic usage

using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Codebelt.Extensions.Carter.AspNetCore.Xml;
using Codebelt.Extensions.Xunit;
using Cuemon.Xml.Serialization.Formatters;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Microsoft.Net.Http.Headers;
using Xunit;

namespace MyProject.Tests;

public class XmlNegotiationTest : Test
{
    public XmlNegotiationTest(ITestOutputHelper output) : base(output) { }

    [Fact]
    public async Task ShouldSerializeNegotiatedXmlResponse()
    {
        var context = new DefaultHttpContext();
        context.Response.Body = new MemoryStream();
        var negotiator = new XmlResponseNegotiator(Options.Create(new XmlFormatterOptions()));

        Assert.True(negotiator.CanHandle(MediaTypeHeaderValue.Parse("application/xml")));
        await negotiator.Handle(context.Request, context.Response, new WorkItem { Id = 9, State = "complete" }, CancellationToken.None);

        context.Response.Body.Position = 0;
        var body = await new StreamReader(context.Response.Body).ReadToEndAsync();
        TestOutput.WriteLine(body);
        Assert.StartsWith("application/xml", context.Response.ContentType);
        Assert.Contains("<State>complete</State>", body);
    }

    private sealed class WorkItem { public int Id { get; init; } public string State { get; init; } }
}

Use this pattern when a Carter endpoint must negotiate XML output for downstream systems that consume XML contracts. It matters because the negotiator keeps XML media-type matching, formatter selection, and response encoding in a single reusable component.

Installation

dotnet add package Codebelt.Extensions.Carter.AspNetCore.Xml

Usage guidance

Choose this package when XML is part of the external contract and you want Carter to negotiate it through XmlResponseNegotiator instead of hand-authoring XML in endpoints. If the API only needs JSON or YAML, use the sibling negotiators that match those formats rather than carrying XML-specific dependencies.

Family packages