Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to build view model?

I'm using asp.net mvc with entity framework and starting to learn DDD. I'm working on project that contains surveys. Here's my domain model:

public class Survey
{
    public int? SurveyID { get; set; }
    public string Name { get; set; }
    public decimal MinAcceptanceScore { get; set; }
    public int UserFailsCount { get; set; }

    public IEnumerable<SurveyQuestion> Questions { get; set; }
    public IEnumerable<Prize> Prizes { get; set; }
    public IEnumerable<SurveyAttempt> UserAttempts { get; set; }
}

I need different parts of surveys for different views so I've created different ViewModels:

    public class ShortSurveyViewModel
    {
        public int? SurveyID { get; set; }
        public string Name { get; set; }
        public int UserFailsCount { get; set; }
        public IEnumerable<SurveyAttempt> UserAttempts { get; set; }
    }

    public class ShortSurveyWithPrizesViewModel
    {
        public int? SurveyID { get; set; }
        public string Name { get; set; }
        public int UserFailsCount { get; set; }
        public IEnumerable<SurveyAttempt> UserAttempts { get; set; }
        public IEnumerable<Prize> Prizes { get; set; }
    }

    public class SurveyEditViewModel
    {
        public int? SurveyID { get; set; }
        public string Name { get; set; }
        public decimal MinAcceptanceScore { get; set; }
        public int UserFailsCount { get; set; }

        public IEnumerable<SurveyQuestion> Questions { get; set; }
        public IEnumerable<Prize> Prizes { get; set; }
    }

What would be the best way to build my architecture if I want my survey repository to get information needed for appropriete view model?

Different solusions that I see:

  1. Repository could return IQueryable to SurveyService and service could return the appropriete view model, but I hesitate that doing this is right because I think view models should be created in UI, not Service layer.

  2. Create three appropriate classes in my domain layer. But now domain will be dependent from representation and with each new view new domain class should be created.

  3. Retrieve full domain object and map just properties that needed for particular view. This is not good because in my example Questions only needed in one representation and it could be heavy collection.

like image 747
Oleksii Aza Avatar asked Mar 20 '13 18:03

Oleksii Aza


People also ask

What should ViewModel contain?

The viewmodel may expose the model directly, or properties related to the model, for data-binding. The viewmodel can contain interfaces to services, configuration data, etc in order to fetch and manipulate the properties it exposes to the view.


1 Answers

Domain driven design:

  • You should have a repository returning aggregate root - in your case Survey and all relations which cannot exist without parent Survey
  • This repository will load always whole Survey class and depending on your requirements just some relations (the really dogmatic DDD would always load whole aggregate but that is not a good approach for stateless web).
  • Your application layer (controller) will ask repository for Survey and selected relations and fills view models.

Onion architecture:

  • You will create some repository exposing IQueryable<Survey> - even worse you will use generic repository with CRUD interface
  • You will create some service calling repository and building Linq-to-entities projection into your DTOs and returning them to application layer (controller)
  • Now what? You can either use those DTOs directly or use another set of objects used as your view models with some UI related attributes etc. There is obviously something wrong ...

Simple architecture:

  • You will use injected IDbSet<Survey> directly in your controller as a repository
  • You will make Linq-to-entities projections directly in your controller to fill view models

There is no best way. It is always about your goal and about your expectations. For small applications you can live with simple architecture without any issue.

Domain driven design is more complex. The main concept in DDD are domain entities, value objects and their composition. Domain entity encapsulates data and logic executed on those data. DDD does not work with partial data or DTOs - when your domain entities don't have any logic you are doing it wrong (it is called anemic model). The service in DDD is not mediator between application layer and repository. It is used to handle business logic which is not related to single domain entity (so cannot be encapsulate in domain entity). Repository is infrastructure code needed to materialize your aggregates from storage and to persist them in storage. Application logic (controller) can interact with domain entities, services and infrastructure code.

I don't like onion architecture.

like image 137
Ladislav Mrnka Avatar answered Sep 29 '22 04:09

Ladislav Mrnka