5

I'm following the repository pattern with service layers in my project. For each view I'm going to create a viewmodel.

What I'm confused is that, should the service layer directly access domain objects and returns them to the controller, or should I use DTOs. If I should use DTOs, where to put them in the project architecture?

Thank you.

SherleyDev
  • 335
  • 5
  • 21

1 Answers1

9

Service layer is responsible for mapping (converting) Dto objects and Domain objects by implementing proper business logic.

Your DTO objects should be used in controllers and services.

DTO's are transfered between Controller and Service, on the other hand Domain objects are transfered between Service and Repository

Controller does not know about Domain and Repository does not know about DTO. Service knows both DTO and Domain and converts them each other with business rules like a car between driver and road, like stackoverflow between you and me, like everything, abstraction...

Following code is an example. Consider each namespace is a package.

namespace Controllers
{
    using Services;
    using DataTransferObjects;

    public class CoffeeController
    {
        public ICoffeeService CoffeeService { get; set; }

        public JsonResult GetCoffee(GetCoffeeInDto inDto)
        {
            var result = CoffeeService.GetCoffee(inDto);
            return JsonResult(result);
        }

        public JsonResult SaveCoffee(SaveCoffeeInDto inDto)
        {
            var outDto = CoffeeService.SaveCoffee(inDto);
            return JsonResult(outDto);
        }
    }
}

namespace Services
{
    using DataTransferObjects;
    public interface ICoffeeService
    {
        GetCoffeeOutDto GetCoffee(GetCoffeeInDto inDto);
        SaveCoffeeOutDto SaveCoffee(SaveCoffeeInDto inDto);
    }
}

namespace Services.Impl
{
    using Services;
    using Repository;
    using DataTransferObjects;
    using Domain;

    public class CoffeeService : ICoffeeService
    {
        public ICoffeeRepository CoffeeRepository { get; set; }
        public GetCoffeeOutDto GetCoffee(GetCoffeeInDto inDto)
        {
            var entity = CoffeeRepository.Get(inDto.Id);
            return new GetCoffeeOutDto {Id = entity.Id, Name = entity.Name};
        }

        public SaveCoffeeOutDto SaveCoffee(SaveCoffeeInDto inDto)
        {
            var entity = new CoffeeEntity {Name = inDto.Name};
            CoffeeRepository.Save(entity);
            return new SaveCoffeeOutDto {Id = entity.Id};
        }
    }
}

namespace Repository
{
    using Domain;
    public interface ICoffeeRepository
    {
        CoffeeEntity Get(int id);
        void Save(CoffeeEntity coffeeEntity);
    }
}

namespace Repository.Impl
{
    using Repository;
    using Domain;

    public class CoffeeRepository:ICoffeeRepository
    {
        public CoffeeEntity Get(int id)
        {
            //get entity from db
            throw new System.NotImplementedException();
        }

        public void Save(CoffeeEntity coffeeEntity)
        {
            //insert entity into db
            throw new System.NotImplementedException();
        }
    }
}

namespace DataTransferObjects
{
    public class SaveCoffeeInDto
    {
        public string Name { get; set; }
    }

    public class SaveCoffeeOutDto
    {
        public int Id { get; set; }
    }

    public class GetCoffeeInDto
    {
        public int Id { get; set; }
    }

    public class GetCoffeeOutDto
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
}

namespace Domain
{
    public class CoffeeEntity
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
}
Community
  • 1
  • 1
mehmet mecek
  • 2,615
  • 2
  • 21
  • 25
  • If I send CoffeeEntity to the controller rather than GetCoffeeInDto, do I break rules of the architecture? It seems to me rewriting domain objects just to make use of DTOs. – SherleyDev Nov 02 '13 at 06:39
  • Yes, if you send an entity to controller, you violate the architecture. But you don't have to use this architecture, if your project is not large and your business is not complicated enough. Seperating objects as Dto and Entity is about distinction between information and data. With respect to the seperation of concerns principle, playing with data in data layer and playing with information in presentation layer are thought as seperate concerns and held with use of seperate class implementations. – mehmet mecek Nov 03 '13 at 01:03
  • +1 Excellent answer. @SherleyDev Have a look here: http://stackoverflow.com/a/21569720/654708 for a more detailed answer. Note, it's not inherently bad to bind your controller to your domain models; for smaller projects, creating DTOs could be considered overkill. – GFoley83 Jan 09 '16 at 06:19