2

I've gone through a few tutorials in ASP.NET Core MVC, and I've built a little app (for looking at problems in old exams) that looks roughly like this:

Solution
    Project
        ...
        Models
            Exam.cs
            Problem.cs
            SubProblem.cs
        Views
            Exam
                Index.cshtml
                Problem.cshtml
            Shared
        Controllers
            ExamController.cs
        Data
            ExamsContext.cs
            DbInitializer.cs
        Migrations
        ...

Now I asked the question, Where to put methods in a .NET Core MVC Web app? and got a few answers. Mainly that The business logic should only be in the Model because this logic is technology-agnostic.

Now I asked if this means that I should add methods to my Models (Exam.cs, Problem.cs, etc.). Wheras I got an explanation of layers, what Data Access Layer and Business Model is and what they are for.


Apparently, the DAL should communicate with the database and not contain any logic methods. In C#, these classes often have the form of a POCO. Also, this layer is part of the Model (in the MVC sense).

To me, this sounds a lot like the classes I have in my Model-folder, they are POCO's without methods used to communicate with the database?


The Business model is apparently the thing that should reflect the business reality. This is where I should add my business logic, decoupled from the database and the UI. This layer is also part of the Model (in the MVC sense).

To me this sounds almost like the classes I have in my Model folder, though they aren't really decoupled from the database (are they) I mean they get connected to the database through the DbContext don't they?


I still don't really feel I've understood how I am to implement these things into my solution above. Though I didn't wish to bloat my previous question with repeated follow up questions so I thought I'd ask new questions:

  • What are the models I have in my project called? Are they some form of "model" connected to the DAL? Are they my "Business Models"? Are they some third kind of model? The tutorials described it like the models were only code-first representations of the tables in my relational database.

  • How would I go about implementing all of these layers and other models into my solution? What would that roughly even look like?

  • Take a look into this answer of mine first. I'll get back here to give you an answer soon. – Machado Jul 13 '17 at 12:43
  • Thanks! Looked through the answer (and thanks for the laugh). Unsure on a few details, i.e how the repositories connect to their respective DAL. We instansiate ShadyReport.Repository.PersonRepository(); then call personRepository.GetAllPersons();. When and how in PersonRepository.cs is the connection to EF6OracleContext.cs made? – MrJalapeno Jul 13 '17 at 13:01
  • That depends upon what DAL you're using. I'd stick with Dapper at first, because it's one of the simplest ways to abstract the database without a high learning curve. I'll try to find an example of a Dapper repository using SQL Server for you. – Machado Jul 13 '17 at 13:22
  • This one is a pretty good example of a Dapper repository: jeremymorgan.com/blog/programming/how-to-dapper-web-api . Some people like to make it a "generic" repository, but stick with this example first. It'll help you understand the basics. Looks verbose and complex, but it's not in reality. Once you get how it's done, all of them look the same. :) – Machado Jul 13 '17 at 13:28
1

Taking into consideration this quote from the accepted answer from your original question:

Here's how I see the different layers (note for experienced readers: I've willingly simplified to make it understandable for the OP):

View <==> Controller <==> Business model <==> Data access

And taking into consideration this answer from me on an old question regarding the repository pattern, I think that you're missing a fundamental point to understand the layering or clean architecture of an ASP.Net MVC application.

And the key concept here is UI is a big layer. Breath. Calm down. I'll explain shortly.

Think of all the business rules of your application, what should it do, who will operate it. Done that ? Good.

