Introduction
In the first part of this tutorial series we got a glimpse of MVC. In this part we'll focus on the practical implementation of the MVC Pattern. I don't need to explain the theory of MVC since we have already covered that in the previous part of the article.
Our Roadmap
Our agenda is as follows:
Topics to be covered
The following are the topics to be covered here:
- Creating a MVC project from scratch.
- Adding Controllers, Views and Models.
- Creating a sample database and use LINQ to SQL for communication.
- Perform CRUD operations in a MVC application using LINQ to SQL.
- Understand ViewData, ViewBag and TempData.
- Model Validation by System.Component.DataAnnotation.
1. Creating MVC project
Step 1: Open Visual Studio 2010/201. ,I am using 2010. Go to "File" -> "New" -> "Project..." and select "ASP.Net MVC3 Web Application", as in the following:
Name the application as LearningMVC.
Step 2: A project template selection window will be opened, select "Empty" in that. Select "View Engine as Razor" and press "OK".
Step 3: Now our solution is ready with an empty MVC application.
We can clearly see that the solution contains some extra folders in comparison to a traditional ASP.Net web application.
We have a Models, Views and Controllers folder and a Shared folder in the Views folder. The folders, as the name implies, hold the respective MVC players model-view-controllers, the shared folder in Views contains the _Layout.cshtml, that can be used as the master page for the views that we create.
We see the global.asax file that contains a default routing table, that defines the route to be followed when the request is received, it says that when the request is received by the Home controller, the Index action of that Home Controller must be called.
Actions are the methods defined in Controllers that can be called defining a route. The Action methods can also contain parameters; in the figure mentioned above, it says that the Home controller has an Action Index that contains an optional parameter id.
When we run our application, we get something as in the following,
It says that the resource that we are looking for cannot be found. The request by default follows the default route as mentioned in global.asax, in other words go to the controller Home and invoke the method Index. Since we don't have any of these yet, the browser shows this error.
Never mind, let's make the browser happy.
2. Adding Controllers, View and Models
Step 1: Create a My Controller by right-clicking on the Controllers folder and add a controller named My, add the controller with empty read/write actions, it will give us a class with a few default generated actions.
Note that there are two Actions for every Action name, one is for Get, in other words when a view loads for the first time, and second one is for POST, when the View is submitted with some data.
Change global.asax RegisterRoutes method to be as:
- public static void RegisterRoutes(RouteCollection routes)
- {
- routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
- routes.MapRoute(
- "Default",
- "{controller}/{action}/{id}",
- new { controller = "My", action = "Index", id = UrlParameter.Optional }
- );
- }
Note: we have changed the name of controller as per our added controller.
Step 2: We will see that we have Actions but they return a View, so we need to create Views for them. But before this we'll create a Model named User for our Views. Right-click on the Model folder and add a class named User.
Add the following properties to the User class:
Now our model is created and we can create Views bound to this particular model.
Step 3: Go to the controller, right-click on the empty Actions of the controller and from the context menu select "AddView" on the top. By default the View name is the same as the Actions name.
For example, for Details:
Select Viewname as Details,Model class as User, and Scaffold Template as Details.This template specifies the role of the View, that this view will show the details of the User (entity). Click add.
Likewise perform this operation for all the Actions, and create Views.
Note that Views are automatically added to the Views folder under My folder (auto created as per the Controller's name). This is to maintain a particular structure for MVC, so that we don't need to use overhead to maintain it.
Now we have a controller as well as Views, so if we run the application we get:
In other words, the Index Action of our My controller is fired that returned Index View.
3. Creating sample database and use LINQ to SQL for communication
Our MVC application is ready, but rather than displaying dummy data, I will run the application talking to a data base so that we can cover wider aspects of the application.
Step 1: Create a database. The script is given in the attachment, just execute it over SQL Server 2005/2008.
Step 2: Add a new item to the solution and select LINQ to SQL class, call it MyDB.dbml.
Our solution looks like:
Step 3: Open Server Explorer of Visual Studio, open a connection by providing the server name and existing database name in the Server Explorer Open Connection window.
Click OK. Our solution looks like:
Step 4: Drag the User table to the dbml designer window, we get the table in a class diagram format in the designer window.
When we open MyDB.designer.cs, we get the MyDBDataContext class. This class holds database user table information in the form of classes and properties. For every column of the table, properties are created in the class, and we can use these properties to get/set values from/in database.
4. Perform CRUD operations in MVC application using LINQ to SQL
We now have a database, a context class to communicate with the database and a MVC application to perform CRUD operations in the database using the context class.
Step 1 Read
-
Go to Index Action, make an instance of the context class. We can get all the table and column names in that context's instance.
-
Make a query to display all the records on the Index view.
-
Populate the User Model that we created earlier, and it to the Index view (Index View will be of a List type Item template).
When we run the application, we get an empty list, in other words we don't have records in the database.
Step 2 Create
-
First write code for creating a user, for the first time for the Get Action of create, always an empty view will be returned.
-
When we post some data on the click of the submit of Create, we need to make a data entry in the table for creating a new user.
-
When the form is posted, it fires a Post Action of Create with the already bound User model properties to view fields, we'll retrieve these model properties and make an instance of the context class to populate the context User and submit to the database.
-
Redirect action to Index, and now a record will be shown on the Index View. We successfully created a user.
-
In the database:
Step 3 Update
Step 4 Delete
Now we are smart enough to perform update and delete by ourself, this I leave for the reader's understanding capabilities, the following are the screens for Update and Delete.
Edit Code:
Get:
Post:
Get Action View of Edit:
Edited few fields:
Update reflected in database:
Code to show details of a particular user :
Details Screen:
Note: a Details Action does not have a POST, since nothing is posted to the controller.
Likewise for Delete:
Screen:
Back to List after Delete:
In database after delete:
Yes, all the CRUD operations are done. Now we understand MVC.
There are a few basic scenarios that I want to discuss before finishing with the First Part, like ing data from the Controller to Views, between Controllers and so on and about Model validation.
5. Understand ViewData, ViewBag and TempData
I wanted to use this topic since there is so much confusion regarding these three players.
MVC provides us ViewData, VieBag and TempData for ing data from a controller and view and in future requests as well. ViewData and ViewBag are similar to some extent but TempData performs additional roles. Let's get the key points of these three players:
ViewBag & ViewData
I have written sample test code in the same application that we are following from the beginning,
-
Populate ViewData and ViewBag on Index action of My Controller.
-
Code in View to fetch ViewData/ViewBag.
-
When run the application, we get one screen.
The following are the roles and similarities between ViewData and ViewBag:
-
Maintains data when moving from controller to view.
-
es data from controller to respective view.
-
Their value becomes null when any redirection occurs , because their role is to provide a way to communicate between controllers and views. It's a communication mechanism within the server call.
Differences between ViewData and ViewBag (taken from a blog)
-
ViewData is a dictionary of objects that is derived from the ViewDataDictionary class and accessible using strings as keys.
-
ViewBag is a dynamic property that takes advantage of the new dynamic features in C# 4.0.
-
ViewData requires typecasting for complex data types and check for null values to avoid errors.
-
ViewBag doesn't require typecasting for complex data types.
TempData
TempData is a dictionary derived from the TempDataDictionary class and stored in a short-lived session. It is a string key and object value.
It maintains the information for the time of an HTTP Request. This mean only from one page to another. It helps to maintain data when we move from one controller to another controller or from one action to another action. In other words, when we redirect, "Tempdata" helps to maintain data between those redirects. It internally uses session variables. Temp data is used during the current and subsequent request only, in other words it is used when we are sure that the next request will be redirecting to the next view. It requires typecasting for complex data types and checks for null values to avoid errors. Generally it is used to store only one-time messages, like error messages and validation messages.
I added a TempData in Edit Action as:
- [HttpPost]
- public ActionResult Edit(int? id, User userDetails)
- {
- TempData["TempData Name"] = "Akhil";
- ....
And when View redirected to Index Action:
In other words I get the TempData value across Actions.
6. Model Validation
We can have many methods for implementing validation in our Web Application Client Side, Server Side and so on.
But MVC provides us a feature with which we can annotate our Model for validation by writing just one or two lines of code.
Go to the Model class User.cs, add [Required(ErrorMessage = "FirstName is required")] on the top of FirstName property as in:
- public int UserId { get; set; }
- [Required(ErrorMessage = "FirstName is required")]
- public string FirstName { get; set; }
- public string LastName { get; set; }
Now when we run the application, and try to Edit/Create a user without specifying FirstName, we get:
Surprised? Yes the model validates itself with these annotations, there are many more validators like the required field one that I used.
Do not forget to include "using System.ComponentModel.DataAnnotations;" for the namespace when using Model Validation. This is the namespace that holds classes used for validation.
Conclusion
Now that we understand what MVC is, how to implement it, its advantages and, CRUD operations in MVC. Future parts of the tutorial will be focusing on more advanced topics, like EntityFramework, Repository Pattern, Unit Of Work Pattern and Code First Approach.
Read more:
Other Series
My other series of articles:
For more informative articles visit my Blog.