& Lt; ABP framework & gt; Application Service, and abp Framework Application Service

Source: Internet
Author: User
Tags automap

<ABP framework> application service, and abp Framework Application Service

Document directory

 

Content of this section:

  • IApplicationService Interface
  • ApplicationService class
  • CrudAppService and AsyncCrudAppService
    • Simple CRUD application service example
    • Custom CRUD Application Service
      • Retrieve list
      • Create and update
      • Others
  • Work Unit
  • One application service Lifecycle

 

The Application Service exposes the domain logic to the presentation layer. An Application Service is called by the presentation layer using a DTO (data transmission object) parameter. It uses a domain object to execute some special business logic and returns a DTO to the presentation layer. Therefore, the presentation layer is completely independent from the domain layer. In an ideal layered application, the presentation layer never directly uses domain objects.

 

IApplicationService Interface

An Application Service should implement the IApplicationService interface in the ABP. It is a good practice to create an interface for each application service. Therefore, we first create an interface for an application service, as shown below:

public interface IPersonAppService : IApplicationService{    void CreatePerson(CreatePersonInput input);}

IPersonAppService has only one method. It is used by the presentation layer to create a new person. CreatePersonInput is a DTO object, as shown below:

public class CreatePersonInput{    [Required]    public string Name { get; set; }    public string EmailAddress { get; set; }}

Then we can implement IPersonAppService:

public class PersonAppService : IPersonAppService{    private readonly IRepository<Person> _personRepository;    public PersonAppService(IRepository<Person> personRepository)    {        _personRepository = personRepository;    }    public void CreatePerson(CreatePersonInput input)    {        var person = _personRepository.FirstOrDefault(p => p.EmailAddress == input.EmailAddress);        if (person != null)        {            throw new UserFriendlyException("There is already a person with given email address");        }        person = new Person { Name = input.Name, EmailAddress = input.EmailAddress };        _personRepository.Insert(person);    }}

There are several key points:

  • PersonAppService uses IRepository <Person> to perform database operations. It uses the constructor injection mode. Here we use dependency injection.
  • PersonAppService implements IApplicationService (because IPersonAppService extends the IApplicationService). It is automatically injected to the dependency injection system by ABP and then injected and used by other classes. Naming Conventions are important here. view the dependency injection document for more information.
  • The CreatePerson method obtains the CreatePersonInput, which is an input DTO and automatically verified by the ABP. For more details, see the DTO and verification documentation.

 

ApplicationService class

An Application Service should implement the IApplicationService interface. As shown above, it can also inherit from the ApplicationService base class at will, because it implements IApplicationService internally and some basic functions of ApplicationService, it makes logs and localization easier. We recommend that you create a special base class that inherits the ApplicationService class for your application service to add some common functions to all application services. An example of an application service is as follows:

