This is a question related to how to structure an ASP.NET MVC project for a medium to large application.
I thought I understood the concepts of MVC but after looking into architectures for medium and large applications I am confused. (trying to take into consideration scalability, extensibility and ongoing maintenance)
My confusion come in when I try to think of how to structure an application following guidelines of 'best practices' (from many and numerous sources included printed and web)
Trying to respect things like
Now when creating small (basic, simple) MVC apps, then all of this is pretty much done in the same project (I'm talking about Visual Studio Project in this case), and the separation between the MVC "Layers" is pretty much just folders in the VS project (well separate namespaces).
With some of our other projects we have adopted a Service -> repository style, so this one is not going to be any different.
We are using Entity Framework as the DB persistence (DB first approach).
We have separated our DB access (the EF stuff) into another VS project, so we have a Web project and Models (or data) project in the solution.
The web project has the controllers and views, and the data project has the Services, Repositories and the EF stuff.
My confusion is with the models (or perhaps with understanding a Domain Model vs a View model)
If I was to try to follow the methodology (I think), I would have a domain model (the model that the EF and repository layers deal with), and then I would have a view model? (the model that the Controller and view would deal with), now wouldn't these be 90% the same? Isn't this way of separating out the concerns just making you write model code twice? As I am sure I read somewhere that Controllers and Views shouldn't have the Domain model?
One way that we have approached it is the EF makes all its model classes partial. We then extend that same class and add a MetaDataType class to it to make the 'View Model' (add the DataAnnotations to the properties) and then in essence the same model is passed through all layers, but is this 'best' practice (there is a splinter in my mind that this is just not right)
eg
[MetadataType(typeof(Product_Metadata))]
public partial class Product
{
//Pretty much deliberately kept empty, just so
// the EF model class can have the attribute added
//The other side of this partial class is of course in the EF models
}
public class Product_Metadata
{
[Required]
[Display(Name = "Product name")]
public string Name { get; set; }
[Required]
[Display(Name = "Unit Cost")]
public decimal Cost { get; set; }
//etc... for the rest of the properties on the product EF model
}
Maybe this is the 'best' way to attack it but I have not come across this method before.
We are creating all the Services and Repositories as Interfaces and using structure map as the IoC container. Another thing I admit, even though we are using the dependency Injection I am still struggling to come to terms with TDD, feels like to have to write everything twice (whole point of the DI I would think)
I suppose ultimately I am appealing to the willing here at SO that know more than me about architecting large ASP.NET MVC applications for some assistance and guidance. There seems to be a huge wealth of information out there, but all seems to be very conceptual. When I finally come to the implementation I get lost in the concepts.
EDIT
In response to Mr Karl Anderson
However, Microsoft discontinued ASP.NET MVC in 2018. While the framework still works, it isn't being actively developed, and there are no plans to release any new features or updates.
Does this mean ASP.NET Web Forms is dead and should no longer be used? Of course not! As long as the . NET Framework ships as part of Windows, ASP.NET Web Forms will be a supported framework.
MVC actually defined in two life cycles, the application life cycle, and the request life cycle. The Starting point for every MVC application begins with routing. After that, the received request figures out and finds how it should be handled with the help of the URL Routing Module.
Building Web Applications with ASP.NET Core 3 MVC The Model-View-Controller (MVC) is an architectural pattern that separates an application into three main logical components: the model, the view, and the controller. Each of these components are built to handle specific development aspects of an application.
When I finally come to the implementation I get lost in the concepts.
The concepts are very important but also abstract. It's hard to imagine how best to structure your solution until after it's complete (i.e. too late), and no one can really tell you how to structure it because every project is so different.
I would have a domain model [...] and then I would have a view model? [...] wouldn't these be 90% the same?
I believe this is ok. A domain model describes the actual object (usually from a database). A view model describes the information that the view will need to render everything correctly. Both typically contain no logic and only a list of properties. I think it's fine for these to be almost identical. Use Automapper to easily map between models.
Controllers and Views shouldn't have the Domain model?
Most developers prefer this approach, yes. So do I. Views should be given a view model and a controller can simply map between models if needed.
EF makes all its model classes partial. We then extend that same class and add a MetaDataType class to it to make the 'View Model'
It's an interesting approach, but I can't recommend it. Duplicating models is acceptable.
TDD, feels like to have to write everything twice
Yes, it can. The approach that you're taking separates abstraction and implementation a lot. It does make it feel like there is more to write, but it's also simpler to understand. Especially because you communicate with interfaces rather than implementations.
I am appealing [...] for some assistance and guidance
Although you mentioned TDD, I don't recall you mentioning onion architecture. Make sure you read through The Onion Architecture by Jeffrey Palermo.
Watch Put your controllers on a diet by Jimmy Bogard.
You raise some interesting questions and points about the myriad of ways you can architect an ASP.NET MVC application, let alone any application for that matter. I can provide you with my thoughts on the topic and you can use it however you wish.
You said you are worried that in creating both a domain model and view model you will be making the same thing twice, because they will look almost identical. Let me give you a few scenarios that might make you change your mind:
List<Category>
, but you would not want your domain model to have to keep track of metadata for paging, such as total records, page size and page number, right? A CategoryListViewModel
would address this issue.IsAdmin
Boolean value; if you used the domain model to populate the view, then if a bad user figured out that a IsAdmin
property existed and passed IsAdmin=true
in the query string, then the model binder would pick that up and make the account an administrator even though the view never displayed a field to allow for that value to be changed. If you bound to a view model, which did not contain that IsAdmin
property, but rather only the pieces of data relevant to the view, then this vulnerability would not exist.int
), then directly binding your domain model to your view would require the view to parse and format that int
value. Instead a view model could hold the phone number as a string, already properly formatted and just display the value.PagedAccountViewModel
, AddNewAccountViewModel
, UpdateAccountViewModel
, etc.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With