IDomainRepository
is the base repository that IContentRepository
and IAdvancedContentRepository
inherit from and includes all the base functionality without any of the content-specific extensions, providing easy access to components such as command and query execution, permission escalation and transaction management.
Typically you'd use IDomainRepository
if you are only interested in using Cofoundry as a framework without any of the CMS content APIs, however all the features documented in this section are also relevant to IContentRepository
and IAdvancedContentRepository
.
Executing queries and commands
Cofoundry repositories have the following methods to facilitate working with queries and commands:
ExecuteQueryAsync
: Directly executes anIQuery
instance and returns the results.WithQuery
: Allows you to chain mutator functions to run after execution of a query such asMap
orMapItem
.ExecuteCommandAsync
: Directly executes anICommand
instance.PatchCommandAsync
: Patches anIPatchableCommand
command to modify the current state before executing it.
Detailed information on using the CQS framework itself is here.
Example:
var command = new ExampleCommand()
{
ExampleId = 1
};
await _domainRepository.ExecuteCommandAsync(command);
Executing the queries in this way allows you to benefit from many of the additional features described here such as mapping, permission elevation and transaction management.
Mapping
Queries executed using WithQuery
can benefit from the same mapping features found in content repository queries:
var results = await _domainRepository
.WithQuery(new SearchCustomEntityRenderSummariesQuery()
{
CustomEntityDefinitionCode = BlogPostCustomEntityDefinition.DefinitionCode
})
.MapItem(b => new { b.Title })
.ExecuteAsync();
Elevating Permissions
Execution of queries and commands is restricted by permissions. If you want to run a query or command that currently signed in user doesn't have permissions for, you'll need to elevate your permissions before executing it.
An example of when this might be useful would be registering a new user from a public sign-up form. The anonymous user role does not typically have permissions to create a user, so we'd need to elevate permissions:
public async Task RegisterUser(string email, string password)
{
await _advancedContentRepository
.WithElevatedPermissions()
.Users()
.AddAsync(new AddUserCommand()
{
Email = email,
Password = password,
UserAreaCode = MemberUserArea.Code,
RoleCode = MemberRole.Code
});
}
Changing Context
IDomainRepository.WithContext
can be used to change the command or query execution context. It has three different overloads:
WithContext(IExecutionContext)
: Executes the command or query with the specific execution context. Typically this is used to maintain context by passing the execution context down to nested queries or commands.WithContext(IUserContext)
: Switches the existing execution context to use the specified user context. This is used to impersonate a user without creating a new execution context.WithContext<TUserArea>()
: Execute queries or commands using the user context associated with the specified user area. This is useful when implementing multiple user areas whereby a client can be signed into multiple user accounts belonging to different user areas. Use this to force execution to use the context of a specific user area rather than relying on the "ambient" or default. The user area docs contains more information about the ambient user area.
This example passes down the execution context to the execution of a nested command:
public class ExampleCommandHandler
: ICommandHandler<ExampleCommand>
, ISignedInPermissionCheckHandler
{
// ...constructor omitted for brevity
public async Task ExecuteAsync(ExampleCommand command, IExecutionContext executionContext)
{
await _domainRepository
.WithContext(executionContext)
.ExecuteCommandAsync(new NestedCommand());
}
}
Transactions
The Cofoundry transaction manager can be accessed via the Transactions()
extension method:
using (var scope = _domainRepository.Transactions().CreateScope())
{
// Do stuff
await scope.CompleteAsync();
}
Read more about the Cofoundry transaction manager in the transactions docs.
Influencing execution with ModelState
The Cofoundry.Web
namespace includes extensions that make it easier to work with queries or command execution in ASP.NET controllers and Razor Pages by making use of ModelState
to work with validation errors. This is covered in the content repository docs.