Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ServiceComposer/ServiceComposer.AspNetCore/llms.txt

Use this file to discover all available pages before exploring further.

ScatterGatherOptions holds the per-endpoint configuration for a scatter/gather route: the list of gatherers to call in parallel, whether to use MVC output formatters, and an optional custom aggregator type. ScatterGatherEndpointBuilderExtensions exposes two MapScatterGather overloads — one for fully in-code configuration and one that reads endpoint definitions from IConfiguration — making it easy to manage routes in code, in appsettings.json, or in a mix of both.

ScatterGatherOptions

Class in the ServiceComposer.AspNetCore namespace. Passed directly to MapScatterGather or built internally when loading from configuration.

Gatherers

public IList<IGatherer> Gatherers { get; set; }
The ordered list of gatherers that will be invoked in parallel when the endpoint receives a request. All gatherers run concurrently via Task.WhenAll; their results are passed to the aggregator in completion order. Defaults to an empty list.
Gatherers
IList<IGatherer>
One or more IGatherer instances. Each gatherer must have a unique Key within the list.

UseOutputFormatters

public bool UseOutputFormatters { get; set; }
When true, the aggregated result is passed to an MVC ObjectResult and written through the MVC output formatter pipeline, enabling full content negotiation (JSON, XML, etc.) driven by the Accept header. Gatherers should return plain .NET objects rather than JsonNode values when output formatters are in use, so all formatters can serialize them. MVC services must be registered (e.g., services.AddControllers()) before this option takes effect. Defaults to false.

CustomAggregator

public Type CustomAggregator { get; set; }
When set, the aggregator used to combine gatherer results is resolved from DI using this type rather than the built-in DefaultAggregator. The type must implement IAggregator and must be registered in the service collection; setting a type that does not implement IAggregator throws InvalidOperationException immediately.
CustomAggregator
Type
A Type that implements IAggregator. The type must be registered in DI (e.g., via services.AddTransient<MyAggregator>()). null uses the default aggregator.
// Register the custom aggregator
builder.Services.AddTransient<SortedJsonAggregator>();

// Use it for a specific endpoint
app.MapScatterGather("api/products", new ScatterGatherOptions
{
    CustomAggregator = typeof(SortedJsonAggregator),
    Gatherers =
    [
        new HttpGatherer("CatalogA", "https://catalog-a/api/products"),
        new HttpGatherer("CatalogB", "https://catalog-b/api/products")
    ]
});

ScatterGatherEndpointBuilderExtensions

Static class in the ServiceComposer.AspNetCore namespace.

MapScatterGather (code-first overload)

public static IEndpointConventionBuilder MapScatterGather(
    this IEndpointRouteBuilder builder,
    string template,
    ScatterGatherOptions options)
Registers a single GET endpoint at template. When the endpoint is hit, all gatherers in options.Gatherers are invoked concurrently, their results are passed to the aggregator, and the aggregated object is written as JSON (or via output formatters when UseOutputFormatters is true). This overload does not require AddScatterGather to have been called.
builder
IEndpointRouteBuilder
required
The route builder (e.g., WebApplication or the builder inside UseEndpoints).
template
string
required
The ASP.NET Core route template for the endpoint (e.g., "api/products").
options
ScatterGatherOptions
required
The per-endpoint configuration including gatherers, formatter preference, and optional custom aggregator.
Returns IEndpointConventionBuilder for attaching endpoint metadata.
app.MapScatterGather("api/scatter-gather", new ScatterGatherOptions
{
    Gatherers =
    [
        new HttpGatherer("ASamplesSource",
            "https://a.web.server/api/samples/ASamplesSource"),
        new HttpGatherer("AnotherSamplesSource",
            "https://another.web.server/api/samples/AnotherSamplesSource")
    ]
});
With error tolerance
app.MapScatterGather("api/scatter-gather", new ScatterGatherOptions
{
    Gatherers =
    [
        new HttpGatherer("ASamplesSource", "https://a.web.server/api/samples/ASamplesSource")
        {
            IgnoreDownstreamRequestErrors = true
        },
        new HttpGatherer("AnotherSamplesSource",
            "https://another.web.server/api/samples/AnotherSamplesSource")
    ]
});

