MVC 2 is quiet old and this article was written long years back. We would recommend you to start reading from our fresh Learn MVC 5 step by step series from here: -http://www.codeproject.com/Articles/866143/Learn-MVC-step-by-step-in-days-Day
- So, What’s the agenda?
- Day 1: -Controllers, strong typed views and helper classes
- Day 2: - Unit test, routing and outbound URLS
- Day 3:- Partial views, Data annotations,Razor, Authentication and Authorization
- Day 4:- JSON, JQuery, State management and Asynch controller
- Day 5:- Bundling , Minification , ViewModels,Areas and Exception handling
- Day 6: - Display Modes,MVC OAuth,Model Binders,Layout and Custom view engine
- Lab 18: - MVC bundling and minification
- Understanding Bundling
- Understanding Minification
- Step 1: - Create a MVC project with Empty template
- Step 2: - Create a controller which invokes a view
- Step 3: - Run and see how multiple calls are made.
- Step 4: - Referencing “System.Web.Optimization”
- Step 5: - The bundle config file
- Step 6: - Call the bundle config file from global.asax.cs file
- Step 7: - Render the bundles in the view
- Step 8: - Watch your Bundling and Minification in real
- Lab 19: - MVC View model
- Theory
- What kind of logic view model class will contain?
- Step 1 :- Creating the customer model
- Step 2: - Creating the view model
- Step 3: - Consume view model in the view
- Should VM be composed or inherited.
- Advantages of VM
- Lab 20: - Exception Handling
- Introduction
- Step 1: - Add a controller and action which raises error
- Step 2: - Create an Error view
- Step 3: - Reuse across Actions within same controller (OnException)
- Step 4: - Reuse across any action and any controller (FilterConfig)
- Step 5: - Error handling across project: - Application_Error
- Lab 21: - MVC Area
- What is Area and Why Area?
- How to use Areas?
- Step1: - Add Area using the MVC template.
- Step 2: Start pushing relevant files to relevant areas
- What is the difference Areas vs. Folders?
- What is for the sixth day?
- Are you completely new to MVC?
- Do not miss MVC interview questions with answers
In day 5 we will look in to how to bundling and minification to maximize performance of MVC application. We will also look in to the concept and advantages of view model which is nothing but a bridge between model and the view.
http://www.codeproject.com/Articles/207797/Learn-MVC-Model-view-controller-Step-by-Step-in-7
http://www.codeproject.com/Articles/259560/Learn-MVC-Model-view-controller-Step-by-Step-in-7
http://www.codeproject.com/Articles/375182/Learn-MVC-Model-View-Controller-Step-by-Step-in-4
http://www.codeproject.com/Articles/667841/Learn-MVC-Model-view-controller-Step-by-Step-in-3
http://www.codeproject.com/Articles/724559/Learn-MVC-Model-view-controller-Step-by-Step-in-7
http://www.codeproject.com/Articles/789278/Learn-MVC-Model-view-controller-Step-by-Step-in-d
Both these concepts bundling and minification helps us to increase performance.
Web projects always need CSS and script files.Bundling helps us to combine to multiple javascript and CSS file in to a single entity during runtime thus combining multiplerequests in to a single request which in turn helps to improve performance.
For example consider the below web request to a page. The below request are recorded by using chrome developer tools. This page consumes two JavaScript files “Javascript1.js” and “Javascript2.js”. So when this is page is requested it makes three request calls:-
- One for the “Index” page.
- Two requests for the other two JavaScript files “Javascript1.js” and “Javascript2.js”.
Now if you think a little the above scenario can become worst if we have lot of javascript files(especially JQUERY files) resulting in multiple requests thus decreasing performance.
If we can somehow combine all the JS files in to a single bundle and request them as a single unit that would result in increased performance (See the next figure which has a single request).
Minification reduces the size of script and CSS files by removing blank spaces , comments etc. For example below is a simple javascript code with comments.
var x = 0;
x = x + 1;
x = x * 2;
After implementing minification the javascript code looks something as below. You can see how whitespaces and comments are removed to minimize file size and thus increasing performance as the file size has become smaller and compressed.
var x=0; x=x+1; x=x*2;
So let’s demonstrate a simple example of bundling and minification with MVC 4.0 step by step.
So to understand bundling and minification , let’s go ahead and create a empty MVC project. In that let’s add a “Script” folder and inside”Script” folder , lets add two javascript files as shown in the below figure.
Below is the code for “Javascript1” file.
var x = 0;
x = x + 1;
x = x * 2;
Below is the code for “Javascript2” file.
alert("Hello");
Now let’s go ahead and create a controller which invokes a view called as “MyView” which consumes both the javascript files.
public class SomeController : Controller
{
public ActionResult MyView()
{
return View();
}
}
Below is the ASPX view which consumes both javascript files.
<html>
<script src="../../Scripts/JavaScript1.js"></script>
<script src="../../Scripts/JavaScript2.js"></script>
<head>
</head>
<body>
<div>
This is a view.
</body>
</html>
Now run the MVC application in Google chrome , press CNTRL + SHIFT + I keyboard keys to see the below output. You can see there are three requests: -
- First request is to the view “MyView”.
- The other two requestsfetch “javascript1” and “javascript2” respectively.
Now bundling is all about making those two JavaScript call’s in to one.
Bundling and minification is done by “System.Web.Optimization” namespace. Now this DLL is not a part of .NET or ASP.NET framework. We need to use NUGET to download this DLL. So go to NUGET and search for ASPNET.Web.Optimization.
In case you are new to Nuget and do not know how to use it please see this video for basics
So once you have got the optimization in your package , click on install to get the references in your project.
Now this step depends on which MVC template you have selected. If you have selected the “Basic” template then the “BundleConfig” file is ready made and if you have selected the “Empty” template then you have do lot of work.
Currently we have selected “Empty” template so that we can know things from scratch.
So go ahead and add ‘BundleConfig” class file and create a “RegisterBundles” method as shown in the below code. In the below code the “bundles.add” says that add all the javascript files in the “Scripts” folder in to one bundle called as “Bundles”.
Important note: - Do not forget to import “using System.Web.Optimization;” in the class file or else you will end up with errors.
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/Bundles").Include(
"~/Scripts/*.js"));
BundleTable.EnableOptimizations = true;
}
}
This step is not necessary to be performed by project who have created using “Basic” template. But below goes the steps for people who have created using “Empty” template. Open the global.asax.cs file and in the application start call the “RegisterBundles” method as shown in the below code.
protected void Application_Start()
{
…
…
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
Once the bundling is done we need to remove the “script” tag and call the “Optmization” dll to render the bundle.
<script src="../../Scripts/JavaScript1.js"></script>
<script src="../../Scripts/JavaScript2.js"></script>
Below is the code which will bundle both javascript files in to one unit thus avoiding multiple request call for each file.
<%= System.Web.Optimization.Scripts.Render("~/Bundles") %>
Below is the complete bundling code called inside the MVC view.
<%= System.Web.Optimization.Scripts.Render("~/Bundles") %>
<head runat="server">
<meta name="viewport" content="width=device-width" />
<title>MyView</title>
</head>
<body>
<div>
This is a view.
</body>
</html>
So now that you are all set,it’s time to see the bundling and minification in real. So run google chrome, press CNTRL + SHIFT + I and you can see the magic there is only one call for both the javascript files.
If you click on the preview tab you can see both the javascript files have been unified and…. GUESS , yes minification has also taken place. Remember our original javascript file.
var x = 0;
x = x + 1;
x = x * 2;
You can see in the below output how the comments are removes , white spaces are remove and the size of the file is less and more efficient.
A view model is a simple class which represents data to be displayed on the view.
For example below is a simple customermodel object with “CustomerName” and “Amount” property.
CustomerViewModel obj = new CustomerViewModel();
obj.Customer.CustomerName = "Shiv";
obj.Customer.Amount = 1000;
But when this “Customer” model object is displayed on the MVC view it looks something as shown in the below figure. It has “CustomerName” , “Amount” plus “Customer Buying Level” fields on the view / screen. “Customer buying Level” is a color indication which indicates how aggressive the customer is buying.
“Customer buying level” color depends on the value of the “Amount property. If the amount is greater than 2000 then color is red , if amount is greater than 1500 then color is orange or else the color is yellow.
In other words “Customer buying level” is an extra property which is calculated on the basis of amount.
So the Customer viewmodel class has three properties
- “TxtCustomerName” textbox takes data from “CustomerName” property as it is.
- “TxtAmount” textbox takes data from “Amount” property of model as it is.
- “CustomerBuyingLevelColor” displays color value depending on the “Amount “ value.
Customer Model | Customer ViewModel |
CustomerName | TxtCustomerName |
Amount | TxtAmount |
| CustomerBuyingLevelColor |
So the view model class can have following kind of logics: -
- Color transformation logic: - For example you have a “Grade” property in model and you would like your UI to display “red” color for high level grade, “yellow” color for low level grade and “green” color of ok grade.
- Data format transformation logic: - Your model has a property “Status” with “Married” and “Unmarried” value. In the UI you would like to display it as a checkbox which is checked if “married” and unchecked if “unmarried”.
- Aggregation logic: -You have two differentCustomer and Address model classes and you have view which displays both “Customer” and “Address” data on one go.
- Structure downsizing: - You have “Customer” model with “customerCode” and “CustomerName” and you want to display just “CustomerName”. So you can create a wrapper around model and expose the necessary properties.
Let’s do a small lab to understand MVC view model concept using the below screen which we discussed previously.
I will use a top down approach for creating the above screen: -
- Step 1: - First create the “customer” model.
- Step 2: - Create the view model.
- Step 3: - Consume the view model in the view.
So let’s go ahead and create a “Customer” model with the below properties. Because this is a view model I have avoided the color property in the below class.
public class CustomerModel
{
private string _CustomerName;
public string CustomerName
{
get { return _CustomerName; }
set { _CustomerName = value; }
}
private double _Amount;
public double Amount
{
get { return _Amount; }
set { _Amount = value; }
}
}
The next thing is to create a view model class which will wrap “Customer” model and add UI properties. So let’s create a folder “ViewModels” and in that add a class “CustomerViewModel”.
Below goes the code for “CustomerViewModel” class. Below are some important points to note about the view model class: -
- You can see in the below class how “CustomerViewModel” class wraps “CustomerModel” class.
- Also most important point we have created properties which go with the UI naming convention (TxtName, TxtAmount, CustomerLevelColor etc).
- Now for the most important watch the code for “CustomerLevelColor” property , it displays color depending on the amount of customer sales. A “ViewModel” exists for such kind of gel code / bridge code which connects the model and view.
public class CustomerViewModel
{
private CustomerModel Customer = new CustomerModel();
public string TxtName
{
get { return Customer.CustomerName; }
set { Customer.CustomerName = value; }
}
public string TxtAmount
{
get { return Customer.Amount.ToString(); }
set { Customer.Amount = Convert.ToDouble(value); }
}
public string CustomerLevelColor
{
get
{
if (Customer.Amount > 2000)
{
return "red";
}
else if (Customer.Amount > 1500)
{
return "orange";
}
else
{
return "yellow";
}
}
}
}
The next step is to create a strongly typed MVC view where we can consume the view model class. In case you are not aware of MVC strongly typed views please see Learn MVC Day 1, Lab 4
If you see the view it is now decorated or you can say binded with view model class. The most important thing to watch is your view is CLEAN. It does not have decision making code for color coding. Those gel codes have gone inside the view model class. This is what makes VIEW MODEL a very essential component of MVC.
This view can be invoked from a controller which passes some dummy data as shown in the below code.
public class CustomerController : Controller
{
public ActionResult DisplayCustomer()
{
CustomerViewModel obj = new CustomerViewModel();
obj.Customer.CustomerName = "Shiv";
obj.Customer.Amount = 1000;
return View(obj);
}
}
Lot of architects make mistakes of creating a view model class by inheriting. If you see the above view model class it is created by composition and not inheritance.
So why does composition make more sense?. If you visualize we never say “This Screen is a child of Business objects”, that would be a weird statement.
We always say “This screen uses those models”. So it’s very clear it’s a using relationship and not an IS A (child parent) relationship.
Some of the scenarios where inheritance will fail are: -
- When you DO NOT want some properties from the model in your view
- When you have a view which uses multiple models.
So do not get lured with the thought of creating a view model by inheriting from a model you can end up in to a LISKOV issue(read about SOLID LISOV from here)
It looks like a duck, quacks like a duck but it is not a duck. It looks like a model has properties like a model but it is not exactly a model.
Image from http://tomdalling.com
- Reusability: - Now that my gel code has come in to a class. I can create the object of that class in any other UI technology (WPF, Windows etc) easily.
- Testing: - We do not need manual testers to test the UI look and feel now. Because our UI code has moved in to a class library (least denominator) we can create an object of that class and do unit testing. Below is a simple unit test code which demonstrates unit testing of UI look and feel logic. You can see how the color testing is done automatically rather than some manual tester testing it manually.
[TestMethod]
publicvoid TestCustomerLevelColor()
{
CustomerViewModel obj = new CustomerViewModel();
obj.TxtName = "Shiv";
obj.TxtAmount = "1000";
Assert.AreEqual("Red",obj.CustomerLevelColor);
}
When it comes to exception handling Try…Catch block is the favorite choice among .NET developers. For example in the below code we have wrapped the action code in a TRY CATCH block and if there are exceptions we are invoking an “Error” view in the catch block.
public ActionResult TestMethod()
{
try
{
return View();
}
catch (Exception e)
{
return View("Error");
}
}
The big problem with the above code is REUSABILITY of exception handling code. MVC provides you to reuse exception handling code at three levels: -
- Across Actions within same controller: - You can use the “OnException” event where you can write logic which can be reused across “Action” in the same controller.
- Across any Controller and Actions: - In MVC we can use “FilterConfig” to create an attribute which can be applied to any controller and any action.
- Across project level: - UsingApplication_Error handler in Global.asax. So when exception is raised from any part of the MVC project it will be routed to this central error handler.
Let’s go step by step to demonstrate all the above 3 ways of handling errors in MVC.
So the first thing is to add a simple controller and action which raises some kind of exception. In the below code you can see we have added a “TestingController” with an action “TestMethod” where we have raised divide by zero exception.
public class TestingController : Controller
{
public ActionResult TestMethod()
{
int x = 0;
x /= x;
return View();
}
}
So if you execute the above action you would end up with error as shown in the below figure.
Now once the error is caught by any of the three above methods we would like throw some error page for display purpose. So let’s create a simple view by the name “Error” as shown in the figure below.
So now that we have an error and also an error view it’s time to do demo’s using all the three ways. So first let’s start with “OnException” i.e. exception code reusability across actions but in the SAME CONTROLLER.
To implement exception go to the “TestingController” and override the “OnException” method as shown in the below code. This method executes when any error occurs in any action of the “TestingController”.
The viewname i.e. “Error” is set in the result property of “filterContext” object as shown in the below code.
protected override void OnException(ExceptionContext filterContext)
{
Exception e = filterContext.Exception;
filterContext.Result = new ViewResult()
{
ViewName = "Error"
};
}
Now if you try to invoke the “TestMethod” from the “TestController” you should see the “Error” view as shown in the below figure.
The “OnException” method helps to provide error handling for a specific controller but what if we want to reuse the exception logic across any controller and any action. That’s where we have “FilterConfig” way which is the next thing.
In Web.Config simply enable custom error as follows.
<customErrors mode="On">
In App_Start folder open FilterConfig.cs and make sure that HandleErrorAttribute is added to GlobalFilterCollection.
HandleErrorAttribute at global level confirms that exceptions raised by each and every action in all the controllers will be handled.
Note: If you are curious about how to make “HandleErrorAttribute” controller specific or action specific then click here and learn in detail about exception handling in ASP.NET MVC.
If you execute the controller you should get the same error page as shown in step 3.
To handle error across MVC project we can use listed to “Application_Error” event in global.asax file and write logic of error handling in the same.
That’s it. A simple demonstration of Exception handling in MVC using all the 3 ways.
Note: We have uploaded a supporting article for our step by step series. It explains in detail exception handling in ASP.NET MVC. If you are willing to read more about it, click here.
In ASP.NET MVC we have a concept of Areas using which we can break our system into modules and organize our project in a better manner.
Assume we have a system which consists of two modules Customer and Order Processing. Normally when we create Asp.Net MVC Project our structure consist of 3 folders – Controllers, Model and Views. So Project structure will be something like this.
| As you can see nothing is organized. When it comes to code management it will be very difficult.
Side image is the structure of the project when we had 2 modules, imagine a situation when we have hundreds of modules in single system.
|
Examples for Areas in real world
| Country is divided into states to make development and management easy.
|
Just like real world we use the concept of area in Asp.Net MVC to break single system into modules. One area represents one module by means of logical grouping of controllers, Models and Views.
To add area right click your project and say Add>>Area as shown in the below figure.
Put all your related files into respected areas as shown in the below figure. In the below figure you can see I have created two areas “Customer” and “Order”. And each of these areas have their own View , controller and models.
Note: - Area is logical grouping not physical, so no separate dlls will be created for every area.
One can ask a question why we should use Areas for breaking system into modules when we can just use folders. In simple words, answer for this question is “To avoid of huge manual work”
In order to achieve same functionality using simple folder you have to do following things.
-
- a. One folder for every module.
- b. Three Folder inside every module folder naming Controller, Models and Views
- c. One Web.Configfile for every module (to store settings related to that module).
- Create module structure manually.
- Create one custom route for every module Controllers.
- Create Custom View Engine for every module which will search for the view in customized locations instead of predefined locations (Views/{Controllers} or Views/Shared )
Default View Search
Customized View Search
Final note, you can watch my C# and MVC training videos on various sections like WCF, Silver light, LINQ, WPF, Design patterns, Entity framework etc. By any chance do not miss my .NET/C# interview questions and answers book from www.questpond.com.
For technical training related to various topics including ASP.NET, Design Patterns, WCF, MVC, BI, WPF contact SukeshMarla@gmail.com or visit www.sukesh-marla.com
In case you are completely a fresher I will suggest to start with the below 4 videos which are 10 minutes approximately so that you can come to MVC quickly.
Lab 1: A simple Hello World ASP.NET MVC application
Lab 2: In this lab we will see how we can share data between the controller and the view using view data
Lab 3: In this lab we will create a simple customer model, flourish it with some data, and display it in a view
Lab 4: In this lab we will create a simple customer data entry screen with some validation on the view
Start with MVC 5
In case you want to start with MVC 5 start with the below video Learn MVC 5 in 2 days.
Every lab I advance in this 7 days series I am also updating a separate article which discusses about important MVC interview questions which are asked during interviews. Till now I have collected 60 important questions with precise answers you can have a look at the same from here
For further reading do watch the below interview preparation videos and step by step video series.