docs/en/framework/architecture/best-practices/application-services.md
//[doc-seo]
{
"Description": "Explore best practices for implementing Application Services in ABP Framework, ensuring effective use of Domain-Driven Design principles."
}
This document offers best practices for implementing Application Services classes in your modules and applications based on Domain-Driven-Design principles.
Ensure you've read the Application Services document first.
interface for each application service in the application contracts package.IApplicationService interface.AppService postfix for the interface name (ex: IProductAppService).Do define a basic DTO for an aggregate root.
User.Password).IHasExtraProperties).Example:
[Serializable]
public class IssueDto : ExtensibleFullAuditedEntityDto<Guid>
{
public string Title { get; set; }
public string Text { get; set; }
public Guid? MilestoneId { get; set; }
public Collection<IssueLabelDto> Labels { get; set; }
}
[Serializable]
public class IssueLabelDto
{
public Guid IssueId { get; set; }
public Guid LabelId { get; set; }
}
Do define a detailed DTO for an entity if it has reference(s) to other aggregate roots.
User.Password).MilestoneId in the example above). Will already add details for the reference properties.Example:
[Serializable]
public class IssueWithDetailsDto : ExtensibleFullAuditedEntityDto<Guid>
{
public string Title { get; set; }
public string Text { get; set; }
public MilestoneDto Milestone { get; set; }
public Collection<LabelDto> Labels { get; set; }
}
[Serializable]
public class MilestoneDto : ExtensibleEntityDto<Guid>
{
public string Name { get; set; }
public bool IsClosed { get; set; }
}
[Serializable]
public class LabelDto : ExtensibleEntityDto<Guid>
{
public string Name { get; set; }
public string Color { get; set; }
}
GetAsync(...) instead of GetProductAsync(...) in the IProductAppService.GetAsync method name.Task<QuestionWithDetailsDto> GetAsync(Guid id);
GetListAsync method name.Task<List<QuestionWithDetailsDto>> GetListAsync(QuestionListQueryDto queryDto);
CreateAsync method name.ExtensibleObject (or any other class implements the IHasExtraProperties) to allow to pass extra properties if needed.Example method:
Task<QuestionWithDetailsDto> CreateAsync(CreateQuestionDto questionDto);
The related DTO:
[Serializable]
public class CreateQuestionDto : ExtensibleObject
{
[Required]
[StringLength(QuestionConsts.MaxTitleLength,
MinimumLength = QuestionConsts.MinTitleLength)]
public string Title { get; set; }
[StringLength(QuestionConsts.MaxTextLength)]
public string Text { get; set; } //Optional
public Guid? CategoryId { get; set; } //Optional
}
UpdateAsync method name.ExtensibleObject (or any other class implements the IHasExtraProperties) to allow to pass extra properties if needed.Example:
Task<QuestionWithDetailsDto> UpdateAsync(Guid id, UpdateQuestionDto updateQuestionDto);
DeleteAsync method name.Task DeleteAsync(Guid id);
Task<int> VoteAsync(Guid id, VoteType type);
This method votes a question and returns the current score of the question.
ProductAppService class for the IProductAppService interface.ApplicationService base class.IProductRepository).IRepository<Product>).MapExtraPropertiesTo extension method (see) or configure the object mapper (MapExtraProperties) to allow application developers to be able to extend the objects and services.IFormFile or Stream in the application services. If you want to serve a file you can use byte[].Controller to handle file uploading then pass the byte[] of the file to the application service method.