This post showcases an intermediate .NET MVC application leveraging EF Core.
It is divided in three sections for your viewing pleasure:
Application Overview (with UI Screenshots)
Application Structure (with Solution Explorer Screenshots)
Application Implementation Discussion (with various illustrations from across the application).
The application's full code may be found here
Sigma is an MVC application using EFCore serving as a marketplace for courses
This is an ongoing project as of June 2023 This is a more involved MVC EF Core application built from scratch.
This course marketplace consists of a listing of courses with their respective prices (home controller - index view), the posibility of viewing details about the course (home controller - details view) . It implements .NET Scaffolded Identity ( identity area - pages) which allows users to register with their personal information ( identity area - pages - account - register view) as well as log in once they are registered ( identity area - pages - account - login).
Customers can then view a shopping cart count on the main screen (views - shared - layout && views - shared - components - shopping cart - default view) and may add courses they want to purchase (from home controller - details view) and view them in their…
- Application Overview
- Application Structure
- Application Development Process a. Foreword b. Basic Setup c. Initial Development d. Secondary Development Phase e. Limitations
- Closing Words
Although this is a functioning project (not deployed, but code works against a local SQL Server database), it is not intended for commercial use so various integrations such as payments with a payment portal have not been included.
The intended use of this application is educational. Its best use is as an overview of an intermediate .NET MVC EF Core Solution.
It is a great summary snapshot of an intermediate MVC application.
When you start the application - which by the way is a Course Marketplace - you are greeted with the home screen, which displays the available courses, provided you have the right data in the database and the images loaded up in the wwwroot folder.
Upon reviewing the courses (referred to as products in the application), you can click on the details button to learn more:
From this screen, you now have the possibility of adding this course to your cart. But wait! Before you can access the Shopping Cart screen, you'll first need to login! You can also login by clicking on the link in the navbar.
Through the navbar also, you can access the Register section, in case you need to register before logging in.
You may also access the Register page when you are logged in as an administrator, under the Manage Content section, so you may add users at will.
Once you are logged in as an Admin or a Customer (you can choose how to do so when you register), you can finally access the Shopping Cart screen, either through the button in the Details view (see above), or by clicking on the Shopping Cart icon in the navbar.
Inside the cart page, you may view the Order Summary by clicking on the Summary button.
Only as an Admin, you may access the Product (Courses) Management Screen to add new courses, edit existing ones or delete unwanted ones, thus removing them from the Home page.
So that's an overview of the Application UI. Note that you cannot proceed to checkout and pay yet because payment portal integration has not been implemented. Yet, you'd be surprised at the complexity behind these 7 simple screens.
Let's jump now to review the Structure, or more humbly, the Solution Explorer Folder Setup and Organization of the Projects that make up this solution.
Before jumping into an overview of the development process for this application, let's take a brief moment to look at the final setup for the Solution.
Here is a general overview of the project structure.
There are four main sections and two of them have corresponding unit test projects associated with them.
The first section is the Data Access Layer or "Data Access". This is where the ApplicationDbContext lives, to manage EF connection to the database (the connection string lives in appsettings.json in the SigmaWeb Project).
The Data Project contains Repository and Unit of Work Patterns implementation to manage access to the models via individual repositories.
These will be useful in the controllers when we are making calls to Add or Get products from the database.
In essence the Repositories inherit from a common Repository file where all main CRUD operations are defined. Operations that are more specific to a given model are defined in a more specific repository.
Access to the repositories happens through the UnitOfWork class. A UnitOfWork object is then injected in the constructor of various controllers.
The Migrations folder holds the migrations for translating our Models into the database tables, again managed via ApplicationDbContext
The Models project holds the Models, defined in this project with data annotations as a more simple alternative to EF Core's fluent API.
Fluent API statements are also defined although commented as we will see later to showcase the alternative way of defining tables.
The Models project also holds ViewModels which are Models that are not persisted to the database, and which in turn hold other models of other items such as Lists, all of which are used to interface with views.
The Utilities project is also there but we've omitted it because it only holds a static details file and a class to manage an email service, which is disabled in our application via comments, but which serves to send emails when users perform certain actions.
Let's see the Models Project:
And finally we have the heart of the Solution: SigmaWeb, where the Controllers and corresponding Views reside (inside the Customer and Admin folders), nested within Area folders. Scaffolded Identity items, including code files, models and views reside here inside the Identity Area.
The ViewComponent folder holds a ViewComponent for the ShoppingCart counter and its code behind file.
SigmaWeb is also the main entry point into our application, the pipeline and registered services are defined in Program.cs. Finally we have appsettings.json for managing connection strings to the database and third party services, and some other items like the _Layout master page and other Shared View items like partial views.
Let's now move on to application development!
A thorough discussion of the application development process would take several articles, so instead, what I'll do here is go through an overview of the steps that I had to take to develop the application.
If you are developing an intermediate application like this on MVC, this should serve as a guide on where to begin, and then reading the code in the repository I provided, with the assistance of ChatGPT and/or Google, you should be able to build your own similar application.
I first began with paper and pencil diagramming the different views in the application. I drew boxes, buttons and fields. This gave me a good starting idea of what the models would look like.
Of course, and this is true for the views the models or any other component you develop: Your original drafts will need to be modified several times as you build the application and/or discover new requirements.
Still you have to start somewhere.
With a little of knowledge of bootstrap I diagrammed the views that I had previously drafted on paper and I saved them for later reference. This included the _Layout view master page.
After that I created the folder structure in the previous section and installed the NuGet Packages I knew I would need. Again, this doesn't mean you won't need to install more packages as you go, but you have to start somewhere.
Then I started coding the initial Program.cs file and the AppSettings.json connection string to the database.
After that I designed the ApplicationDbContext and the Models.
Finally, I created the Interfaces and Repositories for the Models following the Unit of Work and Repository patterns. Once the Models, the Unit of Work, Repositories and ApplicationDbContext were done, I performed the first migrations to the database.
After setting things up, I started coding the Home Controller with its views. Here I returned to the view snippets I had developed earlier and created the views on their corresponding controller action.
Next, as I could see I could not proceed further developing controller logic without authenticated and authorized users, I proceeded to scaffold Identity.
Once done I did the necessary touches on the Login and Register views and models inside the Identity Folder.
I implemented the Email Sender functionality both in the Identity area and within the Utilities Project and tested it.
I next added Identity related code to the controllers and implemented sessions.
I created the Shopping Cart View Component, coded the Cart Controller and its actions and views. Where necessary I developed View Models.
Now that the application was well underway I proceeded with development. I coded the Product Controller and its Actions and View.
I made additional coding distinctions in the Identity Folder between registering as Admins or Customers so I could display different functionality.
I coded the cart controller and then implemented Unit Tests for several (not all) of the methods and scenarios.
Unit Testing was heavy work that required extensive Mocking, especially in the Controllers. Although the Controllers are relatively light weight, there's a lot of dependencies to take care of. ChatGPT did most of the heavy lifting and I had to edit the tests extensively due to their complexity.
I then added a commented Fluent API Implementation to demonstrate an alternative to the Model's data annotations.
This is intended as educational practice, so the project is not fully integrated such that functionality regarding integration such as payment portals was not developed. Email integration was developed as noted previously, but commented.
For this reason if you pull the repo from its source and you interface with your database you will be able to see the project working, but you won't be able to actually purchase products (courses).
Altogether this is an intermediate N-Tier Solution leveraging .NET Core and EF Core features. It is functional, and however incomplete, it should nonetheless serve to educate you on the basics of the MVC Pattern, conventions and such. In addition, it provides several Unit Tests for you to see how to test the logic of any given Controller on any such project.
It is a great opportunity to see a .NET Project well underway. It will serve as review for those who have already developed applications in .NET and to those who have not implemented the Repository and Unit of Work Patterns, it should be of great help.