Controller-based queries
Use a controller when your query needs MVC routing, model binding, or authorization policies. Unlike a model-bound query, the method does not need to live on the type it returns.
Start with an MVC GET action
Section titled “Start with an MVC GET action”This controller example uses the shared AccountId and AccountName concepts with an ASP.NET Core Arc host, MVC, and the configured Arc MongoDB provider. Use this DebitAccount declaration instead of the model-bound alternative. No Chronicle integration is required.
using System.Collections.Generic;using Microsoft.AspNetCore.Authorization;using Microsoft.AspNetCore.Mvc;using MongoDB.Driver;
namespace Banking.Accounts;
public record DebitAccount(AccountId Id, AccountName Name, decimal Balance);
[Authorize(Roles = "AccountReader")][Route("api/accounts")]public class AccountsController(IMongoCollection<DebitAccount> collection) : ControllerBase{ [HttpGet] public IEnumerable<DebitAccount> AllAccounts() => collection.Find(_ => true).ToList();}With authentication and authorization middleware configured, the MVC authorization attribute protects this action. Arc’s QueryActionFilter handles GET actions: it establishes query context, processes MVC model-state errors, renders the returned data, applies interception, and wraps it in QueryResult.
This is not the model-bound IQueryPipeline filter chain. Do not assume model-bound custom filters run for a controller action, or that Arc’s GET query wrapper applies to a POST action.
Choose the next step
Section titled “Choose the next step”- Route templates: bind identifiers from route values.
- Query arguments: bind scalar values, arrays, and MVC DTOs.
- Dependency injection: resolve application services.
- Return types: understand wrapping, nulls, and explicit MVC responses.
- Paging: return
IQueryable<T>for renderer-based paging. - Observable queries: expose a producer over direct SSE or WebSocket.
The proxy generator creates client types from supported controller query declarations. For raw MVC responses, see without wrappers; opting out changes the contract a standard Arc query client expects.