In systems built from autonomous services, each service owns its own slice of data — and that’s a feature, not a bug. But the moment a UI or API client needs to display a product page, a dashboard, or any view that draws from several services at once, that clean ownership starts to feel like an obstacle. ServiceComposer is an ASP.NET Core library that resolves this tension through a pattern called ViewModel Composition: each service contributes its own fragment of the response through an independent handler, and the gateway assembles them into one coherent reply.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.
The Problem: Data Ownership vs. Display Needs
Consider a typical e-commerce product page. The Sales service owns the price and availability. The Marketing service owns the product name and description. Neither service should know what the other holds — that separation is what lets them be deployed, scaled, and evolved independently. Yet the client needs all of that data in a single response. This is not a niche problem. Every sufficiently decomposed system faces it, and the way you solve it determines whether your services remain truly autonomous or gradually collapse into a distributed monolith.Why Naive Approaches Fall Short
The temptation is to reach for the most convenient solution. But the common shortcuts each carry hidden costs:Client-Side Merging
The UI calls each service separately and stitches results together. This couples the client to service internals, leaks service boundaries, and causes a flood of round-trips — especially painful on mobile or low-bandwidth connections.
Shared Database
Services read from a common schema. This destroys the data ownership that makes services autonomous. A schema change in one service can silently break another, and deployment independence disappears.
Dedicated Aggregation Service
A new service is built purely to call others and combine their data. This service must be updated every time any contributing service changes its API, creating a tight coupling in a different place — and a single point of failure.
ViewModel Composition: Assembly at the Gateway Layer
ViewModel Composition moves the aggregation concern to the API gateway, where it belongs. The key insight is that each service is the best author of its own slice of the response. Instead of one service (or the client) knowing about all the others, each service ships a small composition handler — a class that lives in its own assembly, targets a specific route, and writes only the properties that service owns. The gateway discovers all registered handlers for an incoming request, runs them in parallel, and serializes the merged result. No handler knows about the others. No handler owns the route exclusively. This preserves all of the properties that make services valuable:- Data ownership — each service writes only its own fields
- Independent deployability — adding a new service means adding a new handler; no existing handler changes
- Single client request — the caller sees one endpoint and one response
ServiceComposer: The ASP.NET Core Implementation
ServiceComposer is the production-ready ASP.NET Core implementation of the ViewModel Composition pattern. It integrates with the standard ASP.NET Core endpoint routing pipeline, requires minimal configuration, and automatically discovers composition handlers by scanning loaded assemblies at startup. A handler is nothing more than a class that implementsICompositionRequestsHandler and carries an [Http*] routing attribute:
Handle method receives the full HttpRequest, so handlers have access to route values, query strings, headers, and the DI container — everything needed to fetch data from a downstream service or database and project it onto the shared view model via request.GetComposedResponseModel().
Supported Platforms
Starting with version 5.0, ServiceComposer targets .NET 10 only. Both existing ASP.NET Core web applications and new gateway projects are supported. ServiceComposer can also be hosted in a .NET console application.
Philosophy: Getting Service Boundaries Right
Service boundaries are the most critical design decision in a service-oriented system. When boundaries are wrong, the usual reaction is to compensate with rich events or shared caches (like Elasticsearch) to satisfy UI needs — but this causes data ownership to erode across the entire system. Every change starts to impact everything else. ViewModel Composition techniques are designed to prevent this. They bring the separation of concerns established at the back end forward to the front end, without forcing any service to know what another owns.Service boundary identification is challenging; it requires extensive business domain knowledge and confidence in high-level design techniques. Technical challenges, such as the lack of technical solutions to problems foreseen while defining service boundaries, might drive the solution design in the wrong direction.For a deeper exploration of the philosophy and the full pattern catalogue, see the ViewModel Composition series and the technical introduction on YouTube.
Ready to Build?
Quickstart: Your First Composition in 5 Minutes
Install ServiceComposer, write your first two composition handlers, wire them into an ASP.NET Core gateway, and see a merged JSON response — step by step.