Application Layer
The application layer serves as a mediator between the UI and the domain layers. Here you can define the job(s) certain action is expected to perform. It is a thin layer that will, usually, just reference the domain layer, but it may contain some workflow logic (never business logic), for example when you need to access more than one domain service:
public class CustomAppService : BaseAppService, IJointAppService
{
public CustomAppService(IServiceProvider serviceProvider) : base(serviceProvider) { }
public async Task<OperationResult> PerformAction(object data)
{
var ds1 = await GetDomainService<IAction1DomainService>().Action1(data);
var ds2 = await GetDomainService<IAction2DomainService>().Action2(ds1);
return new OperationResult {
IsSuccessful = ds2.IsSuccessful,
Result = ds2
};
}
}
If it wasn't for this layer, if we ever decided to invoke our domain layer from another UI (let's say we changed our console app for a WebAPI one, for example), we'd need to rewrite the logic.
All services inherit from BaseService containing the following methods:
| Method | Signature | Description |
|---|---|---|
| ToEntity | TEntity ToEntity<TEntity>(object source) | Maps the source object to the entity type requested. |
| ToResponse | TResponse ToResponse<TResponse>(object source) | Maps the source object (entity) to the response type requested. |
| MapTo | TResponse MapTo<TResponse>(object source) | Maps the source object to the type requested. |
| GetDomainService | TDomainService GetDomainService<TDomainService>() | Gets a domain service. |
You can always add extra methods to your service.
Let's explore the available structures provided by the UpDevs SDK:
Base
Provides the basic structure for all application services. It is the simplest form an app service can take.
Interface
public interface IMyAppService : IAppService
{
// ... Methods' signatures
}
Implementation
public class MyAppService : BaseAppService, IMyAppService
{
public MyAppService(IServiceProvider serviceProvider) : base(serviceProvider) { }
// ... Methods
}
List
Inherits from BaseAppService and adds extra functionality to implement the listing behavior. Requires a response type to be informed (this is the type of the model that represents the entity as it's returned to the outside - it can have a Response or Model suffix depending on your structure for this entity).
The interface used for the related domain service must be provided here (see Implementation).
Methods Provided
They all have async options - ending with Async.
| Method | Signature | Description |
|---|---|---|
| List | PagedListModel<TResponse> List(SearchRequest? searchModel) | Retrieves the entities found as a paged list based on the query. |
| GetByIds | TResponse[] GetByIds<TId>(TId[] ids) | Retrieves a list of entities using the informed IDs. |
Interface
public interface IMyAppService : IListAppService<MyResponse>
{
// ... Other methods' signatures
}
Implementation
public class MyAppService : BaseListAppService<IMyDomainService, MyResponse>, IMyAppService
{
public MyAppService(IServiceProvider serviceProvider) : base(serviceProvider) { }
// ... Other methods
}
Search
Inherits from BaseListAppService and adds extra functionality to implement the search behavior. Requires a response type to be informed (this is the type of the model that represents the entity as it's returned to the outside - it can have a Response or Model suffix depending on your structure for this entity).
The interface used for the related domain service must be provided here (see Implementation).
Methods Provided
They all have async options - ending with Async.
Also includes the methods in BaseListAppService.
| Method | Signature | Description |
|---|---|---|
| Search | PagedListModel<TResponse> Search(SearchRequest? searchModel) | Retrieves the entities found as a paged list based on the query. |
| GetCsv | byte[] GetCsv(CsvSearchRequest? searchModel) | Retrieves the entities found as a CSV structure based on the query. |
Interface
public interface IMyAppService : ISearchAppService<MyResponse>
{
// ... Other methods' signatures
}
Implementation
public class MyAppService : BaseSearchAppService<IMyDomainService, MyResponse>, IMyAppService
{
public MyAppService(IServiceProvider serviceProvider) : base(serviceProvider) { }
// ... Other methods
}
Entity (CRUD)
Inherits from BaseSearchAppService and adds extra functionality to implement the CRUD behavior. Requires an input (this is the type of the model that represents the entity as it's sent to service - it can have an Input or Model suffix depending on your structure for this entity) and response (this is the type of the model that represents the entity as it's returned to the outside - it can have a Response or Model suffix depending on your structure for this entity) types to be informed .
The interface used for the related domain service must be provided here (see Implementation).
Methods Provided
They all have async options - ending with Async.
Also includes the methods in BaseSearchAppService.
| Method | Signature | Description |
|---|---|---|
| Get | TResponse? Get(params object[] keyValues) | Retrieves an entity using its ID(s). |
| Get | TResponse? Get<TId>(TId id) | Retrieves an entity using its ID. |
| Create | TResponse Create(TInput data) | Creates a new record using the input data. |
| Create | TResponse Create(TInput data, IFormFileCollection files) | Creates a new record using the input data and associated files. |
| Update | TResponse Update(TInput data) | Updates the existing record using the input data. |
| Update | TResponse Update(TInput data, IFormFileCollection files) | Updates the existing record using the input data and associated files. |
| Delete | bool Delete(params object[] keyValues) | Removes an entity using its ID(s). |
| DeleteMany | bool DeleteMany<TId>(TId[] ids) | Removes the entities matching the informed IDs. |
Interface
If you use the Model pattern instead of Input/Response for this entity, you only need to provide the model type once.
public interface IMyAppService : IEntityAppService<MyModel>
{
// ... Other methods' signatures
}
public interface IMyAppService : IEntityAppService<MyInput, MyResponse>
{
// ... Other methods' signatures
}
Implementation
If you use the Model pattern instead of Input/Response for this entity, you only need to provide the model type once.
public class MyAppService : BaseEntityAppService<IMyDomainService, MyModel>, IMyAppService
{
public MyAppService(IServiceProvider serviceProvider) : base(serviceProvider) { }
// ... Other methods
}
public class MyAppService : BaseEntityAppService<IMyDomainService, MyInput, MyResponse>,
IMyAppService
{
public MyAppService(IServiceProvider serviceProvider) : base(serviceProvider) { }
// ... Other methods
}