locked
Which is the best approach to show a viewmodel RRS feed

  • Question

  • User1984354752 posted

    Hi  there:

    I'm a newbie  but enthusiastic guy who loves coding .I do understand the MVC arquitecture and the use of  viewmodel. I also successful implemented a generic repository pattern in my web asp.net core project. However I'm stuck in this:

    1) Following the generic repository and unit of work pattern my controllers consume   methods that return entities which I believe is correct.  The method below  provides the  list of all the records of the Contract entity  and the related contract amount entity .  What follows is what I used to do in the past.......I used to create  an  anonymous type -like query to  load the json return to feed the view . I recently learn that this approach isn't a right one ( separation of concern) and I should use viewmodel instead. 

    var Contract_List = from i in db.Contractrepository.Getlist(includeProperties: "Company,Contract_Amounts")
    select new
    {
    ID = i.ID,
    i.IdCompany,
    i.Contractdescription,
    i.ContractValue,
    Startdate = i.Startdate,
    Enddate = i.Enddate,
    i.Company.Companyname,
    WorkDone = db.Invoicerepository.Getlist(includeProperties: "Contract_Amounts", filter: y => y.Contract_Amounts.IdContract == i.ID).Sum(j => j.Workdone),
    Budgeted = i.Contract_Amounts.Select(p => p.SAP_Budget).Sum(),
    commitment = i.Contract_Amounts.Select(p => p.ContractBreakdownAmount).Sum(),
    i.Total

    };


    return Json(new { rows = Contract_List });

    Accordingly,  I'm busy creating  a viewmodel with the above properties. Now my understanding about viemodels is that in you solely declare in your viewmodel class  the properties and  you calculate them in the controller ...right? I this is the case , then I can calculate the Wordone property in the viewmodel exactly as I did it before using the invoice repository method 

    WorkDone = db.Invoicerepository.Getlist(includeProperties: "Contract_Amounts", filter: y => y.Contract_Amounts.IdContract == i.ID).Sum(j => j.Workdone)

    If this is the case, is basically a copy and paste exercise...right? 

    2) I read also that another solution is to create another layer ( bussiness layer is name ?? ) where I get access to all the related data via de DBcontext  and perform all the aggregate calculations and later pass  the results to the viewmodel  ? I think that is this way everything is encapsulated in one specific place of the application and the controller will  just render  the viewmodel  to a view 

    Which of these two is the right approach. I also read  about automapping between the model and viewmodel but fail to understand its use  ...for instance the above properties of the above  viewmodel differs from the actual model so how the mapping works?????

    I will appreciate if you can send me some example or demos so I can see your explanation with an example. 

    Thanking  you in advance. 

    Sunday, July 19, 2020 1:25 PM

Answers

  • User1120430333 posted

    The object's method that  is being unit tested that references the DAL can mockout the DAO, since the DAO implements an interface. :)

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, July 20, 2020 8:23 PM

