Skip to main content

application-services

Writes or reviews an ABP application service — the DTO-taking, DTO-returning boundary between the domain and the presentation/API layer. USE FOR: implementing IApplicationService/ApplicationService for non-CRUD use cases, using AbstractKeyCrudAppService for composite or non-standard keys, and unit-of-work basics. DO NOT USE FOR: exposing application services as auto/conventional API controllers, routes, verbs or [RemoteService] (use expose-http-apis); a complete standard-key CrudAppService workflow (use build-crud-application-services); detailed object-to-DTO mapping mechanics/profiles (use map-objects-and-dtos); DTO validation attributes and business exceptions (use handle-validation-and-errors); permission definitions and authorization policy (use permissions-and-authorization); the overall layered project structure (use layered-architecture).

Ir a la instalación

Datos de origen

Repositorio
abpframework/abp-skills
Última actividad en el origen
20 de julio de 2026 a las 03:24
Idioma detectado de SKILL.md
inglés
Estrellas
18
Forks
0

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
application-services
description
Writes or reviews an ABP application service — the DTO-taking, DTO-returning boundary between the domain and the presentation/API layer. USE FOR: implementing IApplicationService/ApplicationService for non-CRUD use cases, using AbstractKeyCrudAppService for composite or non-standard keys, and unit-of-work basics. DO NOT USE FOR: exposing application services as auto/conventional API controllers, routes, verbs or [RemoteService] (use expose-http-apis); a complete standard-key CrudAppService workflow (use build-crud-application-services); detailed object-to-DTO mapping mechanics/profiles (use map-objects-and-dtos); DTO validation attributes and business exceptions (use handle-validation-and-errors); permission definitions and authorization policy (use permissions-and-authorization); the overall layered project structure (use layered-architecture).
license
MIT
# ABP Application Services Application services implement use cases. They take and return **DTOs** (never entities), orchestrate domain objects and repositories, and are the boundary between the domain and the presentation/API layer. ## When to Use - Implementing an application service (interface in `*.Application.Contracts`, class in `*.Application`). - Using `AbstractKeyCrudAppService` when standard repository key lookup is not available. - Understanding the ambient unit of work around app service methods. ## When Not to Use - **Object-to-DTO mapping mechanics** (AutoMapper profiles, Mapperly, custom mappers) — use map-objects-and-dtos; here mapping appears only as `ObjectMapper.Map` usage. - **A complete standard-key `CrudAppService` workflow** — use build-crud-application-services for contract overloads, policies, filtering, sorting, paging, mapping paths, and operation validation. - **DTO validation attributes and business/error exceptions** — use handle-validation-and-errors; this skill only notes that validation runs automatically. - **Permission definitions and authorization policy** — use permissions-and-authorization; `[Authorize]` here is just wiring. - **Overall layered project structure** — use layered-architecture. ## Base class & interface Define the interface in `*.Application.Contracts` and the implementation in `*.Application`. Implement `IApplicationService` (namespace `Volo.Abp.Application.Services`) on the interface and derive from `ApplicationService` (same namespace) in the class: ```csharp // *.Application.Contracts public interface IBookAppService : IApplicationService { Task<BookDto> GetAsync(Guid id); Task<BookDto> CreateAsync(CreateBookDto input); } // *.Application public class BookAppService : ApplicationService, IBookAppService { private readonly IRepository<Book, Guid> _bookRepository; public BookAppService(IRepository<Book, Guid> bookRepository) => _bookRepository = bookRepository; public async Task<BookDto> GetAsync(Guid id) { var book = await _bookRepository.GetAsync(id); return ObjectMapper.Map<Book, BookDto>(book); } public async Task<BookDto> CreateAsync(CreateBookDto input) { var book = await _bookRepository.InsertAsync( new Book(GuidGenerator.Create(), input.Name)); return ObjectMapper.Map<Book, BookDto>(book); } } ``` The `ApplicationService` base gives you injected members via `LazyServiceProvider`: `ObjectMapper`, `GuidGenerator`, `CurrentUser`, `CurrentTenant`, `Logger`, `L` (localization), `AuthorizationService`, etc. ## DTOs & object mapping `ObjectMapper` is an `IObjectMapper` (namespace `Volo.Abp.ObjectMapping`). Key methods: ```csharp TDestination Map<TSource, TDestination>(TSource source); TDestination Map<TSource, TDestination>(TSource source, TDestination destination); ``` The default implementation (`DefaultObjectMapper`) delegates to a replaceable `IAutoObjectMappingProvider`, so the actual mapping is provided by the registered AutoMapper *or* Mapperly provider — the default app template registers Mapperly (`AddMapperlyObjectMapper`). One option is AutoMapper: register mappings in an AutoMapper `Profile` and add it in your module's `ConfigureServices`: ```csharp public class MyApplicationAutoMapperProfile : Profile { public MyApplicationAutoMapperProfile() { CreateMap<Book, BookDto>(); // entity -> output DTO; build the entity via its constructor, don't auto-map the input DTO onto it } } // In the *.Application module class Configure<AbpAutoMapperOptions>(options => { options.AddMaps<MyApplicationModule>(); }); ``` ## CRUD services Use **build-crud-application-services** for the complete standard-key `ICrudAppService` / `CrudAppService` contract, implementation, authorization, mapping, filtering, sorting, paging, and validation workflow. `AbstractKeyCrudAppService<...>` has the **same generic overloads** and is the variant to use when the entity does not derive from `IEntity<TKey>` (e.g. composite/non-standard keys). The only members you **must** implement are the abstract `GetEntityByIdAsync` and `DeleteByIdAsync` (key resolution). The mapping methods (`MapToEntityAsync`, `MapToGetOutputDtoAsync`, etc.) are `virtual` with default object-mapping implementations — override them only when you need custom mapping. ## Input validation Input DTOs are validated automatically because `ApplicationService` implements `IValidationEnabled` (namespace `Volo.Abp.Validation`). Use standard data annotations on DTO properties: ```csharp public class CreateBookDto { [Required] [StringLength(128)] public string Name { get; set; } [Range(typeof(decimal), "0", "999.99")] public decimal Price { get; set; } } ``` Invalid input throws `AbpValidationException` → HTTP 400 before your method body runs. Any class implementing `IValidationEnabled` gets this behavior via the validation interceptor. ## Authorization Apply `[Authorize]` at class or method level; combine with permissions defined in `*.Application.Contracts`. You can also call `CurrentUser` / `AuthorizationService` for imperative checks: ```csharp [Authorize(MyPermissions.Books.Default)] public class BookAppService : ApplicationService, IBookAppService { [Authorize(MyPermissions.Books.Create)] public async Task<BookDto> CreateAsync(CreateBookDto input) { /* ... */ } } ``` ## Exposing the service over HTTP ABP can expose an application service as a REST API controller automatically, with no controller class — configuring `ConventionalControllers.Create`, the route/verb conventions, and `[RemoteService]` toggles is the **expose-http-apis** skill's job. Write the application service here; publish it there. ## Unit of work basics Every app service method runs inside an **ambient unit of work** by default (`ApplicationService` implements `IUnitOfWorkEnabled`) — repository changes are saved and the DB transaction commits/rolls back around the method automatically, so you rarely call `SaveChanges` manually. Use `[UnitOfWork]` (namespace `Volo.Abp.Uow`) to tune behavior (e.g. transactional flag, isolation) or to make a normally non-UoW method transactional: ```csharp [UnitOfWork(isTransactional: true)] public async Task DoWorkAsync() { /* changes commit together */ } ``` If you need the current UoW imperatively, inject `IUnitOfWorkManager` and use `Current` / `Begin`. ## Validation - Confirm the service resolves and returns DTOs (never entities) — the `*.Application.Contracts` interface should reference only DTOs. - After registering the app service assembly via `ConventionalControllers.Create`, confirm the auto-generated REST endpoints appear (e.g. in Swagger) with the expected verbs (`GetAsync` → GET, `CreateAsync` → POST, etc.). - Post an invalid DTO and confirm an `AbpValidationException` → HTTP 400 before the method body runs. - Confirm repository changes persist without a manual `SaveChanges` (the ambient UoW commits around the method). ## Common Pitfalls - Application services take and return **DTOs, never entities** — leaking entities across the boundary defeats the layering. - Use **build-crud-application-services** for standard-key CRUD instead of reconstructing its contract and pipeline here. - Use `AbstractKeyCrudAppService` (not `CrudAppService`) when the entity does **not** derive from `IEntity<TKey>` (composite/non-standard keys); you must implement `GetEntityByIdAsync` and `DeleteByIdAsync`. - Validation only fires for classes implementing `IValidationEnabled` via the interceptor — `ApplicationService` already does, so validation is automatic there. - Every app service method runs in an ambient UoW by default, so avoid manual `SaveChanges` — but "ambient UoW" doesn't mean "DB transaction": with the default `Auto` mode, only HTTP `GET` requests are non-transactional; all other verbs (including `QUERY`) open a transaction unless a URL is listed in `NonTransactionalUrls`. Use `[UnitOfWork]` to tune behavior.
Ver en GitHub