Application Services are used to expose domain logic to the presentation layer. An Application Service is called from presentation layer with a DTO (Data Transfer Object) as parameter, uses domain objects to perform some specific business logic and returns a DTO back to the presentation layer. Thus, Presentation layer is completely isolated from Domain layer. In an ideally layered application, presentation layer never directly works with domain objects.

IApplicationService interface

In ASP.NET Boilerplate, an application service should implement IApplicationService interface. It's good to create an interface for each Application Service. So, we first define an interface for an application service as shown below:

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

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

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

    public string EmailAddress { get; set; }
}

Then we can implement the 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 some important points here:

ApplicationService class

An application service should implement IApplicationService interface. Also, optionally, can be derived from ApplicationService base class. Thus, IApplicationService is inherently implemented. Also, ApplicationService class has some base functionality that makes easy to logging and localization. It's suggested to create a special base class for your application services that extends ApplicationService class. Thus, you can add some common functionality for all your application services. A sample application service class is shown below:

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 can have a base class which defines LocalizationSourceName in it's constructor. Thus, you do not repeat it for all service classes. See logging and localization documents for more informations on this topics.

Unit of work

An application service method is a unit of work by default in ASP.NET Boilerplate.

For connection & transaction management

Say that we want to call two repository method in an application service method those must be transactional. Example:

public void CreatePerson(CreatePersonInput input)
{
    var person = new Person { Name = input.Name, EmailAddress = input.EmailAddress };    
    _personRepository.Insert(person);
    _statisticsRepository.IncrementPeopleCount();
}

We inserted an item to People table, then incremented people count that is stored in another table field. These methods are implemented in different repositories but shares same connection and transaction. So, how?

A database connection is opened and a transaction is started at the beginning of CreatePerson method by ASP.NET Boilerplate automatically. At the end of the method, the transaction is commited if no exception occurs and the connection is closed. Thus, all database operations in CreatePerson method is transactional (atomic) and rolled back if any exception is thrown. Thus, two repository methods in this example shares same connection and transaction.

When you call GetAll() method of a repository, it returns an IQueryable<T>. Database connection should be open after calling the repository method. This is because of deferred execution of IQueryable<T> and LINQ. Database query is actually performed when you call ToList() method. See the example below:

public SearchPeopleOutput SearchPeople(SearchPeopleInput input)
{
    //Get IQueryable<Person>
    var query = _personRepository.GetAll();

    //Add some filters if selected
    if (!string.IsNullOrEmpty(input.SearchedName))
    {
        query = query.Where(person => person.Name.StartsWith(input.SearchedName));
    }

    if (input.IsActive.HasValue)
    {
        query = query.Where(person => person.IsActive == input.IsActive.Value);
    }

    //Get paged result list
    var people = query.Skip(input.SkipCount).Take(input.MaxResultCount).ToList();

    return new SearchPeopleOutput {People = Mapper.Map<List<PersonDto>>(people)};
}

Since an application service method is a unit of work, database connection is open during the method execution. If you use GetAll() in a class that is not an application service, you should explicitly use unit of work.

Note that I used AutoMapper library to convert List<Person> to List<PersonDto>. See DTO document for details.

For automatically saving changes

For a unit of work method, ASP.NET Boilerplate saves all changes at the end of the method automatically. Assume that we need an application service method to update name of a person:

public void UpdateName(UpdateNameInput input)
{
    var person = _personRepository.Get(input.PersonId);
    person.Name = input.NewName;
}

That's all, name was changed! We did not even called _personRepository.Update method. O/RM framework keep track of all changes of entities in a unit of work and reflects changes to the database.

More

See unit of work documentation for more.

Lifecycle of an application service

All application service instances are Transient. It means, they are instantiated per usage. ASP.NET Boilerplate strongly uses Dependency Injection technique. When an application service class needed to be injected, a new instance of the class is created automatically by dependency injection container. See Dependency Injection documentation for more information.