All replies

  • User475983607 posted

    Now my understanding about viemodels is that in you solely declare in your viewmodel class  the properties and  you calculate them in the controller ...right?

    The term "ViewModel" refers to a Model class within an MVC application that a View uses to populate dynamic HTML.  Data passed through application layers is commonly called a DTO or POCO. 

    I read also that another solution is to create another layer ( bussiness layer is name ?? ) where I get access to all the related data via de DBcontext  and perform all the aggregate calculations and later pass  the results to the viewmodel  ?

    A business layer sits between an application or application server and the data access layer.  In your architecture, the data access layer is a custom Unit of Work.  There is nothing stopping you from interacting with the DbContext (entity Framework) directly but doing so bypasses the custom Unit of Work pattern rendering the custom Unit of Work useless.  

    My recommendation is dropping the Unit of Work pattern and going to a DDD (Domain Driven Design) pattern.  Which is basically option 2.

    Sunday, July 19, 2020 2:01 PM
  • User-474980206 posted

    you should understand what problem the repository and unit of work pattens solve.

    the repository pattern solves two problems. the first is the ability to change database engine and only having to change code in one place or configure at deployment. The second (and typically more import) is to be able to mock for unit tests. typically the repository is low level.

    the unit of work pattern is layer over the repository. It handles transactions (say master / detail updates). the main use of the unit of work pattern is to allow mocking for unit tests.  

    these two patterns are very popular in java world where unit testing and interface design are very popular. as formal coding practice from the java world have been moving to the c# world, we see these patterns.

    as generally you do not write units tests for the repository and even the unit of work (as its so dependent on the repository), I prefer an adapter pattern for persistent store access, which is like the the two combined. now days often this is implemented as a micro service. the api should be mockable.

    there are some common patterns on top of these. you might want to review the saga pattern which is very popular with micro services / serverless processing. you also might want to review graphQL as an alternative.

    in general database layer return entity models which are formal definition of the database properties. in MVC the view models are the data messages passed between the controller and view, and the view to the controller. while an entity model can be used instead of a new model, you are highly coupling your controller / view interactions. this would make sense for a simple admin crud pages, but less sense for a complex  application.

    if the database is just a backing store for the controller actions, then using entities makes more sense because they are tightly coupled by definition.

     

    Monday, July 20, 2020 3:35 PM
  • User1120430333 posted

    1) Following the generic repository and unit of work pattern my controllers consume 

    The generic repository is frowned upon IMO. And besides,  the UoW and repository patterns are already being used by the Entity Framework. 

    https://docs.microsoft.com/en-us/dotnet/api/system.data.entity.dbcontext?view=entity-framework-6.2.0

    <copied>

    A DbContext instance represents a combination of the Unit Of Work and Repository patterns such that it can be used to query from a database and group together changes that will then be written back to the store as a unit. DbContext is conceptually similar to ObjectContext.

    <end>

    https://programmingwithmosh.com/net/common-mistakes-with-the-repository-pattern/

    https://blog.sapiensworks.com/post/2012/03/05/The-Generic-Repository-Is-An-Anti-Pattern.aspx

    Accordingly,  I'm busy creating  a viewmodel with the above properties. Now my understanding about viemodels is that in you solely declare in your viewmodel class  the properties and  you calculate them in the controller ...right? I this is the case , then I can calculate the Wordone property in the viewmodel exactly as I did it before using the invoice repository method

    The calculations should be done in the Models folder IMHO. 

    <copied>

    An MVC model contains all of your application logic that is not contained in a view or a controller. The model should contain all of your application business logic, validation logic, and database access logic. 

    A view should contain only logic related to generating the user interface. A controller should only contain the bare minimum of logic required to return the right view or redirect the user to another action (flow control). Everything else should be contained in the model.

    In general, you should strive for fat models and skinny controllers. Your controller methods should contain only a few lines of code. If a controller action gets too fat, then you should consider moving the logic out to a new class in the Models folder.

    <end>

    I use the DAO and DTO patterns in a layered architectural style that's implementing SoC

    https://en.wikipedia.org/wiki/Separation_of_concerns

    https://www.c-sharpcorner.com/UploadFile/56fb14/understanding-separation-of-concern-and-Asp-Net-mvc/

    https://docs.microsoft.com/en-us/previous-versions/msp-n-p/ee658117(v=pandp.10)

    https://javarevisited.blogspot.com/2013/01/data-access-object-dao-design-pattern-java-tutorial-example.html

    https://www.codeproject.com/Articles/1050468/Data-Transfer-Object-Design-Pattern-in-Csharp

    About the viewmodel.....

    https://www.dotnettricks.com/learn/mvc/understanding-viewmodel-in-aspnet-mvc

    https://deviq.com/kinds-of-models/

    An example project where you can see things in action.  :)

    https://github.com/darnold924/PublishingCompany

    Monday, July 20, 2020 4:57 PM
  • User-474980206 posted

    While EF core is implemented with the repository and unit of work patterns, it does not support mocking in c# land except via a in memory database You may still need to define a wrapping interface. 

    Monday, July 20, 2020 5:48 PM
  • User1120430333 posted

    IMHO, unit testing EF is a waste of time. The time could be used to integration test from the DAL the DAO objects that are using EF,  using a test hosting solution such as MSTest, Reshaper or others and integration test with a testing classlib project referencing the DAL.

    Any object that uses the DAL DAO in unit testing would simply mockout the DAO. 

    Monday, July 20, 2020 6:21 PM
  • User-474980206 posted

    I don’t think you should unit test the dal, but the dal often needs to be an interface so it can be mocked.

    Monday, July 20, 2020 6:40 PM
  • User1120430333 posted

    The object's method that  is being unit tested that references the DAL can mockout the DAO, since the DAO implements an interface. :)

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, July 20, 2020 8:23 PM
  • User1984354752 posted

    Thanks Da924 ..I got it 

    Friday, July 24, 2020 4:38 PM