MapScatterGather (configuration-driven overload)

public static IReadOnlyList<IEndpointConventionBuilder> MapScatterGather(
    this IEndpointRouteBuilder builder,
    IConfiguration configuration,
    Action<string, ScatterGatherOptions> customize = null)
Reads every child section from configuration, creates a ScatterGatherOptions for each one, and calls the code-first overload to register a GET endpoint per route. Requires AddScatterGather to have been called during service registration so that ScatterGatherConfiguration is available in DI.
builder
IEndpointRouteBuilder
required
The route builder.
configuration
IConfiguration
required
The configuration section containing the array of route definitions. Pass builder.Configuration.GetSection("ScatterGather") when the array is nested under a "ScatterGather" key.
customize
Action<string, ScatterGatherOptions>
Optional callback invoked for each route after its ScatterGatherOptions is built from configuration but before the endpoint is registered. The first argument is the route template string; the second is the mutable options object. Use this to add extra gatherers or override settings for specific routes.
Returns IReadOnlyList<IEndpointConventionBuilder> — one entry per route defined in configuration. Basic usage
var builder = WebApplication.CreateBuilder();
builder.Services.AddRouting();
builder.Services.AddHttpClient();
builder.Services.AddScatterGather();

var app = builder.Build();
app.MapScatterGather(builder.Configuration.GetSection("ScatterGather"));
app.Run();
With per-route customization
app.MapScatterGather(
    builder.Configuration.GetSection("ScatterGather"),
    customize: (template, options) =>
    {
        if (template == "api/products")
        {
            options.Gatherers.Add(
                new HttpGatherer("Reviews", "https://reviews.web.server/api/reviews"));
        }
    });
Mixed code and configuration
// Routes from appsettings.json
app.MapScatterGather(configuration.GetSection("ScatterGather"));

// Additional route defined in code
app.MapScatterGather("api/other", new ScatterGatherOptions
{
    Gatherers = [ new HttpGatherer("OtherSource", "https://other.web.server/api/items") ]
});

Configuration JSON shape

When using the configuration-driven overload the IConfiguration section must contain an array of route objects. Each object has the following shape:
{
  "ScatterGather": [
    {
      "Template": "api/products",
      "UseOutputFormatters": false,
      "Gatherers": [
        {
          "Key": "CatalogA",
          "DestinationUrl": "https://catalog-a/api/products",
          "Type": "http"
        },
        {
          "Key": "CatalogB",
          "DestinationUrl": "https://catalog-b/api/products",
          "Type": "http",
          "IgnoreDownstreamRequestErrors": true
        }
      ]
    },
    {
      "Template": "api/promotions",
      "Gatherers": [
        {
          "Key": "Promotions",
          "DestinationUrl": "https://promo-service/api/active"
        }
      ]
    }
  ]
}
FieldRequiredDescription
TemplateYesASP.NET Core route template for the GET endpoint.
UseOutputFormattersNoDefaults to false. Set to true to enable MVC output formatters.
GatherersYesArray of gatherer objects.
Gatherers[].KeyYesUnique key for the gatherer; also used as the named HttpClient key.
Gatherers[].DestinationUrlYes (for "http" type)Base URL of the downstream endpoint.
Gatherers[].TypeNoGatherer factory discriminator. Defaults to "http". Register custom types with AddGathererFactory.
Gatherers[].IgnoreDownstreamRequestErrorsNoDefaults to false. Set true to swallow downstream errors for the "http" type.
Custom gatherer types can declare any additional fields in their configuration section — the entire IConfigurationSection is passed to the factory delegate registered via ScatterGatherConfiguration.AddGathererFactory.

Build docs developers (and LLMs) love