public class TaskAppService : ApplicationService, ITaskAppService{    public TaskAppService()    {        LocalizationSourceName = "SimpleTaskSystem";    }    public void CreateTask(CreateTaskInput input)    {        //Write some logs (Logger is defined in ApplicationService class)        Logger.Info("Creating a new task with description: " + input.Description);        //Get a localized text (L is a shortcut for LocalizationHelper.GetString(...), defined in ApplicationService class)        var text = L("SampleLocalizableTextKey");        //TODO: Add new task to database...    }}

You have a base class that defines LocalizationSourceName In the constructor, so that you do not need to repeatedly define all service classes. For more information about this topic, see the log and localization documentation.

 

CrudAppService and AsyncCrueAppService

If you need to Create an application service that contains the Create, Update, Delete, and GetAll methods for a specific object, you can inherit from CrudAppService (or AsyncCrudAppService, Create Asynchronous Method, the CrudAppService base class is a generic type with the related Entity and DTO types as parameters, and can be customized by using the rewrite function.

 

Simple CRUD application service example

Assume that you have a Task object, which is defined as follows:

public class Task : Entity, IHasCreationTime{    public string Title { get; set; }    public string Description { get; set; }    public DateTime CreationTime { get; set; }    public TaskState State { get; set; }    public Person AssignedPerson { get; set; }    public Guid? AssignedPersonId { get; set; }    public Task()    {        CreationTime = Clock.Now;        State = TaskState.Open;    }}

We create a DTO for this object:

[AutoMap(typeof(Task))]public class TaskDto : EntityDto, IHasCreationTime{    public string Title { get; set; }    public string Description { get; set; }    public DateTime CreationTime { get; set; }    public TaskState State { get; set; }    public Guid? AssignedPersonId { get; set; }    public string AssignedPersonName { get; set; }}

The AutoMap feature creates ing configurations between entities and DTO. Now, we can create an application service, such:

public class TaskAppService : AsyncCrudAppService<Task, TaskDto>{    public TaskAppService(IRepository<Task> repository)         : base(repository)    {    }}

We inject warehousing and pass it to the base class (if you want to use the synchronous method, we can inherit from CrudAppService ). This is all the code! TaskAppService now has a simple CRUD method. If you want to create an interface for this application service, you can do the following:

public interface ITaskAppService : IAsyncCrudAppService<TaskDto>{        }

Note: IAsyncCrudAppService does not use an object (Task) as a generic parameter. Because the object is related to the implementation, it should not be included in the public interface. Next, we can implement the ITaskAppService interface for the TaskAppService class:

public class TaskAppService : AsyncCrudAppService<Task, TaskDto>, ITaskAppService{    public TaskAppService(IRepository<Task> repository)         : base(repository)    {    }}

 

Custom CRUD Application Service

Retrieve list

The GetAll method of the Crud Application Service uses PagedAndSortedResultRequestInput as the parameter by default. This parameter provides optional sorting and paging parameters, but you may want to add another parameter for the GetAll method, for example: you want to add custom filters. In this case, you can create a dto for the GetAll method, such:

public class GetAllTasksInput : PagedAndSortedResultRequestInput{    public TaskState? State { get; set; }}

We inherit from PagedAndSortedResultRequestInput (not required, but we can get the paging and sorting parameters directly from the base class) and add an empty State attribute to filter tasks. Now we should modify TaskAppService to accept custom Filtering:

public class TaskAppService : AsyncCrudAppService<Task, TaskDto, int, GetAllTasksInput>{    public TaskAppService(IRepository<Task> repository)        : base(repository)    {    }    protected override IQueryable<Task> CreateFilteredQuery(GetAllTasksInput input)    {        return base.CreateFilteredQuery(input)            .WhereIf(input.State.HasValue, t => t.State == input.State.Value);    }}

First, we add the GetAllTasksInputAsyncCrudAppService 4th generic parameters (the third is the object primary key type), and then override the CreateFilteredQuery method to implement custom filtering, this method is an extension point of the AsyncCrudAppService class (WhereIf is an extension of the ABC method to simplify conditional filtering, but what we actually do is simply filter an IQueryable ).

Note: If you have created an application service interface, you need to add the same generic parameters for the interface.

 

Create and update

Note: we use the same DTO (TaskDto) for obtaining, creating, and updating tasks. This may not be good in practical applications. Therefore, we want to customize DTO for creation and updating, let's start by creating a CreateTaskInput class:

[AutoMapTo(typeof(Task))]public class CreateTaskInput{    [Required]    [MaxLength(Task.MaxTitleLength)]    public string Title { get; set; }    [MaxLength(Task.MaxDescriptionLength)]    public string Description { get; set; }    public Guid? AssignedPersonId { get; set; }}

Create an UpdateTaskInput DTO:

[AutoMapTo(typeof(Task))]public class UpdateTaskInput : CreateTaskInput, IEntityDto{    public int Id { get; set; }    public TaskState State { get; set; }}

We inherit all attributes from CreateTaskInput for the Update operation (but you may not do this). Here we must implement IEntity (or IEntity different from the int type primary key <PrimaryKey> ), because we need to know which object needs to be updated. At last, I added an additional property State which is not included in CreateTaskInput.

Next, we can use these DTO classes as the generic interfaces of the AsyncCrudAppService class, as shown below:

public class TaskAppService : AsyncCrudAppService<Task, TaskDto, int, GetAllTasksInput, CreateTaskInput, UpdateTaskInput>{    public TaskAppService(IRepository<Task> repository)        : base(repository)    {    }    protected override IQueryable<Task> CreateFilteredQuery(GetAllTasksInput input)    {        return base.CreateFilteredQuery(input)            .WhereIf(input.State.HasValue, t => t.State == input.State.Value);    }}

You do not need to modify other code.

 

Others

If you want to customize the DTO of the input of the Get and Delete methods, AsyncCrudAppService can accept more generic parameters. Similarly, all basic class methods are virtual, so you can rewrite them for behavior customization.

 

Work Unit

An application service method is a unit of work in ABP. Therefore, any application service method is transactional and is automatically saved to the database at the end of the method.

For more information, see the work unit document.

 

Lifecycle of an Application Service

All application service entities are temporary. For more information, see the dependency injection documentation.

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.