Not implement everything using a command-line interface. Create a .Net Console Application and try to run everything you need from that console application. Do you need to add an Exam ? Good. Create an Exam entity, a ExamRepository repository, make this repository talk to your DAL (be it a lightweight ORM like Dapper or Linq To SQL or Entity Framework or NHibernate, but I'd stick with Dapper for the beginning).

Your repository should do your CRUD operations for you. No thinking, just manipulating the DAL to do the "low level" stuff.

Now, create a "business" object, like a ExamBusiness. This object may have your business rules implemented, like "an Exam must always have a student name and student name must have at least 3 characters" kind of stuff. Your business object calls your repository in order to save and retrieve data.

Now, a small change to your Console Application: Make it talk only to your Business object. Nothing more, nothing else. Your Console App should not talk to your DAL or your Repository directly.

Done that ? Good. Your application is done. Your business rules are implemented. Everything is functional. Except for one tiny detail: How your user will interact with your application.

Enters ASP.Net MVC. Or Windows Forms. Or Console App. Or WPF Service. But for all intended purposes, let's stick with ASP.Net MVC here.

In this example, ASP.Net MVC is just the UI layer. It presents Exams to users, and let users change these Exams somehow. To make things more graphic:

+-----------------+---+-------------+
| UI              | E | ASP.Net MVC |
+-----------------+ n +-------------+
| Business        | t | Another     |
+-----------------+ i | project on  |
| Repository      | t | your .Net   |
+-----------------+ y | solution.   |
| DAL             |   |             |
+-----------------+---+-------------+

But what about my Models on ASP.Net MVC ? Well they're what you should show to the user on the HTML pages. You have on your Business Objects an Entity called Exam. But do your Exam entity has all the fields necessary to be shown to the user ? What about foreign keys ? You'll need a student name for showing the exam, but you don't need the name to persist an exam, you just need the id ?

It seems that the default naming of the Models on an ASP.Net MVC application is a poor convention. What they really are are ViewModels, and not "real" Models. They are what you need to interact with the user, not the bare minimum you need for your application to work.

Bottom lines:

  1. Your Domain should be on another Class Library, do you can decouple your UI from the problem you're trying to solve;
  2. UI layer is huge. And it should be huge, giving it's importance;
  3. The sample above is based on Anaemic Domain Model and Clean Architecture. There are advocates for and against both, but you need to know that they exist and are tools you can use to advance your learning;
  4. There is no Silver Bullet. This post shows one way of organizing your solution, and a simple one to help you understand.
  5. In this example, your Entities are POCOs, and your ViewModels may or may not be POCOs. But the business logic and validation must be on the business objects, that do not have state.

I hope that helps.

  • So for example, I'll have another project called BusinessAndData (or something, not sure what's right there), which has three folders, Business, Repository and DAL? I'm using Entity Framework Core and was wondering if you perhaps could give your take on what's being said Here specifically the part about not needing the repository pattern when using EF. – MrJalapeno Jul 13 '17 at 13:33
  • "I'll have another project ... , which has three folders, Business, Repository and DAL?": Yes. But regarding the comment on EF Core not needing a Unit of Work or Repository Pattern, it's an entirely new discussion. What they're basically saying is that you can use the Context object as a repository, which may or may not hold true, and I don't have this answer as I haven't used EF Core yet. I'd suggest you open a new question specific for this. – Machado Jul 13 '17 at 15:18
  • People need to really internalize there is no Silver Bullet in Software Engineering. – johnny Jul 13 '17 at 18:05
0

In the context of the MVC pattern, a model can really be any kind of object which is exposed through an UI. The MVC pattern is not concerned about what "kind" of object the model object are - rather the whole point of the pattern is than the models can be anything. Only constraint is that models should not contain any presentation or UI-specific logic, since this should be separated out into the view and controller classes.

So the model could be connected to a DAL, but you could also have a model which is not connected to a database or persistent at all - for example in a game. The model objects could be entities representing database tables, they could also be abstractions encapsulating entities, or they could be unrelated to entities.

What kind of models you would need in you project depends on what kind of application you are writing!

0

I mean they get connected to the database through the DbContext don't they?

For me this is the revealing line in your post. You are using entity framework and it is colouring your entire approach.

Now I'm not saying EF is a terrible thing you should never use.... But!

It would probably help you to think about these problems if you did not use it.

So instead of EF imagine you have Repository objects which you can use to persist and retrieve your.. lets just call them 'business classes' for now, Exam, Problem, SubProblem and whatever others you have

public interface IRepo
{
    Exam GetExamByid(string id);
    List<Exam> GetAllExams();
    void SaveProblem(Problem p);
    ... whatever other methods we need
}

We don't care about the implementation, it just populates those classes with data from the db somehow. Data Layer, tick!

So, now we have some bit of functionality we want to add to the app, maybe it's 'Grade a completed Exam' we have written the code which takes the data from a fully populated and completed Exam object as input and outputs a Result object. The question is where should we put this code.

There are a number of answers.

  1. Procedural: Simplistic. Put the code on the a controller

We can simply have a controller with a method which loads an Exam from the repo, runs through the code right there and returns the Result object, maybe saving it again via the repo.

Pluses: light on new classes, we have to have the controller, and the code can be seen as 'Controlling' so why not.

Minuses: Binds the logic to the MVC app implementation. If we want a WPF app next week, we have to rewrite some stuff.

  1. Procedural: ADM, Create Service Classes

The next step up, we create a new project, ExamMarkerService with an ExamMarkerService class with the code in it.

We still have a controller, but it just instantiates the service, calls it and returns the results.

Minuses : more code Pluses : more separation of concerns. The controller just worried about parsing the incoming http message and sending back a reply. the service class has the logic and can be put in any application. Also, easy to swap out for new logic later.

3: OOP: Method goes with data

We add the code directly to a method on the Exam class. The controller pulls the Exam from the repository, calls Exam.Grade() and returns the result.

Pluses: No extra classes floating around Minuses: Can get complicated if you need more data than is in the Exam class alone.

Business Layer, tick!

  • Ewan, why is #2 not OOP? Those classes hold logic like the class in #3 does doen't it? I thought #2 was a business layer (I have much to learn.) – johnny Jul 13 '17 at 17:50
  • yeah, I would argue that too, but classically OOP would be #3 – Ewan Jul 13 '17 at 17:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.