Sei sulla pagina 1di 230

http://www.codeproject.

com/Articles/866143/Learn-MVC-step-by-step-in-days-Day

Learn MVC Project in 7 days – Day 1


Contents

 Introduction

 What do we need for doing Asp.Net MVC ?

 ASP.NET vs MVC vs WebForms

 Why ASP.NET Web Forms?

 Problems with Asp.Net Web Forms

 What’s the solution ?

 How Microsoft Asp.Net MVC tackles problems in Web Forms?

 Understand Controller in Asp.Net MVC?

 Understand Views in Asp.Net MVC

 Lab 1 – Demonstrating Controller with a simple hello world

 Q & A session around Lab 1

 Lab 2 – Demonstrating Views

 Q and A session around Lab 2

 What is for Day 2 ?

 Learn MVC in 2 days (16 hours)

Introduction

As the title promises “Learn MVC in 7 days” , so this article will have 7 articles i.e. 1 article for
each day. So start reading this tutorial series with a nice Monday and become a MVC guy till the
end of the week.

Day 1 is kind of a warm up. In this first day we will understand Why Asp.Net MVC over
Webforms ? , Issues with Webforms and we will do two Lab’s one around controller and the
around views.
After each one of these lab’s we will run through a small Q and A session where we will discuss
concepts of the lab. So the structure of this is article is Lab’s and then Q and A.

In case for any Lab you have questions which are not answered in the Q and A please feel free to
put the same in the comment box below. We will definitely answer them and if we find those
question’s recurring we will include the same in the article as well so that rest of the community
benefit from the same.

So we just need your 7 day’s and rest this article assures you become a ASP.NET MVC
developer.

What do we need for doing Asp.Net MVC ?

We just need Visual Studio and the good news is that visual studio is completely free. You can
download Visual studio community edition from http://www.visualstudio.com/ , no expiry , no
license issues and you do not need deep pockets.

ASP.NET vs MVC vs WebForms

“You are reading this article because you know ASP.NET and you want to upgrade yourself to
MVC.”

Sorry for the trouble, can you please read the above statement again and if you think it’s right
then this section is a must read for you.

Lot of ASP.NET developers who start MVC for the first time think that MVC is different new ,
fresh from ASP.NET. But the truth is ASP.NET is a framework for creating web application
while MVC is a great architecture to organize and arrange our code in a better way. So rather
than MVC you can say ASP.NET MVC.

Ok so if the new thing is ASP.NET MVC what is the old thing called as,it’s “ASP.NET
Webforms”.

Let me correct your vocabulary:-

“You are reading this article because you know ASP.NET Webforms and you want to upgrade
yourself to ASP.NET MVC.”

So now that your vocabulary is corrected welcome to the world of ASP.NET MVC and let’s start
this tutorial.

Why ASP.NET Web Forms?

ASP.NET Webforms has served and successfully delivered web application for past 12 years.Let
us try to understand the secret of what made Webform’s so popular and successful.

If you see the success of Microsoft programming languages right from the days of VB (visual
basic) it is due to RAD(Rapid application development)and visual programming approach.Visual
programming was so much preached and successful in Microsoft that literally they named their
IDE’s as “Visual studio”.

By using visual studio ,developers where able to drag drop UI elements on a designer area and at
the backend , visual studio generates C# or VB.NET code for those elements. These codes where
termed as “Behind Code” or “Code Behind”. In this code behind Developers can go and write
logic to manipulate the UI elements.

So the visual RAD architecture of Microsoft has two things one is the UI and the other is the
code behind. So for ASP.NET Web forms you have ASPX and ASPX.CS ,for WPF you have
XAML / XAML.CS and so on.
Problems with Asp.Net Web Forms

So when ASP.NET Webform was so successful, why Microsoft thought of creating ASP.NET
MVC.The main problem with ASP.NET Webform is performance, performance and
performance. In web application there are two aspects which define performance:-

1. Response time: - How fast the server responds to request?.

2. Bandwidth consumption: - How much data is sent ?.

Response time issues

Let us try to understand why response time is slower when it comes to ASP.NET Webforms. We
did a small load testing experiment of Webform vs Asp.Net MVC and we found Asp.Net MVC
to be twice faster.

Read more on how this test was done from here

Let us try to understand why ASP.NET MVC was better in performance in the above load
test.Consider the below simple UI code and Code behind for that UI.

Assume the ASPX code has the below simple text box.

Hide Copy Code


<asp:TextBox ID="TextBox1" runat="server">

In the code behind you have written some logic which manipulates the text box values and the
back ground color.

Hide Copy Code


protected void Page_Load(object sender, EventArgs e)
{
TextBox1.Text = "Make it simple";
TextBox1.BackColor = Color.Aqua;
}

When you run the above program below is the HTML output.
If you see the HTML output by doing view source it looks something as shown below.

Hide Copy Code


<input name="TextBox1" type="text" value="Make it simple" id="TextBox1"
style="background-color:Aqua;" />

Now stop reading for a moment, close your eyes and think. Try to get answers to the below
questions:-

1. Is this a efficient way of generating HTML?. Do we really need to make those long server trips to
get those simple HTML on the browser ?.

2. Can’t the developer write HTML straight forward , Is it so tough?

If you see for every request there is a conversion logic which runs and converts the server
controls to HTML output.This conversion get’s worse and heavy when we have grids, tree view
controls etc where the HTML outputs are complicated HTML tables. Due to this unnecessary
conversion the response time is less.

Solution for this problem: - “GET RID of CODE BEHIND” ,fold your sleeves and work with
pure HTML.

Bandwidth consumption

Viewstate has been a very dear and near friend of ASP.NET developers for past 10 years because
it automatically saves states between post backs and reduces our development time. But this
reduction in development time comes at a huge cost ,viewstate increases the page size
considerably. In this load test we found viewstate increases the page size twice as compared to
Asp.Net MVC.
Below is the plot of the content length emitted from Webform and Asp.Net MVC.

The size increase is because of extra bytes generated from viewstate , below is the snapshot of a
viewstate. Lot of people can argue that viewstate can be disabled but then we all know how
developers are , if there is option given they would definitely try that out.

Solution for this problem: - “GET RID of SERVER CONTROLS”.

Note: -The rest of the three points down below are browny issues which have cropped up due to
presence of code behind and server controls. But the main thing is always performance.

HTML customization

Now because we are salves of the code behind and ASP.NET web server controls, we have “NO
IDEA” what kind of HTML can come out and how efficient they are. For example see the below
ASPX code, can you guess what kind of HTML it will generate.

Hide Copy Code


<asp:Label ID="Label1" runat="server" Text="I am label">
<asp:Literal ID="Literal1" runat="server" Text="I am a literal">
<asp:Panel ID="Panel1" runat="server">I am a panel
Will Label generate DIV tag or SPAN tag ?. If you run the above code below are the respective
generated HTML. Label generates a SPAN , Literal generates simple text , Panel generates DIV
tag and so on.

Hide Copy Code


<span id="Label1">I am label</span>
I am a literal
I am a panel

So rather than generating HTML using server controls how about writing HTML directly and
taking complete control of HTML.

So the solution for this problem is “DO NOT USE SERVER CONTROLS” and work with direct
HTML.

The other great benefit of working directly with HTML is that your web designers can work very
closely with the developer team. They can take the HTML code put in their favourite designer
tool like dream weaver , front page etc and design independently . If we have server controls
these designer tools do not identify them easily.

Reusability of code behind class

If you watch any professional ASP.NET Webform project you will notice that code behind class
is where you have huge amount of code and the code is really complicated.Now this code behind
page class inherits from “System.Web.UI.Page” class. This class is not a normal class which can
be reused and instantiated anywhere. In other words you can never do something as shown below
for a Webform class:-

Hide Copy Code


WebForm1 obj = new WebForm1();
obj.Button1_Click();

Because the “WebForm” class cannot instantiate with out “request” and “response” object. If you
have ever seen the “ButtonClick” events of “WebForm” they are as shown in the code below.
From the code you can know how difficult it is to instantiate the same.

Hide Copy Code


protected void Button1_Click(object sender, EventArgs e)
{
// The logic which you want to reuse and invoke
}

Solution for this problem: - “GET RID of SERVER CONTROLS and CODE BEHIND”.

Unit Testing

As said in the previous section you cannot instantiate behind code straight forward it’s very
difficult to do unit testing or I will say automation testing on the code behind. Someone has to
manually run the application and do the testing.
What’s the solution ?

If we read the four issues mentioned in the previous section with ASP.NET Webforms the main
culprit are two people “Code Behind” and “Server controls”. Below is root cause diagram I have
drawn. In this I started with problems , what is the cause for it and the solution for the same. The
complete diagram zeroes on two things “Code Behind” and “Server controls”.

The solution is we need to move the code behind to a separate simple class library and get rid of
ASP.NET Server controls and write simple HTML.

In short the solution should look something as shown in the below image.

How Microsoft Asp.Net MVC tackles problems in Web Forms?

As said the code behind and server controls are the root cause problem. So if you look at the
current WebForm architecture which developers are using it’s mostly 3 layer architecture. This
three layer architecture comprises of UI which has ASPX and the CS code behind.

This UI talk’s with .NET classes which you can term as middle layer , business logic etc and the
middle layer talks with data access layer.
So Asp.Net MVC comprises of three sections Model , View and Controller. The code behind
logic goes in to the controller. View is your ASPX i.e. pure HTML and your Model is your
middle layer. You can see in the above diagram how those layers fit in.

So if you see there are two major changes VIEW becoming simple HTML and code behind
moving to simple .NET classes termed as controller.

In Asp.Net MVC request flow in general moves as follows:-

Step 1:- The first hit comes to the controller.

Step 2:- Depending on the action controller creates the object of the model. Model in turn calls
the data access layer which fetches data in the model.

Step 3:- This data filled model is then passed to the view for display purpose.

Now that we have understood the different components of Asp.Net MVC let’s go in depth in to
each one of these components , let us start doing some lab’s. Let us first start with controllers as
they are the most important and central part of the MVC architecture.

Understand Controller in Asp.Net MVC?

In order to understand Controller first we need to understand this term User interaction logic.
What is User Interaction logic??

Scenario 1

Did you ever gave a thought what happen’s, when end user hits a URL on a browser.

Browser sends request to server and server sends a response.

By means of such request, client is trying to interact with server. Server is able to respond back
because some logic is written at server end to fulfil this request.

Some logic??, So what exactly can be this logic ?.

Logic which will handle the user requests and user’s interaction with server. In short User
Interaction Logic

Scenario 2

It also possible that response sent by Server is an HTML response. HTML response which can
consist of couple of input controls and a submit button.

What will happen when “Save Customer” button is clicked?


If your answer is “Some event handler will handle the button click”, then sorry .

“In reality in web programming there is no concept of event’s. In case of Asp.net Web Forms
Microsoft wrote some code on behalf of us and brought us the feeling of event driven
programming. It’s just an abstraction or the right word would illusion.”

When button is clicked a simple HTTP request is sent to the server. This time the difference is,
values in the “Customer Name”, “Address” and “Age” will be sent along with request. (In
technical terms “values are posted to the server”). Ultimately, if it’s a request then there must be
a logic written in the server so that server can send back the response. In short there must be
some user interaction logic written on the server.

In Asp.Net MVC, the last letter C that is Controller is the one who will handle the user
interaction Logic.

Lab 1 – Demonstrating Controller with a simple MVC hello world

Step 1 – Create Asp.Net MVC 5 Project

Step 1.1 Open Visual studio 2013(or higher). Click on File>>New>>Project.

Step 1.2 Select Web Application. Put Name. Put Location and say ok.
Step 1.3 Select MVC template

Step 1.4 Click on Change Authentication. Select “No Authentication” from “Change
Authentication” dialog box and click ok.
Step 1.5. Click ok.

Step 2 – Create Controller

Step 2.1. In the solution explorer, right click the controller folder and select Add>>Controller

Step 2.2. Select “MVC 5 Controller – Empty” and click Add


Step 2.3.Put controller name as “TestController” and click Add.

One very important point to note at this step is do not delete the word controller. For now you
can think it’s like a reserved keyword.

Step 3. Create Action Method

Open newly created TestController class. You will find a method inside it called “Index”.
Remove that method and add new public method called “GetString” as follows.

Hide Copy Code


public class TestController : Controller
{
public string GetString()
{
return "Hello World is old now. It&rsquo;s time for wassup bro ;)";
}
}

Step 4. Execute and Test

Press F5. In the address bar put “ControllerName/ActionName” as follows. Please note do not
type the word “Controller” just type “Test”.
Q & A session around Lab 1
What is the relationship between TestController and Test?

TestController is the class name whereas Test is the controller name.Please note, when you type
the controller name on the URL it should be without the word controller.

Asp.Net MVC follows Convention based approach. It strictly look’s into the conventions we
used.

In Asp.Net MVC two things are very important.

1. How we name something?

2. Where we keep something?

What is Action Method?

Action method is simply a public method inside controller which accepts user’s request and
returns some response. In above example, action method “GetString” is returning a string
response type.

Note: In Asp.Net Web Forms default return response is always HTML. In case we want to return
something other than HTML (in asp.net Web Forms), we create HTTP handlers, override content
type , do response.end etc. It’s not an easy task. In Asp.net MVC it’s very easy. If return type is
‘string’ you can just return string , you do not need to send complete HTML.

What will happen if we try to return an object from an action method?

Look at the following code block.

Hide Copy Code


namespace WebApplication1.Controllers
{
public class Customer
{
public string CustomerName { get; set; }
public string Address { get; set; }
}
public class TestController : Controller
{
public Customer GetCustomer()
{
Customer c = new Customer();
c.CustomerName = "Customer 1";
c.Address = "Address1";
return c;
}
}
}

Output of above action method will look as shown below.

When return type is some object like ‘customer’, it will return ‘ToString()’ implementation of
that object.By default ‘ToString()’ method returns fully qualified name of the class which is
“NameSpace.ClassName”;

What if you want to get values of properties in above example?

Simply override “ToString” method of class as follows.

Hide Copy Code


public override string ToString()
{
return this.CustomerName+"|"+this.Address;
}

Press F5. Output will be as follows.

Is it must to decorate action methods with public access modifier?

Yes, every public method will become action methods automatically.

What about non-public methods?

They are simply methods of a class and not available publicly . In simple words these methods
can not be invoked from the web.

What if we want a method to be public but not action method?

Simply decorate it with NonAction attribute as follows.


Hide Copy Code
[NonAction]
public string SimpleMethod()
{
return "Hi, I am not action method";
}

When we try to make request to above action method we will get following response.

Understand Views in Asp.Net MVC

As we discussed earlier controller will handle the user’s requests and send the response. Most
commonly the response is HTML as browser understands that format much better. HTML with
some images, texts, Input controls etc. Normally in technical world layer defining the user
interface design is termed as UI layer and in Asp.Net MVC it is termed as View.

Lab 2 – Demonstrating Views

In the first lab we created a simple MVC application with just controller and simple string return
type. Let us go add view part to the MVC application.

Step 1 – Create new action method

Add a new action method inside TestController as follows.

Hide Copy Code


public ActionResult GetView()
{
return View("MyView");
}

Step 2 – Create View

Step 2.1. Right click the above action method and select “Add View”.
Step 2.2. In the “Add View” dialog box put view name as “MyView”, uncheck “use a layout”
checkbox and click “Add”.

It will add a new view inside “Views/Test” folder in solution explored

Step 3 – Add contents to View


Open MyView.cshtml file and add contents as follows.

Hide Copy Code


@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>MyView</title>
</head>
<body>
Welcome to MVC 5 Step by Step learning

</body> </html>

Step 3. Test and Execute

Press F5 and execute the application.

Q and A session around Lab 2


Why View is placed inside Test Folder?

In ASP.net MVC, Views associated with the particular controller is placed inside a special folder.
This special folder will be named as “ControllerName” and placed inside Views folder (located
in the root folder). For every controller only those views will be available which are located
inside its own folder.

For example: All the views related to Test controller will be placed inside “~/Views/Test” and
Test controller can access only those views which are inside Test folder.

Can’t we reuse some of the views across multiple controllers?

Yes, we can. For that we will keep those files inside a special folder called “Shared”.
Views located inside this Shared folder will be available to all the controllers.

Is it possible that one action method is referencing more than one views?

Yes. Look at the following code.

Hide Copy Code


public ActionResult GetView()
{
if(Some_Condition_Is_Matching)
{
return View("MyView");
}
else
{
return View("YourView");
}
}

Note: In Asp.Net MVC views and controllers are not tightly coupled. One action method can
refer more than one view and one view can be referred by more than one action method (by
keeping them in Shared folder). It provides better reusability

What is the purpose of View function?

Creates ViewResult object which renders View to the response.

 ViewResult internally creates the object of ViewPageActivator

 ViewResult choose the correct ViewEngine and passes ViewPageActivator object as argument to
ViewEngine’s constructor.

 ViewEngine create the object of View class

 ViewResult invoke the RenderView method of View.

Note: We have separate topic in the series disucssing Asp.Net MVC life cycle in detail.
What is the relation between ActionResult and ViewResult?

ActionResult is the abstract class whereas ViewResult is the multi level child of ActionResult.
Multilevel because, ViewResult is the child of ViewResultBase and ViewResultBase is the child
of ActionResult.

If we want to return ViewResult why ActionResult is the ViewResult?

To achieve polymorphism. Look at the following example.

Hide Copy Code


public ActionResult GetView()
{
if(Some_Condition_Is_Matching)
{
return View("MyView");
}
else
{
return Content("Hi Welcome");
}
}

In the above example, when some condition is matching we are returning we are invoking
“View” function which will return ViewResult whereas in some other condition we are invoking
“Content” function which is returning Content Result.

What is ContentResult?

ViewResult represents a complete HTML response whereas ContentResult represents a scalar


text response. It’s just like returning pure string. Difference is ContentResult is aActionResult
wrapper around string result. ContentResult is also the child of ActionResult.

Is it possible to invoke View function without Parameter?

Yes, then it will find the view with name “CurrentActionName”.


Learn MVC Project in 7 days – Day 2
Introduction
We believe you have successfully completed day 1 before coming here.

Day 1 mainly concentrated on

 Why MVC?

 Asp.Net Web Forms vs. Asp.Net MVC

 Understanding Controllers and Views

Note:

If you have not completed the previous day, please make sure to complete it first. Our target is to
create a small MVC project using best practices and modern methodology at the end of the day.
With every next lab we will either add new functionality to previous lab or make previous lab
better.

Complete Series

 Day 1

 Day 2

 Day 3

 Day 4

 Day 5

 Day 6

 Day 7

 Bonus Day 1

 Bonus Day 2
Day 2 Agenda
Introduction

Day 2 Agenda

Passing Data from Controller to View

Lab 3 – Using ViewData

Talk on Lab 3

Lab 4 – Using ViewBag

Talk on Lab 4

Problems with ViewData and ViewBag

Lab 5 - Understand strongly typed Views

Talk on Lab 5

Understand View Model in Asp.Net MVC

ViewModel a solution

Lab 6 – Implementing View Model

Talk on Lab 6

Lab 7– View With collection

Talk on Lab 7

Conclusion

Passing Data from Controller to View


View created in the Lab 2 is very much static. In real life scenario it will display some dynamic
data. In the next lab we will display some dynamic data in the view.

View will get data from the controller in the form of Model.

Model
In Asp.Net MVC model represent the business data.

Lab 3 – Using ViewData

ViewData is a dictionary, which will contains data to be passed between controller and views.
Controller will add items to this dictionary and view reads from it. Let’s do a demo.

Step 1 - Create Model class

Create a new class Called Employee inside Model folder as follows.

Hide Copy Code


public class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Salary { get; set; }
}

Step 2 -Get Model in controller

Create Employee object inside GetView method as follows

Hide Copy Code


Employee emp = new Employee();
emp.FirstName = "Sukesh";
emp.LastName="Marla";
emp.Salary = 20000;

Note: Make sure to put using statement in the top or else we have to put fully qualified name of
Employee class.

Hide Copy Code


using WebApplication1.Models;

Step 3 – Create ViewData and return View

Store Employee object in viewdata as follows.

Hide Copy Code


ViewData["Employee"] = emp;
return View("MyView");

Step 4 - Display Employee Data in View

Open MyView.cshtml.

Retrieve the Employee data from the ViewData and display it as follows.
Hide Copy Code
<div>
@{
WebApplication1.Models.Employee emp=(WebApplication1.Models.Employee)
ViewData["Employee"];
}

<b>Employee Details </b><br />


Employee Name : @emp.FirstName@emp.LastName <br />
Employee Salary: @emp.Salary.ToString("C")
</div>

Step 5- Test the ouput

Press F5 and test the application.

Talk on Lab 3

What is the difference between writing Razor code with brace brackets (that is “{“ and “}”)
and without brace brackets?

In the last lab @emp.FirstName can be replaced with following code snippet.

Hide Copy Code


@{
Response.Write(emp.FirstName);
}

@ Without brace brackets simply display the value of variable or expression.

Why casting is required?

ViewData holds objects internally. Every time a new value is added into it, it get boxed to object
type.

So unboxing is required every time we try to extract value out of it.

What is the meaning of “@emp.FirstName @emp.LastName”?

It means Display First Name followed by a space and then last name.

Can we write same thing with single @ keyword?


Yes, then syntax for this will be @(emp.FirstName+” “+emp.LastName)

Why hardcoded Employee class is created in Controller?

Just for demo purpose. In real time we will get it from may be database or wcf or web service or
may be from somewhere else.

What about the Database Logic/ Data Access Layer and Business Layer?

 Data Access Layer is one of the unspoken layer in Asp.Net MVC. It’s always there but never
included in MVC definition.

 Business layer as explained prior, it’s a part of Model.

Complete MVC structure

Lab 4 – Using ViewBag

ViewBag is just a syntactic sugar for ViewData. ViewBag uses the dynamic feature of C# 4.0 and
makes ViewData dynamic.

ViewBag internally uses ViewData.

Step 1 – Create View Bag

Continue with the same Lab 3 and replace Step 3 with following code snippet.

Hide Copy Code


ViewBag.Employee = emp;

Step 2 - Display EmployeeData in View

Change Step 4 with following code snippet.

Hide Copy Code


@{
WebApplication1.Models.Employee emp = (WebApplication1.Models.Employee)
ViewBag.Employee;
}
Employee Details

Employee Name: @emp.FirstName @emp.LastName

Employee Salary: @emp.Salary.ToString("C")

Step 3 - Test the output

Press F5 and test the application

Talk on Lab 4

Can we pass ViewData and get it as ViewBag?

Yes, We can. Vice versa is also possible. As I said before, ViewBag is just a syntactic sugar for
ViewData,

Problems with ViewData and ViewBag

ViewData and ViewBag is a good option for passing values between Controller and View. But in
real time projects it’s not a good practice to use any of them. Let’s discuss couple of
disadvantages of using ViewData and ViewBag.

Performance issues

Values inside the ViewData are of type Object. We have to cast the value to correct type before
using it. It adds additional overhead on performance.

No Type safety and no compile time errors

If we try to cast values to wrong type or if we use wrong keys while retrieving the values, we
will get runtime error. As a good programming practice, error should be tackled in compiled
time.

No Proper connection between Data sent and Data Received

As a developer I personally found this as a major issue.


In MVC, controller and View are loosely connected to each other. Controller is completely
unaware about what’s happening in View and View is unaware about what’s happening in
Controller.

From Controller we can pass one or more ViewData/ViewBag values. Now when Developer
writes a View, he/she have to remember what is coming from the controller. If Controller
developer is different from View developer then it becomes even more difficult. Complete
unawareness. It leads to many run time issues and inefficiency in development.

Lab 5 - Understand strongly typed Views

Reason for all three problems of ViewData and ViewBag is the data type. Data type of values
inside ViewData, which is “Object”.

Somehow if we were able to set the type of data which need to be passed between Controller and
View problem will get solved and that’s wherestrongly typed Views comes to picture.

Let’s do a demo. This time we will take our View requirement to next level. If salary is greater
than 15000 then it will be displayed in yellow colour or else green colour.

Step 1 – Make View a strongly typed view

Add following statement in the top of the View

Hide Copy Code


@model WebApplication1.Models.Employee

Above statement make our View a strongly typed view of type Employee.

Step 2 – Display Data

Now inside View simply type @Model and Dot (.) and in intellisense you will get all the
properties of Model (Employee) class.

Write down following code to display the data

Hide Copy Code


Employee Details

Employee Name : @Model.FirstName @Model.LastName


@if(Model.Salary>15000)
{
<span style="background-color:yellow">
Employee Salary: @Model.Salary.ToString("C")
</span>
}
else
{
<span style="background-color:green">

Employee Salary: @Model.Salary.ToString("C")


</span>
}

Step 3 – Pass Model data from Controller Action method

Change the code in the action method to following.

Hide Copy Code


Employee emp = new Employee();
emp.FirstName = "Sukesh";
emp.LastName="Marla";
emp.Salary = 20000;
return View("MyView",emp);

Step 4 – Test the output

Talk on Lab 5

Is it required to type fully qualified class Name (Namespace.ClassName) in View every


time?

No, we can put a using statement.

Hide Copy Code


@using WebApplication1.Models
@model Employee

Is it must to make View a strongly typed view always or can we go with ViewData or
ViewBag sometimes?

As a best practice always make the view a strongly typed view.

Can we make our View a strongly typed view of more than one model?
No, we can’t. In real time project we often end up at a point where we want to display multiple
models in same view. Solution for this requirement will be discussed in next lab.

Understand View Model in Asp.Net MVC

In Lab 5 we have violated MVC principle. According to MVC, V that is View should be pure UI.
It should not contain any kind of logic. We have done following three things which purely
violates MVC architecture rules.

 Append First name and Last Name and Display it as Full Name - Logic

 Display Salary with Currency – Logic

 Display Salary in different colour based on value. In simple words Change appearance of HTML
element based on some value. – Logic

Other than these three issues, there isone more pointworth discussion.
Let say we have situation where we want to display more than one kind of data in the View.
Example – Show Current logged in User’s Name along with Employee data

We can implement this in one of the following ways.

1. Add UserName property to Employee class –Every time we want to display new data in the view,
adding new property to Employee class seems illogical. This new property may or may not be
related to Employee. It also violates SRP of SOLID principle.

2. Use ViewBag or ViewData – We already discussed problems of using this approach.

ViewModel a solution

ViewModel is one of the unspoken layer in the Asp.Net MVC application. It fits between Model
and View and act as data container for View

Difference between Model and ViewModel?

Model is Business specific data. It will be created based on Business and Database structure.
ViewModel is View specific data. It will be created based on the View.

How it works exactly?

It’s simple.

 Controller handle the user interaction logic or in simple words, handles the user’s requests.

 Controller get one or more model data.

 Controller will decide which View suits best as response for the correct request.
 Controller will create and initialises ViewModel object from Model data retrieved based on View
Requirement

 Controller will pass ViewModel data to View by means of ViewData/ViewBag/Stongly typed


View.

 Controller will return the view.

How View and ViewModel will be connected here?

View is going to be a strongly typed view of type ViewModel.

How Model and ViewModel will be connected?

Model and ViewModel should be independent of each other. Controller will create and initialises
ViewModel object based on one or more Model object.

Let’s do a small lab to understand it better.

Lab 6 – Implementing View Model

Step 1 – Create Folder

Create a new folder called ViewModels in the project

Step 2 – Create EmployeeViewModel

In order to do that, let’s list all the requirement on the view

1. First Name and Last Name should be appended before displaying

2. Amount should be displayed with currency

3. Salary should be displayed in different colour (based on value)

4. Current User Name should also be displayed in the view as well

Create a new class called EmployeeViewModelinside ViewModels folder will looks like below.

Hide Copy Code


public class EmployeeViewModel
{
public string EmployeeName { get; set; }
public string Salary { get; set; }
public string SalaryColor { get; set; }
public string UserName{get;set;}
}
Please note, in View Model class, FirstName and LastName properties are replaced with one
single property called EmployeeName, Data type of Salary property is string and two new
propertiesareadded called SalaryColor and UserName.

Step 3 – Use View Model in View

In Lab 5 we had made our View a strongly type view of type Employee. Change it to
EmployeeViewModel

Hide Copy Code


@using WebApplication1.ViewModels
@model EmployeeViewModel

Step 4 – Display Data in the View

Replace the contents in View section with following snippet.

Hide Copy Code


Hello @Model.UserName
<hr />
<div>
<b>Employee Details</b><br />
Employee Name : @Model.EmployeeName <br />
<span style="background-color:@Model.SalaryColor">
Employee Salary: @Model.Salary
</span>
</div>
Step 5 – Create and Pass ViewModel

In GetView action method,get the model data and convert it to ViewModel object as follows.

Hide Copy Code


public ActionResult GetView()
{
Employee emp = new Employee();
emp.FirstName = "Sukesh";
emp.LastName="Marla";
emp.Salary = 20000;

EmployeeViewModel vmEmp = new EmployeeViewModel();


vmEmp.EmployeeName = emp.FirstName + " " + emp.LastName;
vmEmp.Salary = emp.Salary.ToString("C");
if(emp.Salary>15000)
{
vmEmp.SalaryColor="yellow";
}
else
{
vmEmp.SalaryColor = "green";
}

vmEmp.UserName = "Admin"
return View("MyView", vmEmp);
}

Step 5 – Test the output

Press F5 and Test the output

Same output as Lab 5 but this time View won’t contain any logic.

Talk on Lab 6

Does it means, every model will have one View Model?

No, Every View will have its corresponding ViewModel.

Is it a good practice to have some relationship between Model and ViewModel?

No, as a best practice Model and ViewModel should be independent to each other.

Should we always create ViewModel? What if View won’t contain any presentation logic
and it want to display Model data as it is?

We should always create ViewModel. Every view should always have its own ViewModel even
if ViewModel is going to contain same properties as model.

Let’s say we have a situation where View won’t contain presentation logic and it want to display
Model data as it is.Let’s assume we won’t create a ViewModelin this situation.
Problem will be, if in future requirement,ifwe have been asked to show some new data in our UI
or if we asked to put some presentation logic we may end with complete new UI creation from
the scratch.
So better if we keep a provision from the beginning and Create ViewModel. In this case, in the
initial stage ViewModel will be almost same as Model.

Lab 7– View With collection

In this lab we will display list of Employees in the View.

Step 1 – Change EmployeeViewModel class

Remove UserName property from EmployeeViewModel.


Hide Copy Code
public class EmployeeViewModel
{
public string EmployeeName { get; set; }
public string Salary { get; set; }
public string SalaryColor { get; set; }
}

Step 2– Create Collection View Model

Create a class called EmployeeListViewModel inside ViewModel folder as follows.

Hide Copy Code


public class EmployeeListViewModel
{
public List<EmployeeViewModel><employeeviewmodel> Employees { get; set; }
public string UserName { get; set; }
}
</employeeviewmodel>

Step 3 – Change type of strongly typed view

Make MyView.cshtml a strongly typed view of type EmployeeListViewModel.

Hide Copy Code


@using WebApplication1.ViewModels
@model EmployeeListViewModel

Step 4– Display all employees in the view

Hide Copy Code


<body>
Hello @Model.UserName
<hr />
<div>
<table>
<tr>
<th>Employee Name</th>
<th>Salary</th>
</tr>
@foreach (EmployeeViewModel item in Model.Employees)
{
<tr>
<td>@item.EmployeeName</td>
<td style="background-
color:@item.SalaryColor">@item.Salary</td>
</tr>
}
</table>
</div>
</body>

Step 5 – Create Business Layer for Employee


In this lab, we will take our project to next level. We will add Business Layer to our project.
Create a new class called EmployeeBusinessLayer inside Model folder with a method called
GetEmployees.

Hide Copy Code


public class EmployeeBusinessLayer
{
public List<Employee><employee> GetEmployees()
{
List<Employee><employee> employees = new List<Employee><employee>();
Employee emp = new Employee();
emp.FirstName = "johnson";
emp.LastName = " fernandes";
emp.Salary = 14000;
employees.Add(emp);</employee>

Step 6– Pass data from Controller

Hide Shrink Copy Code


public ActionResult GetView()
{
EmployeeListViewModel employeeListViewModel = new EmployeeListViewModel();

EmployeeBusinessLayer empBal = new EmployeeBusinessLayer();


List<employee> employees = empBal.GetEmployees();

List<EmployeeViewModel><employeeviewmodel> empViewModels = new


List<EmployeeViewModel><employeeviewmodel>();

foreach (Employee emp in employees)


{
EmployeeViewModel empViewModel = new EmployeeViewModel();
empViewModel.EmployeeName = emp.FirstName + " " + emp.LastName;
empViewModel.Salary = emp.Salary.ToString("C");
if (emp.Salary > 15000)
{
empViewModel.SalaryColor = "yellow";
}
else
{
empViewModel.SalaryColor = "green";
}
empViewModels.Add(empViewModel);
}
employeeListViewModel.Employees = empViewModels;
employeeListViewModel.UserName = "Admin";
return View("MyView", employeeListViewModel);
}
</employeeviewmodel>

Step 7 – Execute and Test the Output

Press F5 and execute the application.


Talk on Lab 7

Can we make View a strongly typed view of List?

Yes, we can.

Why we create a separate class called EmployeeListViewModel, why didn’t we made View
a strongly typed view of type List<EmployeeListViewModel>?

If we use List directly instead of EmployeeListViewModel then there will be two problems.

1. Managing future presentation logic.

2. Secondly UserName property. UserName is not associated with individual employees. It is


associated with complete View.

Why we removed UserName property from EmployeeViewModel and made it part of


EmployeeListViewModel?

UserName is going to be same for all the employees. Keeping UserName property inside
EmployeeViewModel just increase the redundent code and also increases the overall memoty
requirement for data.

Conclusion
Here we complete our day 2. In Day 3 we will take our project into next version.

Connect us on Facebook, LinkedIn or twitter to stay updated about new releases.

For Offline Technical trainings in Mumbai visit StepByStepSchools.Net

For Online Trainings visit JustCompile.com

In case you want to start with MVC 5 start with the below video Learn MVC 5 in 2 days.
Learn MVC Project in 7 days – Day 3
Introduction
We are assuming that you have read previous days before coming here. In day 2 we have
completed a project which had a grid with List of Employees.
In day 3 we will take it to the next level by introducing data access layer and data entry screen.

Complete Series

 Day 1

 Day 2

 Day 3

 Day 4

 Day 5

 Day 6

 Day 7

 Bonus Day 1

 Bonus Day 2

Agenda
Data Access Layer

What is Entity Framework in simple words?

What is Code First Approach?

Lab 8 – Add Data Access layer to the project

Talk on Lab 8

Organize everything
Lab 9 – Create Data Entry Screen

Talk on Lab 9

Lab 10 – Get posted data in Server side/Controllers

Talk on Lab 10

Lab 11 – Reset and Cancel button

Talk on Lab 11

Lab 12 – Save records in database and update Grid

Lab 13 – Add Server side Validation

How Model Binder work with primitive datatypes

How Model Binder work with classes

Talk on lab 13

Lab 14 – Custom Server side validation

Conclusion

Data Access Layer


A real time project is incomplete without Database. In our project we didn’t spoke database layer
yet. First Lab of Day 3 will be all about database and database layer.

Here we will use Sql Server and Entity Framework for creating Database and Database Access
layer respectively.

What is Entity Framework in simple words?

It’s an ORM tool. ORM stands for Object Relational Mapping.

In RDBMS world, we speak in terms of Tables and Columns whereas in .net world (which is an
object oriented world), we speak in terms of Classes, objects and properties.

When we think about any data driven application we end up with following two things.

 Write code for communicating with database (called Data Access Layer or Database logic)

 Write code for mapping Database data to object oriented data or vice versa.
ORM is a tool which will automate these two things. Entity framework is Microsoft ORM tool.

What is Code First Approach?

In Entity framework we can follow one of these three approaches

 Database First approach – Create database with tables, columns, relations etc. and Entity
framework will generates corresponding Model classes (Business entities) and Data Access Layer
code.

 Model First approach – In this approach Model classes and relationship between them will be
defined manually using Model designer in Visual studio and Entity Framework will generate Data
Access Layer and Database with tables, columns, relations automatically.

 Code First approach – In this approach manually POCO classes will be created. Relationship
between those classes will be defined by means of code.When application executes for the first
time Entity framework will generate Data Access Layer and Database with tables, column and
relations automatically in the database server.

What is mean by POCO classes?

POCO stands for “Plain Old CLR objects”. POCO classes means simple .Net classes we create.
In our previous example Employee class was simply a POCO class.

Lab 8 – Add Data Access layer to the project


Step 1– Create Database

Connect to the Sql Server and create new Database called “SalesERPDB”.

Step 2 – Create ConnectionString


Open Web.config file and inside Configuration section add following section

Hide Copy Code


<connectionStrings>
<add connectionString="Data Source=(local);Initial
Catalog=SalesERPDB;Integrated Security=True"
name="SalesERPDAL"
providerName="System.Data.SqlClient"/>
</connectionStrings>

Step 3– Add Entity Framework reference

Right click the project >> Manage Nuget packages. Search for Entity Framework and click
install.
Step 4 – Create Data Access layer.

 Create a new folder called “DataAccessLayer” in the root folder and inside it create a new class
called “SalesERPDAL”

 Put using statement at the top as follows.

 Hide Copy Code

using System.Data.Entity;

 Inherit “SalesERPDAL” from DbContext

Hide Copy Code


public class SalesERPDAL: DbContext
{
}

Step 5 – Create primary key field for employee class

Open Employee class and put using statement at the topas follows.

Hide Copy Code


using System.ComponentModel.DataAnnotations;

Add EmployeeId property in Employee class and mark it as Key attribute.

Hide Copy Code


public class Employee
{
[Key]
public int EmployeeId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Salary { get; set; }
}

Step 6 – Define mapping

Put following using statement in the top for “SalesERPDAL” class

Hide Copy Code


using WebApplication1.Models;

Override OnModelCreating method in SalesERPDAL class as follows.

Hide Copy Code


protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<employee>().ToTable("TblEmployee");
base.OnModelCreating(modelBuilder);
}
</employee>

Note: In above code snippet “TblEmployee” represents the table name. It automatically get
created in runtime.

Step 7 – Create property to hold Employees in Database

Create a new property called Employee in “SalesERPDAL” class as follows

Hide Copy Code


public DbSet<employee> Employees{get;set;}
</employee>

DbSet will represent all the employees that can be queried from the database.

Step 8– Change Business Layer Code and get data from Database

Open EmployeeBusinessLayer class.Put using statement in the top.

Hide Copy Code


using WebApplication1.DataAccessLayer;

Now change GetEmployees method class as follows.

Hide Copy Code


public List<employee> GetEmployees()
{
SalesERPDAL salesDal = new SalesERPDAL();
return salesDal.Employees.ToList();
}
</employee>

Step 9 – Execute and Test

Press F5 and execute the application.


Right now we don’t have any employees in the database so we will see a blank grid.

Check the database. Now we have a table called TblEmployee with all the columns.

Step 9 – Insert Test Data

Add some dummy data to TblEmployee table.


Step 10 – Execute and test the application

Press F5 and run the application again.

Here we go

Talk on Lab 8

What is DbSet?

DbSet simply represent the collection of all the entities that can be queried from the database.
When we write a Linq query again DbSet object it internally converted to query and fired against
database.

In our case “Employees” is a DbSet which will hold all the “Employee” entitieswhich can be
queried from database. Every time we try to access “Employees” it gets all records in the
“TblEmployee” table and convert it to “Employee” object and return the collection.
How connection string and data access layer is connected?

Mapping will be done based on name. In our example ConnectionString Name and Data Access
Layer class name is same that is “SalesERPDAL”, hence automatically mapped.

Can we change the ConnectionString name?

Yes, in that case we have to define a constructor in Data Access Layer class as follows.

Hide Copy Code


public SalesERPDAL():base("NewName")
{
}

Organize everything
Just to make everything organized and meaningful let’s do couple of changes.

Step 1 - Rename

 “TestController” to “EmployeeController”

 GetView action method to Index

 Test folder (inside Views folder) to Employee

 and “MyView” view to “Index”

Step 2 – Remove UserName property from EmployeeListViewModel

Step 3 – Remove UserName from View

Open Views/Employee.Index.cshtml View and remove username from it.

In simple words, remove following block of code.

Hide Copy Code


Hello @Model.UserName
<hr />

Step 2 – Change Index Action Method in EmployeeController

Accordingly Change the code in Index action in EmployeeController as follows.

Hide Copy Code


public ActionResult Index()
{
&hellip;&hellip;
&hellip;&hellip;
&hellip;&hellip;
employeeListViewModel.Employees = empViewModels;
//employeeListViewModel.UserName = "Admin";-->Remove this line -->Change1
return View("Index", employeeListViewModel);//-->Change View Name
-->Change 2
}

Now at the time of execution URL will “…./Employee/Index”

Lab 9 – Create Data Entry Screen


Step 1 – Create action method

Create an action method called “AddNew” in EmployeeController as follows

Hide Copy Code


public ActionResult AddNew()
{
return View("CreateEmployee");
}

Step 2 – Create View

Create a view called “CreateEmployee” inside View/Employee folder as follows.

Hide Copy Code


@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>CreateEmployee</title>
</head>
<body>
<div>
<form action="/Employee/SaveEmployee" method="post">
First Name: <input type="text" id="TxtFName" name="FirstName"
value="" /><br />
Last Name: <input type="text" id="TxtLName" name="LastName"
value="" /><br />
Salary: <input type="text" id="TxtSalary" name="Salary"
value="" /><br />
<input type="submit" name="BtnSave" value="Save Employee" />
<input type="button" name="BtnReset" value="Reset" />
</form>
</div>
</body>
</html>
Step 3 – Create a link in Index View

Open Index.cshtml and add a hyperlink pointing to AddNew Action URL.

Hide Copy Code


<ahref="/Employee/AddNew">Add New</a>

Step 4 –Execute and Test the application

Press F5 and execute the application


Talk on Lab 9

What is the purpose of form tag?

In day 1 of the series we have understood that “Web world won’t follow Event driven
programming model. It follows request-response model. End user make the request and server
sendsresponse.” Form tag is one of the way to make request in HTML. As soon as the submit
button inside form tag gets clicked, a request will be sent to the URL specified in action attribute.

What is method attribute in Form tag?

It decides the type of request. Request may be one of the following four types - get, post, put and
delete.

As per the web standards we should use–

 Get - > When we want to get something

 Post -> When we want to create something

 Put -> When we want to update something

 Delete -> when we want to delete something.

How making request using Form tag is different from making request via browser address
bar or hyperlink?

When request is made with the help of Form tag, values of all the input controls are sent with the
request for processing.

What about checkbox, radio buttons and Dropdowns? Will values of this controls also
sent?

Yes, All input controls (input type=text, type=radio, type=checkbox) and also dropdowns (which
represented as “Select” element).

How values will be sent to server?

When request is of type Get, Put or Delete, values will be sent as Query string parameters.

When it’s a post request values will be sent as posted data.

What is the purpose of name attribute in input controls?

As discussed before values of all input controls will be sent along with request when submit
button is clicked. It makes server receive more than one value at a time. To distinguish each
value separately while sending every value is attached with one key and that key will be simply
“name” attribute.

Does name and id attribute serves same purpose?

No, as per last question “name” attribute will be used internally by HTML when the request is
being sent whereas “id” attribute will be used by developers inside JavaScript for some dynamic
stuffs.

What is the difference between “input type=submit” and “input type=button”?

Submit button will be specially used when we want to make request to the server whereas simple
button will be used to perform some custom client side actions. Simple button won’t do anything
by its own.

Lab 10 – Get posted data in Server


side/Controllers
Step 1 – Create SaveEmployee Action method

Inside Employee Controller create an action method called SaveEmployee as follows.

Hide Copy Code


public string SaveEmployee(Employee e)
{
return e.FirstName + "|"+ e.LastName+"|"+e.Salary;
}

Step 2 – Execute and Test

Press F5 and execute the application.


Talk on Lab 10

How Textbox values are updated in Employee object inside action method?

In Asp.Net MVC there is a concept called as Model Binder.

 Model Binder will executes automatically whenever a request is made to an action method
containing parameter.

 Model binder will iterate though all primitive parameters of a method and then it will compare
name of the parameter with each key in the incoming data (Incoming data means either posted
data or query string).When match is found, corresponding incoming datawill be assigned to the
parameter.

 After that Model binder will iterate through each and every property of each and every class
parameter and compare each property name with each key in incoming data.When match is
found, corresponding incoming value will be assigned to the parameter.

What will happen when two parameters are specified, one as “Employee e” and second as
“string FirstName”?

FirstName will be updated in both primitive FirstName variable and e.FirstName property.

Will Model Binder workwith composition relationship?

Yes it will, but in that case name of the control should be given accordingly.

Example

Let say we have Customer class and Address class as follows

Hide Copy Code


public class Customer
{
public string FName{get;set;}
public Address address{get;set;}
}
public class Address
{
public string CityName{get;set;}
public string StateName{get;set;}
}

In this case Html should look like this

Hide Copy Code


...
...
...
<input type="text" name="FName">
<input type="text" name="address.CityName">
<input type="text" name="address.StateName">
...
...
...

Lab 11 – Reset and Cancel button


Step 1 – Start withReset and Cancel button

Add a Reset and Cancel button as follows

Hide Copy Code


...

...

...

<input type="submit" name="BtnSubmit&rdquo; value="Save Employee" />

<input type="button" name="BtnReset" value="Reset" onclick="ResetForm();" />

<input type="submit" name="BtnSubmit" value="Cancel" />

Note: Save button and Cancel button have same “Name” attribute value that is “BtnSubmit”.

Step 2 – define ResetForm function

In Head section of Html add a script tag and inside that create a JavaScript function called
ResetForm as follows.

Hide Copy Code


<script>
function ResetForm() {
document.getElementById('TxtFName').value = "";
document.getElementById('TxtLName').value = "";
document.getElementById('TxtSalary').value = "";
}
</script>

Step 3 – Implement cancel click in EmplyeeController’s SaveEmployee action method.

Change SaveEmployee action method as following

Hide Copy Code


public ActionResult SaveEmployee(Employee e, string BtnSubmit)
{
switch (BtnSubmit)
{
case "Save Employee":
return Content(e.FirstName + "|" + e.LastName + "|" + e.Salary);
case "Cancel":
return RedirectToAction("Index");
}
return new EmptyResult();
}

Step 4 – Execute the application.

Press F5 and execute the application. Navigate to the AddNew screen by clicking “Add New”
link.

Step 5 – Test Reset functionality

Step 6 – Test Save and Cancel functionality

Talk on Lab 11

Why same name is given to both Save and Cancel button?


We know that, as soon as submit button is clicked, a request is sent to the server.Along with the
request values of all the input controls will be sent.

Submit button is also an input button. Hence value of the submit button (which is responsible for
the request) will be sent too.

When Save button will be clicked, value of Save button that is “Save Employee” will be sent
with request and when Cancel button is clicked, value of Cancel button that is “Cancel” will sent
with request.

In Action method, Model Binder will do remaining work. It will update the parameter values
with values in input data (coming with request)

What are the other ways to implement multiple submit buttons?

There are many ways. I would like to discuss three of them.

1. Hidden Form element

Step 1 – Create a hidden form element in View as follows.

Hide Copy Code


<form action="/Employee/CancelSave" id="CancelForm" method="get"
style="display:none">

</form>

<form action="/Employee/CancelSave" id="CancelForm" method="get"


style="display:none"> </form>

Step 2 – Change Submit button to normal button and post above form with the help of
JavaScript.

Hide Copy Code


<input type="button" name="BtnSubmit" value="Cancel"
onclick="document.getElementById('CancelForm').submit()" />

2. Change action URL dynamically using JavaScript

Hide Copy Code


<form action="" method="post" id="EmployeeForm" >
...
...
<input type="submit" name="BtnSubmit" value="Save Employee"
onclick="document.getElementById('EmployeeForm').action =
'/Employee/SaveEmployee'" />
...
<input type="submit" name="BtnSubmit" value="Cancel"
onclick="document.getElementById('EmployeeForm').action =
'/Employee/CancelSave'" />
</form>

3. Ajax

Instead of submit button use simple input button and onclick of it make pure Ajax request using
jQuery or any other library.

Why we have not used input type=reset for implementing Reset functionality?

Input type=reset control won’t clear the values, it just set the value to default value of a control.
Example:

Hide Copy Code


<input type="text" name="FName" value="Sukesh">

In above example default value of control is “Sukesh”.

If we use input type=reset for implementing Reset functionality then by default “Sukesh” will be
set in the textbox every time “reset” button is clicked.

What if names are not matching with property names of the classes?

This is a very common question during interviews.

Let say we have HTML as follows

Hide Copy Code


First Name: <input type="text" id="TxtFName" name="FName" value="" /><br />
Last Name: <input type="text" id="TxtLName" name="LName" value="" /><br />
Salary: <input type="text" id="TxtSalary" name="Salary" value="" /><br />

Now our Model class contain property names as FirstName, LastName and Salary. Hence default
model binder won’t work here.

In this situation we have following three solutions

 Inside action method, retrieve posted values using Request.Form syntax and manually construct
the Model object as follows.

Hide Copy Code


public ActionResult SaveEmployee()
{
Employee e = new Employee();
e.FirstName = Request.Form["FName"];
e.LastName = Request.Form["LName"];
e.Salary = int.Parse(Request.Form["Salary"])
...
...
}
 Use parameter names and Creates Model object manually as follows.

Hide Copy Code


public ActionResult SaveEmployee(string FName, string LName, int Salary)
{
Employee e = new Employee();
e.FirstName = FName;
e.LastName = LName;
e.Salary = Salary;
...
...
}

 Create Custom Model Binder and replace default model binder as follows.

Step 1 – Create Custom Model Binder

Hide Copy Code


public class MyEmployeeModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext,
ModelBindingContext bindingContext, Type modelType)
{
Employee e = new Employee();
e.FirstName =
controllerContext.RequestContext.HttpContext.Request.Form["FName"];
e.LastName =
controllerContext.RequestContext.HttpContext.Request.Form["LName"];
e.Salary =
int.Parse(controllerContext.RequestContext.HttpContext.Request.Form["Salary"])
;
return e;
}
}

Step 2- Replace default model binder with this new model binder

Hide Copy Code


public ActionResult
SaveEmployee([ModelBinder(typeof(MyEmployeeModelBinder))]Employee e, string
BtnSubmit)
{
......

What does RedirecttToFunction do?

It generates RedirectToRouteResultJust like ViewResult and ContentResult (discussed in Day 1),


RedirectToRouteResult is a child of ActionResult.It represents the redirect response. When
browser receives RedirectToRouteResult, it makes new request to new action method.

Note: Here browser is responsible for new request hence URL will get updated to new URL.
What is EmptyResult?

One more child of ActionResult. When browser receives EmptyResult as a response it simply
displays blank white screens. It simply represents “No Result”.

In our example this situation won’t happen. Just to make sure that all code paths returns a value
EmptyResult statement was written.

Note:When ActionMethod return type is Void, it is equivalent to EmptyResult

Lab 12 – Save records in database and


update Grid
Step 1 – Create SaveEmployee in EmployeeBusinessLayer as follows

Hide Copy Code


public Employee SaveEmployee(Employee e)
{
SalesERPDAL salesDal = new SalesERPDAL();
salesDal.Employees.Add(e);
salesDal.SaveChanges();
return e;
}

Step 2 – Change SaveEmployee Action method

In EmployeeController change the SaveEmployee action method code as follows.

Hide Copy Code


public ActionResult SaveEmployee(Employee e, string BtnSubmit)
{
switch (BtnSubmit)
{
case "Save Employee":
EmployeeBusinessLayer empBal = new EmployeeBusinessLayer();
empBal.SaveEmployee(e);
return RedirectToAction("Index");
case "Cancel":
return RedirectToAction("Index");
}
return new EmptyResult();
}

Step 3 – Execute and Test

Press F5 and execute the application. Navigate to Data entry screen and put some valid values.
Lab 13 – Add Server side Validation
In Lab 10 we have seen basic functionality of Model Binder. Let understand a little more about
same.

 Model binder updates the Employee object with the posted data.

 But this is not the only functionality performed by Model Binder. Model Binder also updates
ModelState. ModelState encapsulates the state of the Model.

 It have a property called IsValid which determines whether the Model (that is Employee object)
gets successfully updated or not.Model won’t update if any of the server side validation fails.

 It holds validation errors.


Example:ModelState["FirstName "].Errors will contain all errors related to First Name

 It holds the incoming value(Posted data or queryString data)

 It holds the incoming value(Posted data or queryString data)

In Asp.net MVC we use DataAnnotations to perform server side validations.

Before we get into Data Annotation lets understand few more things about Model Binder

How Model Binder work with primitive datatypes

When Action method contain primitive type parameter, Model Binder will compare name of the
parameter with each key in the incoming data (Incoming data means either posted data or query
string).

 When match is found, corresponding incoming data will be assigned to the parameter.

 When match is not found, parameter will be assigned with default value. (Default value – For
integer it is 0 (zero), for string it is null etc.)

 In case assignment is not possible because of datatype mismatch exception will be thrown.
How Model Binder work with classes

When parameter is a Class parameter, Model Binder will iterate through all properties of all the
class and compare each property name with each key in incoming data.

 When match is found,

 If corresponding incoming value is empty, then

 Null value will be assigned to property. If null assignment is not possible, default value will be set
and ModelState.IsValid will be set to false.

 If null assignment is possible but will be considered as invalid value because of the validation
attached to the property then null be assigned as value and ModelState.IsValid will be set to
false.

 If corresponding incoming value is non empty,

 In case assignment is not possible because of datatype mismatch or Server side validation failure
null value will be assigned and ModelState.IsValid will be set to false.

 If null assignment is not possible, default value will be set

 When match is not found, parameter will be assigned with default value. (Default value – For
integer it is 0 (zero), for string it is null etc.)In this case ModelState.IsValid will remain unaffected.

Let’s understand same by adding validation feature to our on-going project.

Step 1 – Decorate Properties with DataAnnotations

Open Employee class from Model folder and decorate FirstName and LastName property with
DataAnnotation attribute as follows.

Hide Copy Code


public class Employee
{
...
...
[Required(ErrorMessage="Enter First Name")]
public string FirstName { get; set; }

[StringLength(5,ErrorMessage="Last Name length should not be greater than


5")]
public string LastName { get; set; }
...
...
}

Step 2 – Change SaveEmployee Action method


Open EmplyeeController and Change SaveEmployee Action method as follows.

Hide Copy Code


public ActionResult SaveEmployee(Employee e, string BtnSubmit)
{
switch (BtnSubmit)
{
case "Save Employee":
if (ModelState.IsValid)
{
EmployeeBusinessLayer empBal = new EmployeeBusinessLayer();
empBal.SaveEmployee(e);
return RedirectToAction("Index");
}
else
{
return View("CreateEmployee ");
}
case "Cancel":
return RedirectToAction("Index");
}
return new EmptyResult();
}

Note: As you can see, When ModelState.IsValid is false response of SaveEmployee button click
is ViewResult pointing to “CreateEmployee” view.

Step 3 – Display Error in the View

Change HTML in the “Views/Index/CreateEmployee.cshtml” to following.

This time we will format our UI a little with the help of “table” tag;

Hide Shrink Copy Code


<table>
<tr>
<td>
First Name:
</td>
<td>
<input type="text" id="TxtFName" name="FirstName" value="" />
</td>
</tr>
<tr>
<td colspan="2" align="right">
@Html.ValidationMessage("FirstName")
</td>
</tr>
<tr>
<td>
Last Name:
</td>
<td>
<input type="text" id="TxtLName" name="LastName" value="" />
</td>
</tr>
<tr>
<td colspan="2" align="right">
@Html.ValidationMessage("LastName")
</td>
</tr>

<tr>
<td>
Salary:
</td>
<td>
<input type="text" id="TxtSalary" name="Salary" value="" />
</td>
</tr>
<tr>
<td colspan="2" align="right">
@Html.ValidationMessage("Salary")
</td>
</tr>

<tr>
<td colspan="2">
<input type="submit" name="BtnSubmit" value="Save Employee" />
<input type="submit" name="BtnSubmit" value="Cancel" />
<input type="button" name="BtnReset" value="Reset"
onclick="ResetForm();" />
</td>
</tr>
</table>

Step 4 – Execute and Test

Press F5 and execute the application. Navigate to “Employee/AddNew” action method and test
the application.

Test 1

Test 2
Note: You may end up with following error.
“The model backing the 'SalesERPDAL' context has changed since the database was created.
Consider using Code First Migrations to update the database.”

To remove this error, simply add following statement in Application_Start in Global.asax file.

Hide Copy Code


Database.SetInitializer(new DropCreateDatabaseIfModelChanges<SalesERPDAL>());

Database class exists inside System.Data.Entity namespace

If you are still getting the same error then, open database in Sql server and just delete
__MigrationHistory table.

Soon I will release a new series on Entity Framework where we will learn Entity framework step
by step. This series is intended to MVC and we are trying to stick with it.

Talk on lab 13

What does @Html.ValidationMessage do?

 @ means it’s a razor code

 Html is an instance of HtmlHelper class available inside view.

 ValidationMessageis a function of HtmlHelper class which displays the error message

How ValidationMessage function works?

ValidationMessage is a function. It executes at runtime. As we discussed earlier, ModelBinder


updates the ModelState. ValidationMessage displays the error message from ModelState based
on Key.

Example: ValidationMessage(“FirstName”) displays the error message related to First Name.

Do we have more attributes like required and StringLength?

Yes, here are some


 DataType – Make sure that data is of particular type like email, credit card number, URL etc.

 EnumDataTypeAttribute–Make sure that value exist in an enumeration.

 Range Attribute – Make sure that value is in a particular range.

 Regular expression- Validates the value against a particular regular expression.

 Required – Make sure that value is provided.

 StringthLength – Validates the string for maximum and minimum number of characters.

How Salary is getting validated?

We have not added any Data Annotation attribute to Salary attribute but still it’s getting
validated. Reason for that is, Model Binder also considers the datatype of a property while
updating model.

In Test 1 – we had kept salary as empty string. Now in this case, as per the Model
binderexplanation we had (In Lab 13), ModelState.IsVaid will be false and ModelState will hold
validation error related to Salary which will displayed in view because of
Html.ValidationMessage(“Salary”)

In Test 2 – Salary data type is mismatched hence validation is failed.

Is that means, integer properties will be compulsory by default?

Yes, Not only integers but all value types because they can’t hold null values.

What if we want to have a non-required integer field?

Make it nullable?

Hide Copy Code


public int? Salary{get;set;}

How to change the validation message specified for Salary?

Default validation support of Salary (because of int datatype) won’t allow us to change the
validation message. We achieve the same by using our own validation like regular expression,
range or Custom Validator.

Why values are getting cleared when validation fails?

Because it’s a new request. DataEntry view which was rendered in the beginning and which get
rendered later are same from development perspective but are different from request perspective.
We will learn how to maintain values in Day 4.
Can we explicitly ask Model Binder to execute?

Yes simply remove parameters from action method. It stops default model binder from executing
by default.

In this case we can use UpdateModel function as follows.

Hide Copy Code


Employee e = new Employee();
UpdateModel<employee>(e);
</employee>

Note: UpdateModel won’t work with primitive datatypes.

What is the difference between UpdateModel and TryUpdateModel method?

TryUpdateModel will be same as UpdateModel except one added advantage.

UpdateModel will throw an exception if Model adaption fails because of any reason. In case of
UpdateModel function ModelState.IsValid will not be of any use.

TryUpdateModel is exactly same as keeping Employee object as function parameter. If updating


fails ModelState.IsValid will be false;

What about client side validation?

It should be done manually unless and until we are using HTML Helper classes.

We are going to talk about both manual client side validation and automatic client side validation
with the help of HTML helper classes in day 4.

Can we attach more than one DataAnnotation attribute to same property?

Yes we can. In that case both validations will fire.

Lab 14 – Custom Server side validation


Step 1 – Create Custom Validation

Open Employee.cs file and create a new class Called FirstNameValidation inside it as follows.

Hide Copy Code


public class FirstNameValidation:ValidationAttribute
{
protected override ValidationResult IsValid(object value,
ValidationContext validationContext)
{
if (value == null) // Checking for Empty Value
{
return new ValidationResult("Please Provide First Name");
}
else
{
if (value.ToString().Contains("@"))
{
return new ValidationResult("First Name should Not contain
@");
}
}
return ValidationResult.Success;
}
}

Note: Creating multiple classes inside single file is never consider as good practice. So in your
sample I recommend you to create a new folder called “Validations” in root location and create a
new class inside it.

Step 2- Attach it to First Name

Open Employee class and remove the default “Required” attribute from FirstName property and
attach FirstNameValidation as follows.

Hide Copy Code


[FirstNameValidation]
public string FirstName { get; set; }

Step 3 – Execute and Test

Press F5. Navigate to “Employee/AddNew” action.

Test 1

Test 2
Conclusion
Here we complete our day 3. In Day 4 we will take our project into next version. Here is the
agenda in Day 4

 Implement client side validation

 Understand HTML helper

 Implement Authentication

 Adding Footers with partial Views

 Create consistent layout with Master Pages

 Custom Request filtering


Learn MVC Project in 7 Days – Day 4
Introduction

Welcome to day 4 of “Learn MVC Project in 7 days” series. If you are directly coming to this
article then I strongly recommend you to first complete all the previous parts of the series and
then proceed here.

Complete Series

 Day 1

 Day 2

 Day 3

 Day 4

 Day 5

 Day 6

 Day 7

 Bonus Day 1

 Bonus Day 2

Agenda
Lab 15 – Retaining values on Validation Error
Talk on Lab 15
Lab 16 – Adding Client side validation
Talk on Lab 16
Lab 17 – Adding Authentication
Talk on Lab 17
Lab 18 – Display UserName in the view
Lab 19 – Implement Logout
Lab 20 – Implementing validation in Login Page
Lab 21 – Implementing Client side validation in Login Page
Talk on Lab 21
Conclusion
Lab 15 – Retaining values on Validation Error

In Lab 13 we introduced Server side validation and in Lab 14 we took it to next level by adding a
Custom Validation support.

I strongly recommend you to rerun to the Lab 14 once again. Execute it and understand the code
and output both perfectly.

In the Lab 15 we will learn how to repopulate values on validation failure.

Step 1 - Create CreateEmployeeViewModel

Create a new class in ViewModel folder as follows.

Hide Copy Code


public class CreateEmployeeViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Salary { get; set; }
}

Step 2 – Change SaveEmployee action method

For repopulation we will simply reuse the Employee object created by Model Binder. Change
SaveEmployee Action method as follows.

Hide Shrink Copy Code


public ActionResult SaveEmployee(Employee e, string BtnSubmit)
{
switch (BtnSubmit)
{
case "Save Employee":
if (ModelState.IsValid)
{
EmployeeBusinessLayer empBal = new EmployeeBusinessLayer();
empBal.SaveEmployee(e);
return RedirectToAction("Index");
}
else
{
CreateEmployeeViewModel vm = new CreateEmployeeViewModel();
vm.FirstName = e.FirstName;
vm.LastName = e.LastName;
if (e.Salary.HasValue)
{
vm.Salary = e.Salary.ToString();
}
else
{
vm.Salary = ModelState["Salary"].Value.AttemptedValue;
}
return View("CreateEmployee", vm); // Day 4 Change - Passing e
here
}
case "Cancel":
return RedirectToAction("Index");
}
return new EmptyResult();
}

Step 3 – Repopulate values in View

Step 3.1 Make View a strongly typed view

Put following code in the top of CreateEmployee View.

Hide Copy Code


@using WebApplication1.ViewModels
@model CreateEmployeeViewModel

Step 3.2 Display values in corresponding controls from Model

Hide Shrink Copy Code


...

...

...

<input type="text" id="TxtFName" name="FirstName" value="@Model.FirstName" />

...

...

...

<input type="text" id="TxtLName" name="LastName" value="@Model.LastName" />

...

...

...

<input type="text" id="TxtSalary" name="Salary" value="@Model.Salary" />

...

...

...
Step 4 – Execute and Test

Press F5 and execute the application. Navigate to the AddNew screen by clicking “Add New”
link.

Reason for above error will be discussed at the end of this lab. Let’s implement solution now.

Step 5 – Change AddNew Action method


Hide Copy Code
public ActionResult AddNew()
{
return View("CreateEmployee&rdquo;, new CreateEmployeeViewModel());
}

Step 6 – Execute and Test

Press F5 and execute the application.


Test 1

 Navigate to the AddNew screen by clicking “Add New” link.

 Keep First Name Empty

 Put Salary as 56.

 Click “Save Employee” button.

It will make two validations fail

As you can see 56 is maintained in Salary Textbox.

Test 2

As you can see FirstName and LastName textbox values are maintained.
Strange thing is Salary is not maintaining. We discuss the reason and solution for it in the end of
the lab.

Talk on Lab 15

Are we really retaining values here?

No, we are not. Here we are actually repopulating the values from the posted data.

Why it’s required to pass “new CreateEmployeeViewModel()” during initial request that is
in “Add New” action method?

In the View we are trying to populate textbox with the values in model.

Example:

Hide Copy Code


<input id="TxtSalary" name="Salary" type="text" value="@Model.Salary" />

As you can see, in the above code block we are accessing FirstName property of current Model.
If Model is null, simply “Object reference not set to an instance of the class” exception will be
thrown.

When “Add New” hyperlink is clicked, request will be handled by “Add New” action method.
Earlier in this action method we werereturning view without passing any data. It means Model
property inside view be Null and Null.Something will throw “Object reference not set to an
instance of the class”. To solve this problems “new CreateEmployeeViewModel()” was passed
during initial request.

Do we have any automated way to achieve same functionality?

Yes, we can use HTML helper classes for that. We will talk about this in one of the upcoming
lab.

Lab 16 – Adding Client side validation

First of all let’s list down what all validations we require here.

1. FirstName should not be empty.

2. LastName length should not be greater than 5.

3. Salary should not be empty.

4. Salary should be a proper number

5. FirstName should not contain “@” symbol


Let’s see how to implement it.

Step 1 – Create JavaScript validation file

Create a JavaScript File called “Validations.js” and keep it inside Scripts folder

Step 2 – Create Validation functions

In “Validations.js” file create validation functions as follows

Hide Shrink Copy Code


function IsFirstNameEmpty() {
if (document.getElementById('TxtFName').value == "") {
return 'First Name should not be empty';
}
else { return ""; }
}

function IsFirstNameInValid() {
if (document.getElementById('TxtFName').value.indexOf("@") != -1) {
return 'First Name should not contain @';
}
else { return ""; }
}
function IsLastNameInValid() {
if (document.getElementById('TxtLName').value.length>=5) {
return 'Last Name should not contain more than 5 character';
}
else { return ""; }
}
function IsSalaryEmpty() {
if (document.getElementById('TxtSalary').value=="") {
return 'Salary should not be empty';
}
else { return ""; }
}
function IsSalaryInValid() {
if (isNaN(document.getElementById('TxtSalary').value)) {
return 'Enter valid salary';
}
else { return ""; }
}
function IsValid() {

var FirstNameEmptyMessage = IsFirstNameEmpty();


var FirstNameInValidMessage = IsFirstNameInValid();
var LastNameInValidMessage = IsLastNameInValid();
var SalaryEmptyMessage = IsSalaryEmpty();
var SalaryInvalidMessage = IsSalaryInValid();

var FinalErrorMessage = "Errors:";


if (FirstNameEmptyMessage != "")
FinalErrorMessage += "\n" + FirstNameEmptyMessage;
if (FirstNameInValidMessage != "")
FinalErrorMessage += "\n" + FirstNameInValidMessage;
if (LastNameInValidMessage != "")
FinalErrorMessage += "\n" + LastNameInValidMessage;
if (SalaryEmptyMessage != "")
FinalErrorMessage += "\n" + SalaryEmptyMessage;
if (SalaryInvalidMessage != "")
FinalErrorMessage += "\n" + SalaryInvalidMessage;

if (FinalErrorMessage != "Errors:") {
alert(FinalErrorMessage);
return false;
}
else {
return true;
}
}

Step 3 - Include Validation file in View

Simple put a reference of “Validations.js” file in the head section of “CreateEmployee” view as
follows.

Hide Copy Code


<script src="~/Scripts/Validations.js"></script>

Step 4 – Attach validations


Simply invoke IsValid function on SaveEmployee button click as follows.

Hide Copy Code


<input type="submit" name="BtnSubmit" value="Save Employee" onclick="return
IsValid();" />

Step 5 – Execute and Test

Press F5 and execute the application

Navigate to the AddNew screen by clicking “Add New” link.

Test 1

Test 2

Talk on Lab 16

Why return keyword is required in onclick of SaveEmployee button click?

As we discussed in Lab 9, submit button will make a request to server when clicked. There is no
point on making server request when validation fails. By writing “return false” in the onclick of
submit button, we can stop the default server request.
In our case IsValid function will return false when validation fails and thus we achieve desired
functionality.

Instead of alert can we show the error messages in the page itself?

Yes we can. Simply create a span tag for each error. Make it invisible (using css) in the beginning
and on submit button click if validation fails make it visible using JavaScript.

Is there any way to get this client side validation automatically?

Yes, when we use HTML helpers we get automatic client side validation based on server side
validation. We will discuss this in one of the future lab

Does server side validation is required anymore?

Yes, In case someone disables JavaScript, Server side validation keep everything in place.

Lab 17 – Adding Authentication

In this lab we will make our GetView action method secured. We will make sure that only valid
user will be able to access the action method.

In the Day 1 of this series we understood the real meaning of word ASP.NET and MVC. We
understood that ASP.NET MVC is part of ASP.NET. Most of the features of ASP.NET are
inherited in ASP.NET MVC. One of the feature is Forms Authentication.

Before we start with lab first let’s understand how Forms Authentication works in ASP.NET

1. End user make a request to Forms authentication enabled application with the help of browser.

2. Browser will send all the associated cookies stored in the client machine with request.

3. When request is received as server end, server examines the request and check for the special
cookie called “Authentication Cookie”.

4. If valid authentication cookie is found, server confirms the identity of the user or in simple
words, consider user as a valid user and make him go further.

5. If valid authentication cookie is not found server considers user as anonymous (or
unauthenticated) user. In this case if the requested resource is marked as protected/secured
user will be redirected to login page.

Step 1 – Create AuthenticationController and Login action method.

Right click controller folder and Select “Add New Controller” and create a controller called
“Authentication”. In this case full class name will be “AuthenticationController”.
Inside controller create and Action method called Login as follows.

Hide Copy Code


public class AuthenticationController : Controller
{
// GET: Authentication
public ActionResult Login()
{
return View();
}
}

Step 2 – Create Model

Create new Model class called UserDetails inside Models folder as follows.

Hide Copy Code


namespace WebApplication1.Models
{
public class UserDetails
{
public string UserName { get; set; }
public string Password { get; set; }
}
}

Step 3 – Create Login View

Crete a new view called Login inside “~/Views/Authentication” folder. Make it a strongly typed
view of type UserDetails.

Put following HTML inside View

Hide Shrink Copy Code


@model WebApplication1.Models.UserDetails

@{

Layout = null;

<!DOCTYPE html>

<html>

<head>

<meta name="viewport" content="width=device-width" />

<title>Login</title>

</head>
<body>

<div>

@using (Html.BeginForm("DoLogin", "Authentication", FormMethod.Post))

@Html.LabelFor(c=>c.UserName)

@Html.TextBoxFor(x=>x.UserName)

<br />

@Html.LabelFor(c => c.Password)

@Html.PasswordFor(x => x.Password)

<br />

<input type="submit" name="BtnSubmit" value="Login" />

</div>

</body>

</html>

As you can see, this time for generating View instead of Pure HTML we are using HtmlHelper
class.

 In view we will get a readymade object of HtmlHelper class called “Html”

 HtmlHelper class functions simply returns html string.

Example 1:

Hide Copy Code


@Html.TextBoxFor(x=>x.UserName)

Above code will generate following HTML.

Hide Copy Code


<input id="UserName" name="UserName" type="text" value="" />

Example 2:
Hide Copy Code
@using (Html.BeginForm("DoLogin", "Authentication", FormMethod.Post))
{
}

Above code will generate following HTML.

Hide Copy Code


<form action="/Authentication/DoLogin" method="post">
</form>

<form action="/Authentication/DoLogin" method="post"> <

Step 4 – Execute and Test

Press F5 and execute the application. In the address put the URL of Login action method. In my
case it will be“http://localhost:8870/Authentication/Login”.

Step 5 – Enable Forms Authentication

Open Web.config file. Navigate to System.Web section. Find a child section called
Authentication. If it won’t exist create it. Set Authentication mode to Forms and Login URL to
“Login” action method created in step 1.

Hide Copy Code


<authentication mode="Forms">
<forms loginurl="~/Authentication/Login"></forms>
</authentication>

Step 6 – Make action method secured.

Open EmployeeController and attach Authorize attribute to Index action as follows.

Hide Copy Code


[Authorize]
public ActionResult Index()
{
EmployeeListViewModel employeeListViewModel = new EmployeeListViewModel();
......

Step 7 – Execute and Test

Press F5 and execute the application. In the address bar put URL of Index action
ofEmployeeController. In my case it will be “http://localhost:8870/Employee/Index”.

As you can see, request to Index action automatically redirected to login action.

Step 8 – Create business layer functionality

Open EmployeeBusinessLayer class and create a method called IsValidUser as follows.

Hide Copy Code


public bool IsValidUser(UserDetails u)
{
if (u.UserName == "Admin" && u.Password == "Admin")
{
return true;
}
else
{
return false;
}
}

Note: In business layer we are comparing username and password with hardcoded values. In real
time we can make call to Database layer and compare it with real time values.

Step 9 – Create DoLogin Action method


Open AuthenticationController class and create a new action method called DoLogin.

This DoLogin action method will be invoked when Login button in Login view is clicked (Check
Step 3).

Now let’s list down the points need to be done in DoLogin

1. Check for validity of user by invoking business layer function.

2. If user is a valid user create an authentication cookie. It makes futures requests authenticated
request.

3. If user is invalid, add a new error to current ModelState. This error will be displayed in View.

Hide Copy Code


[HttpPost]
public ActionResult DoLogin(UserDetails u)
{
EmployeeBusinessLayer bal = new EmployeeBusinessLayer();
if (bal.IsValidUser(u))
{
FormsAuthentication.SetAuthCookie(u.UserName, false);
return RedirectToAction("Index", "Employee");
}
else
{
ModelState.AddModelError("CredentialError", "Invalid Username or
Password");
return View("Login");
}
}

Let’s understand the above code block.

 If you remember in “Day 3 – Lab 13” we spoke about ModelState and understood that it
encapsulates current state of the model. It contains all the errors related to current model. In
above code snippet we are adding a new error when user is an invalid user (new error with key
“CredentialError” and message “Invalid Username or Password”).

 FormsAuthentication.SetAuthCookie will create a new cookie in client’s machine.

Step 10 – Display message in view

Open Login View and add following code just above the @Html.BeginForm

Hide Copy Code


@Html.ValidationMessage("CredentialError", new {style="color:red;" })
@using (Html.BeginForm("DoLogin", "Authentication", FormMethod.Post))
{

Step 11 – Execute and Test


Press F5 and execute the application. Directly make a request to Login Action. I believe you
know how to do it now.

Note: If you want you can make request to Index action of EmployeeController but it ultimately
redirect you to Login Action.

Test 1

Test 2
Talk on Lab 17

Why DoLogin is attached with HttpPost attribute?

This attribute makes DoLogin action method open for only Post request. If someone try to make
a get request to DoLogin it won’twork out.
Do we have more such attributes?

Yes. We have HttpGet,HttpPut and HttpDelete. As a best practice every action method must be
attached with such attributes.

Note: To keep coding and learning simple and easy we have not followed such practice
everywhere in this series but I recommend you to strictly follow it in your project.

As we move along we will keep on talking about such best practices.

Is it must to write FormsAuthentication.SetAuthCookie?

Yes.

Let’s understand a small process.

 Client make a first request to server with the help of browser.

 When request is made via browser, all the associated cookies will be sent with the request.

 Server receives the request and prepares the response.

 Now as we know request-response happens via HTTP protocol and HTTP is a stateless protocol.
For server every request will be a new request hence when the same client makes second
request server won’t recognize it. To solve this issue Server will add a cookie in the prepared
response and send back.

 When client’s browsers receives the response with cookies, it creates cookies in client’s machine.

 Now if client make a request once again server will recognize him/her because request contains
cookies.

FormsAuthentication.SetAuthCookie will add a special cookie called “Authentication” cookie to


the response.

Does it means FormsAuthentication won’t work without cookies?

No. We have an alternative for it. We can use URI instead of cookies.

Open Web.Config and change “Authentication/Forms” section as follows.

Hide Copy Code


<forms cookieless="UseUri" loginurl="~/Authentication/Login"></forms>

As you can see, now authentication cookie is passed in URL itself.

By default cookieless property is set to “AutoDetect”. It means authentication works via cookies
and in case cookies are not supported URL will do the required work.

What does second parameter of FormsAuthentication.SetAuthCookie do?

It will decide whether we want to create a persistent cookie or not. Non persistent cookies will
get deleted automatically when browser is closed. Persistent cookies wont deleted automatically.
We have to remove it manually either via coding or by using browser settings.
How to do logout via coding?

We will learn it in one of the future lab.

How come the UserName textbox is repopulated when credentials are wrong?

That’s the magic of HTML helper classes. They will repopulate the values in the controls from
the posted data. This is one of the advantage of using Helper classes.

What does @Html.ValidationMessage does?

We already discussed it in Lab 13 talks. It displays ModelState error based on key.

What does Authorize attribute do?

In Asp.net MVC there is a concept called Filters. Which will be used to filter out requests and
response. There are four kind of filters. We will discuss each one of them in our 7 daysjourney.
Authorize attribute falls under Authorization filter. It will make sure that only authenticated
requests are allowed for an action method.

Can we attach both HttpPost and Authorize attribute to same action method?

Yes we can.

Why there is no ViewModel in this example?

As per the discussion we had in Lab 6, View should not be connected to Model directly. We must
always have ViewModel in between View and Model. It doesn’t matter if view is a simple
“display view” or “data entry view”, it should always connected to ViewModel. Reason for not
using ViewModel in our project is simplicity. In real time project I strongly recommend you to
have ViewModel everywhere.

Is it required to attach Authorize attribute to each and every action method?

No. We can attach it Controller level or Global level also. When attached at controller level, it
will be applicable for all the action methods in a controller. When attached at Global level, it will
be applicable for all the action method in all the controllers.

Controller Level

Hide Copy Code


[Authorize]
public class EmployeeController : Controller
{
....

Global level
Step 1 - Open FilterConfig.cs file from App_start folder.

Step 2 - Add one more line RegisterGlobalFilters as follows.

Hide Copy Code


public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());//Old line
filters.Add(new AuthorizeAttribute());//New Line
}

Step 3 - Attach AllowAnonymous attribute to Authentication controller.

Hide Copy Code


[AllowAnonymous]
public class AuthenticationController : Controller
{

Step 4 – Execute and Test the application in the same way we did before.

What does filters.Add(new HandleErrorAttribute()) does?

We will discuss this in detail in future lab.

Why AllowAnonymous attribute is required for AuthenticationController?

We have attached Authorize filter at global level. That means now everything is protected
including Login and DoLogin action methods. AllowAnonymous opens action method for non-
authenticated requests.

How come this RegisterGlobalFilters method inside FilterConfig class invoked?

It was invoked in Application_Startevent written inside Global.asax file.

Lab 18 – Display UserName in the view.

In this lab we will display currently logged in User Name in View.

Step 1 – Add UserName in ViewModel

Open EmployeeListViewModel and add a new property called UserName as follows.

Hide Copy Code


public class EmployeeListViewModel
{
public List<EmployeeViewModel><employeeviewmodel> Employees { get; set; }
public string UserName { get; set; }
}
</employeeviewmodel>
Step 2 – Set value to ViewModel UserName

Open EmployeeController and change Index as follows

Hide Copy Code


public ActionResult Index()
{
EmployeeListViewModel employeeListViewModel = new EmployeeListViewModel();
employeeListViewModel.UserName = User.Identity.Name; //New Line
......

Step 3 – Display UserName in View

Open Index.cshtml view and display UserName as follows.

Hide Copy Code


<body>

<div style="text-align:right"> Hello, @Model.UserName </div>

<hr />

<a href="/Employee/AddNew">Add New</a>

<div>

<table border="1"><span style="font-size: 9pt;">


</span>
Step 4 – Execute and Test

Press F5 and execute the application. Complete the login process and you will get to see
following output.

Lab 19 – Implement Logout


Step 1 – Create Logout link

Open Index.cshtml and create Logout link as follows.


Hide Copy Code
<body>

<div style="text-align:right">Hello, @Model.UserName

<a href="/Authentication/Logout">Logout</a></div>

<hr />

<a href="/Employee/AddNew">Add New</a>

<div>

<table border="1">

Step 2 – Create Logout Action method.

Open AuthenticationController and add new action method called Logout as follows.

Hide Copy Code


public ActionResult Logout()
{
FormsAuthentication.SignOut();
return RedirectToAction("Login");
}

Step 3 – Execute and Test

Press F5 and execute the application


Lab 20 – Implementing validation in Login Page

Step 1 – Add data annotations

Open UserDetails.cs and add Data Annotation as follows.

Hide Copy Code


public class UserDetails
{

[StringLength(7,MinimumLength=2, ErrorMessage = "UserName length should be


between 2 and 7")]
public string UserName { get; set; }
public string Password { get; set; }
}

Step 2 – Display error messages in view

Change Login.cshtml to display error messages.

Hide Copy Code


@using (Html.BeginForm("DoLogin", "Authentication", FormMethod.Post))
{
@Html.LabelFor(c=>c.UserName)
@Html.TextBoxFor(x=>x.UserName)
@Html.ValidationMessageFor(x=>x.UserName)
......
Note: This time instead of Html.ValidationMessage we have used Html.ValidationMessageFor.
Both will do same thing. Html.ValidationMessageFor can be used only when the view is strongly
typed view.

Step 3 – Change DoLogin

Change DoLogin action method as follows

Hide Copy Code


[HttpPost]
public ActionResult DoLogin(UserDetails u)
{
if (ModelState.IsValid)
{
EmployeeBusinessLayer bal = new EmployeeBusinessLayer();
if (bal.IsValidUser(u))
{
FormsAuthentication.SetAuthCookie(u.UserName, false);
return RedirectToAction("Index", "Employee");
}
else
{
ModelState.AddModelError("CredentialError", "Invalid Username or
Password");
return View("Login");
}
}
else
{
return View("Login");
}
}

Step 4- Execute and Test

Press F5 and execute the application.


Lab 21 – Implementing Client side validation in Login Page

This time we will do client side validation in a different way.

Step 1 – Download jQuery unobtrusive Validation files.

Right click the project. Select “Manage Nuget packages”.

Click on online and search for “jQuery Unobtrusive”.

Install “Microsoft jQuery Unobtrusive Valiadtion

Step 2 – Include jQuery Validation files in View

Above steps adds three JavaScript files in Scripts folder.


 jQuery-Someversion.js

 jQuery.valiadte.js

 jquery.validate.unobtrusive

Open Login.cshtml and in head section include all three js files (in same sequence)/

Hide Copy Code


<script src="~/Scripts/jquery-1.8.0.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>

Step 3 – Execute and Test.

Press F5 and execute the application.

Talk on Lab 21

How come client side validation is implemented?


As you can see, without much effort client side validation is implemented. In Login view, HTML
elements are generated using HTML helper classes. Helper functions while generating HTML
markup attach some attributes based on the data annotation attributes used.

Example:

Hide Copy Code


@Html.TextBoxFor(x=>x.UserName)
@Html.ValidationMessageFor(x=>x.UserName)

Above code will generate following HTML.

Hide Copy Code


<input data-val="true" data-val-length="UserName length should be between 2
and 7" data-val-length-max="7" data-val-length-min="2" id="UserName"
name="UserName" type="text" value="" />
<span class="field-validation-error" data-valmsg-for="UserName" data-valmsg-
replace="true"> </span>

These custom HTML attributes will be used by “jQuery Unobtrusive validation files” and thus
validation get implemented at client side automatically.

Automatic client side validation is the second advantage of Html helper classes.

What is unobtrusive JavaScript means?

This is what Wikipedia says about it.

Unobtrusive JavaScript is a general approach to the use of JavaScript in web pages. Though the term is
not formally defined, its basic principles are generally understood to include:

 Separation of functionality (the "behaviour layer") from a Web page's structure/content and
presentation

 Best practices to avoid the problems of traditional JavaScript programming (such as browser
inconsistencies and lack of scalability)

 Progressive enhancement to support user agents that may not support advanced JavaScript
functionality

Let me define it in layman terms.

“Write your JavaScript in such way that, JavaScript won’t be tightly connected to HTML.
JavaScript may access DOM elements, JavaScript may manipulate DOM elements but won’t
directly connected to it.”

In the above example, jQuery Unobtrusive JavaScript simply used some input element attributes
and implemented client side validation.
Can we use these JavaScript validation without HTML helper classes?

Yes, for that we have to manually attach such attributes to elements.

What is more preferred, Html helper functions or pure HTML?

I personally prefer pure HTML because Html helper functions once again take “full control over
HTML” away from us and we already discussed the problems with that.

Secondly let’s talk about a project where instead of jQuery some other JavaScript
frameworks/librariesare used. Some other framework like angular. In that case mostly we think
about angular validation and in that case these custom HTML validation attributes will go invain.

Conclusion

Here we complete our day 4. In Day 5 we will have more advanced stuff and more fun.

Connect us on Facebook, LinkedIn or twitter to stay updated about new releases.

For Offline Technical trainings in Mumbai visit StepByStepSchools.Net For Online Trainings
visit JustCompile.com or www.Sukesh-Marla.com

In case you want to start with MVC 5 start with the below video Learn MVC 5 in 2 days.
Learn MVC Project in 7 days - Day 5
Introduction

Welcome to day 5 of “Learn MVC Project in 7 days” series. Hope you had a nice time reading
day 1 to day 4. Completing previous days is must prior to day 5.

Complete Series

 Day 1

 Day 2

 Day 3

 Day 4

 Day 5

 Day 6

 Day 7

 Bonus Day 1

 Bonus Day 2

Agenda
Lab 22 - Add Footer
Talk on Lab 22
Lab 23 – Implementing Role based security
Part 1
Part 2
Talk on Lab 23
Lab 24 - Assignment Lab – Handle CSRF attack
Lab 25 – Implement Consistent look across project
Talk on Lab 25
Lab 26 – Making Header and FooterData code more efficient with Action Filter
Conclusion

Lab 22 - Add Footer

In this lab we will add Footer to our Employee Screen.

Main objective of this lab is understanding Partial Views.


What are “Partial Views”?

Logically, Partial View is a reusable view which will never get displayed directly. It will be
included inside other views and get displayed as a part of that view. It resembles user controls in
Asp.Net web forms, but without Code behind.

Step 1 – Create ViewModel for Partial View

Right click the ViewModel folder and create a class called FooterViewModel as follows.

Hide Copy Code


public class FooterViewModel
{
public string CompanyName { get; set; }
public string Year { get; set; }
}

Step 2 – Create Partial View

Right click the “~/Views/Shared” folder. Select Add>>View.

Put View name as Footer, Check “Create as a partial view” checkbox and click “Add”.

Note: We already spoke about shared folder in Day 1. Shared folder contains views which will
not be specific to a particular controller. Views inside Shared folder will be available to all the
controllers.

Step 3 – Display data in the Partial View

Open Footer.cshtml and put following HTML in it.

Hide Copy Code


@using WebApplication1.ViewModels

@model FooterViewModel
<div style="text-align:right;background-color: silver;color: darkcyan;border:
1px solid gray;margin-top:2px;padding-right:10px;">

@Model.CompanyName &copy; @Model.Year

</div>

Step 3 – Include Footer data in Main ViewModel

Open EmployeeListViewModel class and add a new property to hold Footer data as follows.

Hide Copy Code


public class EmployeeListViewModel
{
public List<EmployeeViewModel> Employees { get; set; }

public string UserName { get; set; }

public FooterViewModel FooterData { get; set; }//New Property


}

In our example Footer (Partial View) is going to be displayed as a part of Index View.

We will pass necessary data to Footer from Index View.

Index View is a strongly typed view of type EmployeeListViewModel and hence all the data
required for Footer view should be encapsulated in EmployeeListViewModel.

Step 4 – Set Footer Data

Open EmployeeController and in Index action method set value to FooterData property as
follows.

Hide Copy Code


public ActionResult Index()
{
...
...
employeeListViewModel.FooterData = new FooterViewModel();
employeeListViewModel.FooterData.CompanyName = "StepByStepSchools";//Can
be set to dynamic value
employeeListViewModel.FooterData.Year = DateTime.Now.Year.ToString();
return View("Index", employeeListViewModel);
}

Step 5 – Display Footer

Open Index.cshtml and display Footer Partial View after table tag as follows.

Hide Copy Code


</table>
@{
Html.RenderPartial("Footer", Model.FooterData);
}
</div>
</body>
</html>

Step 6 – Execute and Test

Press F5. Navigate to Index view. (I believe, you know how to do it now.)

Talk on Lab 22

What does Html.Partial do?

Just like Html.RenderPartial, Html.Partial will be used to display Partial View in the View.

This is the syntax

Hide Copy Code


@Html.Partial("Footer", Model.FooterData);

Syntax is much simpler than earlier one.

What’s the difference between two?

Html.RenderPartial will write result of the Partial View directly to the HTTP response stream
whereas Html.Partial will return result as MvcHtmlString.

What is MvcHtmlString and why does Html.Partial return MvcHtmlString instead of


string?
First let’s understand what is MvcHtmlString?

As per MSDN “MvcHtmlString represents a HTML-encoded string that should not be encoded
again”.

Let’s make this definition easier.

Look at the following code.

Hide Copy Code


@{
string MyString = "My Simple String";
}
@MyString

It will generate following output

As you can see, razor displayed whole content as it is. Many people might have thought of
seeing a bold string but Razor Html encoded the content before displaying and that’s why instead
of bold string we got pure content.

We use MvcHtmlString when we don’t want razor to do the encoding. MvcHtmlString is an


indication to razor that “string is already encoded, no more encoding is required”.

For example look at the following code.

Hide Copy Code


@{
string MyString = "My Simple String";
}
@MvcHtmlString.Create(MyString)

It will generate following output

Why does Html.Partial return MvcHtmlString instead of string?

We already understood a fact that “razor will always encode strings but it never encodes
MvcHtmlString”. It doesn’t make sense if Partial View contents are considered as pure string
gets displayed as it is. We want it to be considered as a HTML content and for that we have to
stop razor from encoding thus Partial method is designed to return MvcHtmlString.

What is recommended Html.RenderPartial or Html.Partial?


Html.RenderPartial is recommended because it is faster.

When Html.Partial will be preferred?

It is recommended when we want to change the result returned by Partial View before
displaying.

Open Index.cshtml and open Footer code to below code and test.

Hide Copy Code


@{
MvcHtmlString result = Html.Partial ("Footer", Model.FooterData);
string finalResult = result.ToHtmlString().Replace("2015", "20000");
}
@MvcHtmlString.Create(finalResult)

Now footer will look like below.

Why Partial View is placed inside Shared Folder?

Partial Views are meant for reusability hence the best place for them is Shared folder.

Can’t we place Partial Views inside a specific controller folder, like Employee or
Authentication?

We can do that but in that case it won’t be available to only specific controller.

Example: When we keep Partial View inside Employee folder it won’t be available for
AuthenticationController or to Views related to AuthenticationController.

Why definition of Partial View contains word “Logically”?

In definition we have said that Partial View is a reusable view but it won’t get executed by its
own. It has to be placed in some other view and then displayed as a part of the view.

What we said about reusability is completely true but what we said about execution is only true
logically. Technically it’s not a correct statement. We can create an action method which will
return a ViewResult as bellow.

Hide Copy Code


public ActionResult MyFooter()
{
FooterViewModel FooterData = new FooterViewModel();
FooterData.CompanyName = "StepByStepSchools";//Can be set to dynamic value
FooterData.Year = DateTime.Now.Year.ToString();
return View("Footer", FooterData);
}

It will display following output

Although logically it doesn’t make sense, technically it’s possible. Footer.cshtml won’t contain
properly structured HTML. It meant to be displayed as a part of some other view. Hence I said
“Logically it doesn’t make sense”.

Why Partial View is created instead of putting footer contents directly in the view?

Two advantages

1. Reusability – we can reuse the same Partial View in some other View.

2. Code Maintenance – Putting it in a separate file makes it easy to manage and manipulate.

Why Header is not created as Partial View?

As a best practice we must create Partial View for header also but to keep Initial labs simpler we
had kept it inline.

Lab 23 – Implementing Role based security

In this lab we will implement Admin and Non-Admin login feature.

Requirement is very simple.

“Non Admin user won’t be able to create new Employees”.

With this lab we will understand two more topics in MVC.

 Session

 Action Filters

Let’s start with our lab. 1

To make it simple lets break it into 2 parts.

Part 1 – Hide AddNew link from Non-Admin User

Step 1 – Create Enum for identifying UserStatus

Right click the Models folder and select “Add New Item”.
Select “Code File” option from the dialog box.

Put Name as “UserStatus” and click Add.

“Code File” option will create a blank “.cs” file.

Create an enum called UserStatus inside it as follows.

Hide Copy Code


namespace WebApplication1.Models
{
public enum UserStatus
{
AuthenticatedAdmin,
AuthentucatedUser,
NonAuthenticatedUser
}
}

Step 2 – Change business layer functionality

Delete IsValidUser function and create a new function called GetUserValidity as follows.

Hide Copy Code


public UserStatus GetUserValidity(UserDetails u)
{
if (u.UserName == "Admin" && u.Password == "Admin")
{
return UserStatus.AuthenticatedAdmin;
}
else if (u.UserName == "Sukesh" && u.Password == "Sukesh")
{
return UserStatus.AuthentucatedUser;
}
else
{
return UserStatus.NonAuthenticatedUser;
}
}

Step 3 – Change DoLogin action method

Open AuthenticationController and change DoLogin action method as follows.

Hide Shrink Copy Code


[HttpPost]
public ActionResult DoLogin(UserDetails u)
{
if (ModelState.IsValid)
{
EmployeeBusinessLayer bal = new EmployeeBusinessLayer();
//New Code Start
UserStatus status = bal.GetUserValidity(u);
bool IsAdmin = false;
if (status==UserStatus.AuthenticatedAdmin)
{
IsAdmin = true;
}
else if (status == UserStatus.AuthentucatedUser)
{
IsAdmin = false;
}
else
{
ModelState.AddModelError("CredentialError", "Invalid Username or
Password");
return View("Login");
}
FormsAuthentication.SetAuthCookie(u.UserName, false);
Session["IsAdmin"] = IsAdmin;
return RedirectToAction("Index", "Employee");
//New Code End
}
else
{
return View("Login");
}
}

As you can see, we are using session variable for identifying whether the user is a admin user or
non admin user.

Don’t know Session?

Session is the feature of Asp.Net which is reused in Asp.Net MVC.

We use Session variables to hold user related data. Life of session variable is going to be life of a
user. It will be available until current session ends.

Step 4 – Remove Existing AddNew link


Open Index.cshtml view from “~/Views/Employee” folder and remove “Add New” hyperlink
completely.

Hide Copy Code


<!-- Remove following line from Index.cshtml -->

<a href="/Employee/AddNew">Add New</a>

Step 5 – Crete partial view

Right click the “~/Views/Employee” folder and select Add>>View. Set View Name to
“AddNewLink” and make sure to check “Create a partial View” checkbox.

Step 6 – Put contents in Partial View

Simply put following contents inside newly created Partial View.

Hide Copy Code


<a href="/Employee/AddNew">Add New</a>

Step 7 – Create Action Method

Open EmployeeController and create a new action method called “GetAddNewLink” as follows.

Hide Copy Code


public ActionResult GetAddNewLink()
{
if (Convert.ToBoolean(Session["IsAdmin"]))
{
return Partial View("AddNewLink");
}
else
{
return new EmptyResult();
}
}

Step 8 – Display AddNew link

Open Index.html and simply put following code inside it.

Hide Copy Code


<a href="/Authentication/Logout">Logout</a>
</div>
<hr />
@{
Html.RenderAction("GetAddNewLink");
}
<div>
<table border="1">
<tr>

Html.RenderAction executes the Action Method and writes result directly to response stream.

Step 9 – Execute and Test

Press F5 and execute the application.

Test 1

Test 2
Part 2 – Direct URL security

With above logic one thing is guaranteed. Now a Non-Admin User won’t be able to navigate to
AddNew action via hyperlink.

Is it enough?

No, It not enough. What if a Non-Admin user directly try to navigate to AddNew action via
URL.

As you can see in the above example, a Non-Admin user is able to access the AddNew action.

To solve this problem we will use MVC ActionFilters. Action Filters let us add some pre-
processing and post-processing logic to our action methods. In this lab we will look after pre-
processing support of ActionFilters and in coming up lab we will look into post-processing
functionality as well.

Step 1 – Setup Filter.

Create a new folder called Filters in Project and create a new class called AdminFilter.
Step 2 – Create Filter

Upgrade simple AdminFilter class to ActionFilter by inheriting it from ActionFilterAttribute


class as follows.

Hide Copy Code


public class AdminFilter:ActionFilterAttribute
{

Note: To use ActionFilterAttribute you have to put using System.Web.Mvc in the top.

Step 3 – Add Security validation logic

Inside ActionFilter override OnActionExecuting as follows.

Hide Copy Code


public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!Convert.ToBoolean(filterContext.HttpContext.Session["IsAdmin"]))
{
filterContext.Result = new ContentResult()
{
Content="Unauthorized to access specified resource."
};
}
}

Step 4 – Attach Filter

Attach filter to both AddNew and SaveEmployee Action Method as follows.

Hide Copy Code


[AdminFilter]
public ActionResult AddNew()
{
return View("CreateEmployee",new Employee());
}
...
...
[AdminFilter]
public ActionResult SaveEmployee(Employee e, string BtnSubmit)
{
switch (BtnSubmit)
{
case "Save Employee":
if (ModelState.IsValid)
{
EmployeeBusinessLayer empBal = new EmployeeBusinessLayer();
....
....

Step 5 – Execute and Test

Press F5 and execute the application. Login using Non-Admin credentials and try to navigate to
AddNew action method by putting URL of AddNew action.

As you can see, now your Action methods are completely secured.

Note: Whatever strategy and logic we have used in this lab for implementing Role based security
may not be the best solution. You may have some better logic to implement such behaviour. It’s
just one of the way to achieve it.

Talk on Lab 23

Can we invoke GetAddNewLink directly via browser Address bar?

Yes, we already spoke about such behaviour in “Talk on Lab 22” section.

Is it possible to stop direct execution of GetAddNewLink?

For that decorate GetAddNewLink with ChildActionOnly attribute.

Hide Copy Code


[ChildActionOnly]
public ActionResult GetAddNewLink()
{
if (Convert.ToBoolean(Session["IsAdmin"]))
{

What does Html.Action do?

Just like Html.RenderAction, Html.Action will execute the action method and display the result
in View.

This is the syntax

Hide Copy Code


@Html.Action("GetAddNewLink");

Syntax is much simpler than earlier one.

What’s the difference between two?

Html.RenderAction will write result of the action method execution directly to the HTTP
response stream whereas Html.Action will return result as MvcHtmlString.

What is recommended Html.RenderAction or Html.Action?

Html.RenderAction is recommended because it is faster.

When Html.Action will be preferred?

It is recommended when we want to change the result returned by action method execution
before displaying.

What is ActionFilter?

Just like AuthorizationFilter ActionFilter is kind of Filter in Asp.Net MVC. It allows us to add
pre-processing and post-processing logic to action method execution.

Note: After each lab we are trying our best to cover each and every question a developer may
come up. In case you believe some more questions need to be included please free to send your
questions to SukeshMarla@Gmail.com

Lab 24 - Assignment Lab – Handle CSRF attack

From safety point of view we must also handle CSRF attacks to the project. This one I will leave
to you guys.

I recommend you to read this article and implement same to our SaveEmployee action method.

http://www.codeproject.com/Articles/994759/What-is-CSRF-attack-and-how-can-we-prevent-
the-sam
Lab 25 – Implement Consistent look across project

In ASP.NET world consistent layout means MasterPage.

ASP.NET MVC is not different from it. In Razor Master Pages are called as Layout Pages.

Before we go and start with our lab, first let’s discuss what all things we have to place in Layout
Page

1. Header with Welcome Message

2. Footer with Footer Data

Biggest problem?

Data for Footer and Header is passed to view from Controller as a part of ViewModel.

Now the big question is, how data will be passed from View to Layout Page after header and
footer are moved to Layout Page.

Solution – Inheritance

We can simply follow the Object oriented Inheritance principle here. Let’s understand it with a
lab.

Step 1 – Create Base class ViewModel

Create a new ViewModel called BaseViewModel class in ViewModel folder as follows.

Hide Copy Code


public class BaseViewModel
{
public string UserName { get; set; }
public FooterViewModel FooterData { get; set; }//New Property
}

As you can see BaseViewModel encapsulates everything required for Layout Page

Step 2 – Prepare EmployeeListViewModel

Remove UserName and FooterData properties from EmployeeListViewModel class and inherit it
from BaseViewModel.

Hide Copy Code


public class EmployeeListViewModel:BaseViewModel
{
public List<EmployeeViewModel> Employees { get; set; }
}

Step 3 – Create Layout Page

Right click shared folder. Select Add>>MVC 5 Layout Page. Put name as MyLayout and click
ok.

It will create a structure like below.

Hide Copy Code


<!DOCTYPE html>

<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
</head>
<body>
<div>
@RenderBody()
</div>
</body>
</html>

Step 4 – Convert Layout to strongly typed Layout

Simply put following statements in the top of the layout page and make it strongly typed layout.

Hide Copy Code


@using WebApplication1.ViewModels
@model BaseViewModel

Step 5 – Design Layout Page

In the layout page add header, footer and three sections for contents as below.
Hide Copy Code
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>@RenderSection("TitleSection")</title>
@RenderSection("HeaderSection",false)
</head>
<body>
<div style="text-align:right">
Hello, @Model.UserName
<a href="/Authentication/Logout">Logout</a>
</div>
<hr />
<div>
@RenderSection("ContentBody")
</div>
@Html.Partial("Footer",Model.FooterData)
</body>
</html>

As you can see we have created three sections in the layout page. TitleSection, HeaderSection
and ContentBody. Content pages will use these sections for defining appropriate contents.

Note: While defining HeaderSection second parameter is passed. This parameter decides whether
it’s the optional section or compulsory section. False indicates it’s an optional section.

Step 6 – Attach Layout Page to Index View

Open Index.cshtml and in the top you will find following code.

Hide Copy Code


@{
Layout = null;
}

Change it to below code.

Hide Copy Code


@{
Layout = "~/Views/Shared/MyLayout.cshtml";
}

Step 7 – Design Index View

1. Take out Headers and Footers from Index View.

2. Copy remaining contents in the body tag and keep it somewhere

3. Now copy contents of title tag.


4. Remove all the HTML contents from the view. Make sure you just remove HTML, @model and
layout statement shouldn’t be touched.

5. Define TitleSection and Contentbody with the contents copied earlier.

Complete View will look like below.

Hide Shrink Copy Code


@using WebApplication1.ViewModels
@model EmployeeListViewModel
@{
Layout = "~/Views/Shared/MyLayout.cshtml";
}

@section TitleSection{
MyView
}
@section ContentBody{
<div>
@{
Html.RenderAction("GetAddNewLink");
}
<table border="1">
<tr>
<th>Employee Name</th>
<th>Salary</th>
</tr>
@foreach (EmployeeViewModel item in Model.Employees)
{
<tr>
<td>@item.EmployeeName</td>
<td style="background-
color:@item.SalaryColor">@item.Salary</td>
</tr>
}
</table>
</div>
}

As you can see, everything in the view is defined inside some section.

Step 8 – Execute and Test

Press F5 and execute the application. Navigate to Index action.


Step 9 – Attach Layout Page to CreateEmployee View

Open Index.cshtml and in the top you will find following code.

Hide Copy Code


@{
Layout = null;
}

Change it to below code.

Hide Copy Code


@{
Layout = "~/Views/Shared/MyLayout.cshtml";
}

Step 10 – Design CreateEmployee View

Follow the same Step 7 procedure and define sections in CreateEmployee View. This time there
will be one addition. We will also define HeaderSection.

Complete HTML look like below.

Hide Shrink Copy Code


@using WebApplication1.Models
@model Employee
@{
Layout = "~/Views/Shared/MyLayout.cshtml";
}

@section TitleSection{
CreateEmployee
}
@section HeaderSection{
<script src="~/Scripts/Validations.js"></script>
<script>
function ResetForm() {
document.getElementById('TxtFName').value = "";
document.getElementById('TxtLName').value = "";
document.getElementById('TxtSalary').value = "";
}
</script>
}
@section ContentBody{
<div>
<form action="/Employee/SaveEmployee" method="post" id="EmployeeForm">
<table>
<tr>
<td>
First Name:
</td>
<td>
<input type="text" id="TxtFName" name="FirstName"
value="@Model.FirstName" />
</td>
</tr>
<tr>
<td colspan="2" align="right">
@Html.ValidationMessage("FirstName")
</td>
</tr>
<tr>
<td>
Last Name:
</td>
<td>
<input type="text" id="TxtLName" name="LastName"
value="@Model.LastName" />
</td>
</tr>
<tr>
<td colspan="2" align="right">
@Html.ValidationMessage("LastName")
</td>
</tr>

<tr>
<td>
Salary:
</td>
<td>
<input type="text" id="TxtSalary" name="Salary"
value="@Model.Salary" />
</td>
</tr>
<tr>
<td colspan="2" align="right">
@Html.ValidationMessage("Salary")
</td>
</tr>

<tr>
<td colspan="2">

<input type="submit" name="BtnSubmit" value="Save


Employee" onclick="return IsValid();" />
<input type="submit" name="BtnSubmit" value="Cancel" />
<input type="button" name="BtnReset" value="Reset"
onclick="ResetForm();" />
</td>
</tr>
</table>
</div>
}

Step 11 – Execute and Test

Press F5 and execute the application and then try to navigate to AddNew Action via hyperlink.

Index View was a strongly typed view of type EmployeeListViewModel which is a child of
BaseViewModel and that’s why it’s worked. CreateEmployee View is a strongly typed view of
type CreateEmployeeViewModel and it’s not the child of BaseViewModel and hence such error
occurred.

Step 12– Prepare CreateEmployeeViewModel

Inherit CreateEmployeeViewModel from BaseViewModel as follow

Hide Copy Code


public class CreateEmployeeViewModel:BaseViewModel
{
...

Step 13 – Execute and Test

Do the testing once again.


This error looks very different than it is really J

Real reason for such error is, we have not initialized Header and FooterData in AddNew action.

Step 14 – Initialize Header and Footer Data

Change AddNew action method code to following.

Hide Copy Code


public ActionResult AddNew()
{
CreateEmployeeViewModel employeeListViewModel = new
CreateEmployeeViewModel();
employeeListViewModel.FooterData = new FooterViewModel();
employeeListViewModel.FooterData.CompanyName = "StepByStepSchools";//Can
be set to dynamic value
employeeListViewModel.FooterData.Year = DateTime.Now.Year.ToString();
employeeListViewModel.UserName = User.Identity.Name; //New Line
return View("CreateEmployee", employeeListViewModel);
}

Step 15 – Initialize Header and FooterData in SaveEmployee

Do the same thing in SaveEmployee action method.

Hide Copy Code


public ActionResult SaveEmployee(Employee e, string BtnSubmit)
{
switch (BtnSubmit)
{
case "Save Employee":
if (ModelState.IsValid)
{
...
}
else
{
CreateEmployeeViewModel vm = new CreateEmployeeViewModel();
...
vm.FooterData = new FooterViewModel();
vm.FooterData.CompanyName = "StepByStepSchools";//Can be set
to dynamic value
vm.FooterData.Year = DateTime.Now.Year.ToString();
vm.UserName = User.Identity.Name; //New Line
return View("CreateEmployee", vm); // Day 4 Change - Passing e
here
}
case "Cancel":
return RedirectToAction("Index");
}
return new EmptyResult();
}

Step 16 – Execute and Test

Press F5 and execute the application.

Talk on Lab 25

What does RenderBody do?

When we first created in the Layout page it had one razor stamen something like below.

Hide Copy Code


@Html.RenderBody()

Let’s understand what does it do?

In content pages we normally define sections which are declared in the Layout Page.
But a strange thing is, Razor allow us to define some contents outside the section too.

All the non-section contents in content page will be rendered by RenderBody function

Below image explains it better.

Can we have nested layouts?

Yes we can. We can create a layout page which will use some other layout page. Syntax will be
same.

Is it required to specify layout page in each and every view?

You will find a special view called __ViewStart.cshtml inside Views folder. Setting defined
inside this will get applied to all Views.

Example – simply put following code in __ViewStart.cshtml and it will set layout page to all
other views.

Hide Copy Code


@{
Layout = "~/Views/Shared/_Layout.cshtml";
}

Is it required to put Header and FooterData code in each and every Action Method?

No, it’s not required. We can remove this repetition with the help of Action Filter. This is going
to be our next lab.
Is it compulsory to define all the sections in child view?

Yes if section is declared as a required section. Default value will be true.

Hide Copy Code


@RenderSection("HeaderSection",false) // Not required
@RenderSection("HeaderSection",true) // required
@RenderSection("HeaderSection") // required

Lab 26 – Making Header and FooterData code more efficient with Action Filter

In Lab 23 we had seen one advantage of ActionFilter now it’s time for second.

Step 1 – Remove redundant code from Action Methods

Remove Header and FooterData code from Index, AddNew and SaveEmployee methods (in the
Employee Controller).

For the reference, Header Code will look like this

Hide Copy Code


bvm.UserName = HttpContext.Current.User.Identity.Name;

Footer Code will look like this

Hide Copy Code


bvm.FooterData = new FooterViewModel();
bvm.FooterData.CompanyName = "StepByStepSchools";//Can be set to dynamic value
bvm.FooterData.Year = DateTime.Now.Year.ToString();

Step 2 – Create HeaderFooterFilter

Create a new class called HeaderFooterFilter in Filters folder and upgrade it to Action filter by
inheriting it from ActionFilterAttribute class

Step 2 - Upgrade ViewModel

Override OnActionExecuted in HeaderFooterFilter class. In this method get the current view
model and attach Header and Footer Data.

Hide Copy Code


public class HeaderFooterFilter : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
ViewResult v = filterContext.Result as ViewResult;
if(v!=null) // v will null when v is not a ViewResult
{
BaseViewModel bvm = v.Model as BaseViewModel;
if(bvm!=null)//bvm will be null when we want a view without
Header and footer
{
bvm.UserName = HttpContext.Current.User.Identity.Name;
bvm.FooterData = new FooterViewModel();
bvm.FooterData.CompanyName = "StepByStepSchools";//Can
be set to dynamic value
bvm.FooterData.Year = DateTime.Now.Year.ToString();
}
}
}
}

OnActionExecuted will be used to add post processing logic to action method execution.

Step 4 – Attach Filter

Attach HeaderFooterFilter to Index, AddNew and SaveEmployee action methods.

Hide Copy Code


[HeaderFooterFilter]
public ActionResult Index()
{
EmployeeListViewModel employeeListViewModel = new EmployeeListViewModel();
...
}
...
[AdminFilter]
[HeaderFooterFilter]
public ActionResult AddNew()
{
CreateEmployeeViewModel employeeListViewModel = new
CreateEmployeeViewModel();
//employeeListViewModel.FooterData = new FooterViewModel();
//employeeListViewModel.FooterData.CompanyName = "StepByStepSchools";
...
}
...
[AdminFilter]
[HeaderFooterFilter]
public ActionResult SaveEmployee(Employee e, string BtnSubmit)
{
switch (BtnSubmit)
{
...

Step 5 – Execute and Test

Press F5 and execute the application.


Conclusion

Here we complete our day 5. Day 6 will be the toughest and most interesting one. stay tuned J

Your comments, Mails always motivates us do more. Put your thoughts and comments below or
send mail to SukeshMarla@Gmail.com

Connect us on Facebook, LinkedIn or twitter to stay updated about new releases.

For Offline Technical trainings in Mumbai visit StepByStepSchools.Net

For Online Trainings visit JustCompile.com or www.Sukesh-Marla.com

In case you want to start with MVC 5 start with the below video Learn MVC 5 in 2 days.
Learn MVC Project in 7 days - Day 6
Introduction

Welcome to Day 6 of “Learn MVC Project in 7 days” series. Hope you had a nice time reading
Day 1 to Day 5. Completing previous days is must prior to Day 6.

Agenda
Lab 27 – Add Bulk upload option
Talk on Lab 27
Problem in the above solution
Solution
Lab 28 – Solve thread starvation problem
Lab 29 – Exception Handling – Display Custom error page
Talk on Lab 29
Understand limitation in above lab
Lab 30 – Exception Handling – Log Exception
Talk on Lab 30
Routing
Understand RouteTable
Understand ASP.NET MVC request cycle
Lab 31 – Implement User friendly URLs
Talk on Lab 31
Conclusion

Lab 27 – Add Bulk upload option


In this lab we will create an option for uploading multiple employees from a CSV file.

We will learn two new things here.

1. How to use File upload control

2. Asynchronous controllers.

Step 1 – Create FileUploadViewModel

Create a new class called FileUploadViewModel in ViewModels folder as follows.

Hide Copy Code


public class FileUploadViewModel: BaseViewModel
{
public HttpPostedFileBase fileUpload {get; set ;}
}

HttpPostedFileBase will provide the access to the uploadedfile by client.


Step 2 - Create BulkUploadController and Index Action

Create a new controller called BulkUploadController and an action method called Index Action
as follows.

Hide Copy Code


public class BulkUploadController : Controller
{
[HeaderFooterFilter]
[AdminFilter]
public ActionResult Index()
{
return View(new FileUploadViewModel());
}
}

As you can see, Index action is attached with HeaderFooterFilter and AdminFilter attributes.
HeaderFooterFilter makes sure that correct header and footer data is passed to the ViewModel
and AdminFilter restricts access to action method by Non-Admin user.

Step 3 – Create Upload View

Create a view for above action method.

Kindly note that view name should be index.cshtml and should be placed in
“~/Views/BulkUpload” folder.

Step 4 – Design Upload View

Put following contents inside the view.

Hide Copy Code


@using WebApplication1.ViewModels
@model FileUploadViewModel
@{
Layout = "~/Views/Shared/MyLayout.cshtml";
}

@section TitleSection{
Bulk Upload
}
@section ContentBody{
<div>
<a href="/Employee/Index">Back</a>
<form action="/BulkUpload/Upload" method="post"
enctype="multipart/form-data">
Select File : <input type="file" name="fileUpload" value="" />
<input type="submit" name="name" value="Upload" />
</form>
</div>
}
As you can see name of the property in FileUploadViewModel and name of the input
[type="file"] are same. It is “fileUpload”. We spoke on the importance of name attribute in
Model Binder lab. Note: In form tag one additional attribute that is enctype is specified. We will
talk about it in the end of the lab.

Step 5 - Create Business Layer Upload method

Create a new method calledUploadEmployees inEmployeeBusinessLayer as follows.

Hide Copy Code


public void UploadEmployees(List<Employee> employees)
{
SalesERPDAL salesDal = new SalesERPDAL();
salesDal.Employees.AddRange(employees);
salesDal.SaveChanges();
}<employee>
</employee>

Step 6 – Create Upload Action method

Create a new action method called Upload inside BulkUploadController as follows.

Hide Shrink Copy Code


[AdminFilter]
public ActionResult Upload(FileUploadViewModel model)
{
List<Employee> employees = GetEmployees(model);
EmployeeBusinessLayer bal = new EmployeeBusinessLayer();
bal.UploadEmployees(employees);
return RedirectToAction("Index","Employee");
}

private List<Employee> GetEmployees(FileUploadViewModel model)


{
List<Employee> employees = new List<Employee>();
StreamReader csvreader = new StreamReader(model.fileUpload.InputStream);
csvreader.ReadLine(); // Assuming first line is header
while (!csvreader.EndOfStream)
{
var line = csvreader.ReadLine();
var values = line.Split(',');//Values are comma separated
Employee e = new Employee();
e.FirstName = values[0];
e.LastName = values[1];
e.Salary = int.Parse(values[2]);
employees.Add(e);
}
return employees;
}

AdminFilter attached to the Upload Action restrict access to Non-Admin user.

Step 7 – Create a link for BulkUpload


Open AddNewLink.cshtml from “Views/Employee” folder and put a link for BulkUpload as
follows.

Hide Copy Code


<a href="/Employee/AddNew">Add New</a>
&nbsp;
&nbsp;
<a href="/BulkUpload/Index">BulkUpload</a>

Step 8 – Execute and Test

Step 8.1 – Create a sample file for testing

Create a sample file like below and save it somewhere in the computer.

Step 8.2 – Execute and Test

Press F5 and execute the application. Complete the login process and navigate to BulkUpload
option by clicking link.

Select File and Click on Upload.


Note:

In above example we have not applied any client side or server side validation in the View. It
may leads to following error.
“Validation failed for one or more entities. See 'EntityValidationErrors' property for more
details.”

To find the exact cause for the error, simply add a watch with following watch expression when
exception occurs.
((System.Data.Entity.Validation.DbEntityValidationException)
$exception).EntityValidationErrors

The watch expression ‘$exception’ displays any exception thrown in the current context, even if
it has not been caught and assigned to a variable.

Talk on Lab 27

Why don’t we have validations here?

Adding client side and server side validation to this option will be an assignment for readers. I
will give you a hint.

 For Server side validation use Data Annotations.

 For client side either you can leverage data annotation and implement jQuery unobtrusive
validation. Obviously this time you have to set custom data attributes manually because we
don’t have readymade Htmlhelper method for file input.
Note: If you didn’t understood this point, I recommend you to go through “implanting client side
validation in Login view” again.

 For client side validation you can write custom JavaScript and invoke it on button click. This
won’t be much difficult because file input is an input control at the end of the day and its value
can be retrieved inside JavaScript and can be validated.

What is HttpPostedFileBase?
HttpPostedFileBase will provide the access to the file uploaded by client. Model binderwill
update the value of all properties FileUploadViewModel class during post request. Right now we
have only one property inside FileUploadViewModel and Model Binder will set it to file
uploaded by client.

Is it possible to provide multiple file input control?

Yes, we can achieve it in two ways.

1. Create multiple file input controls. Each control must have unique name. Now in
FileUploadViewModel class create a property of type HttpPostedFileBase one for each control.
Each property name should match with the name of one control. Remaining magic will be done
by ModelBinder. ☺

2. Create multiple file input controls. Each control must have same name. Now instead of creating
multiple properties of type HttpPostedFileBase, createone of type List.

Note: Above case is true for all controls. When you have multiple controls with same name
ModelBinder update the property with the value of first control if property is simple parameter.
ModelBinder will put values of each control in a list if property is a list property.

What does enctype="multipart/form-data" will do?

Well this is not a very important thing to know but definitely good to know.

This attribute specifies the encoding type to be used while posting data.

The default value for this attribute is "application/x-www-form-urlencoded"

Example – Our login form will send following post request to the server

Hide Copy Code


POST /Authentication/DoLogin HTTP/1.1
Host: localhost:8870
Connection: keep-alive
Content-Length: 44
Content-Type: application/x-www-form-urlencoded
...
...
UserName=Admin&Passsword=Admin&BtnSubmi=Login

All input values are sent as one part in the form of key/value pair connected via “&”.

Whenenctype="multipart/form-data" attribute is added to form tag, following post request will


be sent to the server.

Hide Copy Code


POST /Authentication/DoLogin HTTP/1.1
Host: localhost:8870
Connection: keep-alive
Content-Length: 452
Content-Type: multipart/form-data; boundary=----
WebKitFormBoundarywHxplIF8cR8KNjeJ
...
...
------WebKitFormBoundary7hciuLuSNglCR8WC
Content-Disposition: form-data; name="UserName"

Admin
------WebKitFormBoundary7hciuLuSNglCR8WC
Content-Disposition: form-data; name="Password"

Admin
------WebKitFormBoundary7hciuLuSNglCR8WC
Content-Disposition: form-data; name="BtnSubmi"

Login
------WebKitFormBoundary7hciuLuSNglCR8WC--

As you can see, form is posted in multiple part. Each part is separated by a boundary defined by
Content-Type and each part contain one value.

encType must be set to “multipart/form-data” if form tag contains file input control.

Note: boundary will be generated randomly every time request is made. You may see some
different boundary.

Why don’t we always set encType to “multipart/form-data”?

When encType is set to “multipart/form-data”, it will do both the things–Post the data and upload
the file. Then why don’t we always set it as “multipart/form-data”.

Answer is, it will also increase the overall size of the request. More size of the request means less
performance. Hence as a best practice we should set it to default that is "application/x-www-
form-urlencoded".

Why we have created ViewModel here?

We had only one control in our View. We can achieve same result by directly adding a parameter
of type HttpPostedFileBase with name fileUpload in Upload action method Instead of creating a
separate ViewModel. Look at the following code.

Hide Copy Code


public ActionResult Upload(HttpPostedFileBase fileUpload)
{
}

Then why we have created a separate class.


Creating ViewModel is a best practice. Controller should always send data to the view in the
form of ViewModel and data sent from view should come to controller as ViewModel.

Problem in the above solution

Did you ever wondered how you get response when you send a request?
Now don’t say, action method receive request and blah blah blah!!! ☺

Although it’s the correct answer I was expecting a little different answer.
My question is what happen in the beginning.

A simple programming rule – everything in a program is executed by a thread even a request.

In case of Asp.net on the webserver .net framework maintains a pool of threads.


Each time a request is sent to the webserver a free thread from the pool is allocated to serve the
request. This thread will be called as worker thread.

Worker thread will be blocked while the request is being processed and cannot serve another
request.

Now let’s say an application receives too many requests and each request will take long time to
get completely processed. In this case we may end up at a point where new request will get into a
state where there will be noworker thread available to serve that request. This is called as Thread
Starvation.

In our case sample file had 2 employee records but in real time it may contain thousands or may
be lacks of records. It means request will take huge amount of time to complete the processing. It
may leads to Thread Starvation.
Solution

Now the request which we had discussed so far is of type synchronous request.

Instead of synchronous if client makesan asynchronous request, problem of thread starvation get
solved.

 In case of asynchronous request as usual worker thread from thread pool get allocated to serve
the request.

 Worker thread initiates the asynchronous operation and returned to thread pool to serve
another request. Asynchronous operation now will be continued by CLR thread.

 Now the problem is, CLR thread can’t return response so once it completes the asynchronous
operation it notifies ASP.NET.

 Webserver again gets a worker thread from thread pool and processes the remaining request
and renders the response.

In this entire scenario two times worker thread is retrieved from thread pool. Now both of them
may be same thread or they may not be.

Now in our example file reading is an I/O bound operation which is not required to be processed
by worker thread. So it’s a best place to convert synchronous requests to asynchronous requests.

Does asynchronous request improves response time?

No, response time will remain same. Here thread will get freed for serving other requests.

Lab 28 – Solve thread starvation problem

In ASP.NET MVC we can convert synchronous requests to asynchronous requests by converting


synchronous action methods to asynchronous action methods.

Step 1 - Create asynchronous Controller

Change base class of UploadController to AsynController from Controller.

Hide Copy Code


{
public class BulkUploadController : AsyncController
{

Step 2 – Convert synchronous action method to asynchronous action method

It can be done easily with the help of two keywords – async and await.

Hide Copy Code


[AdminFilter]
public async Task<ActionResult> Upload(FileUploadViewModel model)
{
int t1 = Thread.CurrentThread.ManagedThreadId;
List<Employee> employees = await Task.Factory.StartNew<List<Employee>>
(() => GetEmployees(model));
int t2 = Thread.CurrentThread.ManagedThreadId;
EmployeeBusinessLayer bal = new EmployeeBusinessLayer();
bal.UploadEmployees(employees);
return RedirectToAction("Index", "Employee");
}<actionresult><employee><list<employee>
</list<employee>

As you can see we are storing thread id in a variable in the beginning and in the end of action
method.

Let’s understand the code.

 When upload button is clicked by the client, new request will be sent to the server.

 Webserver will take a worker thread from thread pool and allocate it to serve the request.

 Worker thread make action method to execute.

 Worker method starts an asynchronous operation with the help of Task.Factory.StartNew


method.

 As you can see action method is marked as asynchronous with the help of async keyword. It will
make sure that worker thread get released as soon as asynchronous operation starts.Now
logically asynchronous operation will continue its execution in the background by a separate CLR
thread.

 Now asynchronous operation call is marked with await keyword. It will make sure that next line
wont executes unless asynchronous operation completes.

 Once Asynchronous operation completes next statement in the action method should execute
and for that again a worker thread is required. Hence webserver will simply take up a new free
worker thread from thread pool and allocate it to serve the remaining request and to render
response.

Step 3 – Execute and Test

Execute the application. Navigate to BulkUpload option.

Now before you do anything more in the output, navigate to code and put a breakpoint at the last
line.

Now select the sample file and click on Upload.


As you can see we have different thread id in the beginning and different in end. Output is going
to be same as previous lab.

Lab 29 – Exception Handling – Display Custom error page

A project will not be considered as a complete project without a proper exception handling.

So far we have spoken about two filters in Asp.Net MVC – Action Filters and Authorization
Filters. Now it’s time for third one – Exception Filters.

What are Exception Filters?

Exception Filters will be used in the same way other filters are used. We will use them as an
attribute.

Steps for using exception filter

 Enable them.

 Apply them as an attribute to an action method or to a controller. We can also apply exception
filter at global level.

What they will do?

Exception filter will take control of the execution and start executing code written inside it
automatically as soon exception occurs inside action method.

Is there any automation?

ASP.NET MVC provides us one readymade Exception Filter called HandeError.


As we said before it will execute when exception occurs in an action method. This filter will find
a view inside “~/Views/[current controller]” or “~/Views/Shared” folder with name “Error” ,
create the ViewResult of that view and return as a response.

Let’s see a demo and understand it better.

In the last lab in our project we have implemented BulkUpload option. Now there is high
possibility of error in the input file.

Step 1 – Create a sample Upload file with Error

Create a sample upload file just like before but this time put some invalid value.

As you can see, Salary is invalid.

Step 2 – Execute and Test for exception

Press F5 and execute the application. Navigate to Bulk Upload Option. Select above file and
click on Upload.

Step 3 – Enable Exception Filters


Exception filters get enabled when custom exception is enabled. To enable Custom Exception,
open web.config file and navigate to System.Web Section. Add a new section for custom errors
as below.

Hide Copy Code


<system.web>
<customErrors mode="On"></customErrors>

Step 4 – Create Error View

In “~/Views/Shared” folder you will find a view called “Error.cshtml”. This file was created as a
part ofMVC template in the beginning only. In case if it is not created ,create it manually.

Hide Copy Code


@{
Layout = null;
}

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Error</title>
</head>
<body>
<hgroup>
<h1>Error.</h1>
<h2>An error occurred while processing your request.</h2>
</hgroup>
</body>
</html>

Step 5 – Attach Exception filter

As we discussed before after we enable exception filter we attach them to action method or to
controller.

Good news.☺ It’s not required to manually attach it.

Open FilterConfig.cs file from App_Start folder. In RegisterGlobalFilters method you will see
that HandleError filter is already attached at global level.

Hide Copy Code


public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());//ExceptionFilter
filters.Add(new AuthorizeAttribute());
}

If required remove global filter and attach it at action or controller level as below.

Hide Copy Code


[AdminFilter]
[HandleError]
public async Task<ActionResult> Upload(FileUploadViewModel model)
{<actionresult>
</actionresult>

It’s not recommended to do it. It’s better to apply at global level.

Step 6 – Execute and Test

Let’s test the application in the same way we did before.

Step 7 – Display Error message in the view

In order to achieve this convert Error view to strongly typed view of type HandleErrorInfo class
and then display error messages in the view.

Hide Copy Code


@model HandleErrorInfo
@{
Layout = null;
}

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Error</title>
</head>
<body>
<hgroup>
<h1>Error.</h1>
<h2>An error occurred while processing your request.</h2>
</hgroup>
Error Message :@Model.Exception.Message<br />
Controller: @Model.ControllerName<br />
Action: @Model.ActionName
</body>
</html>

Step 8 – Execute and Test

Perform the same testing but this time we will get following Error view.

Are we missing something?

Handle error attribute make sure that custom view get displayed whenever exception occurs in an
action method. But Its power is limited to controller and action methods. It will not handle
“Resource not found” error.

Execute the application and put something weird in URL

Step 9 – Create ErrorController as follows


Create a new controller called ErrorController in Controller folder and create an action method
called Index as follows.

Hide Copy Code


public class ErrorController : Controller
{
// GET: Error
public ActionResult Index()
{
Exception e=new Exception("Invalid Controller or/and Action Name");
HandleErrorInfo eInfo = new HandleErrorInfo(e, "Unknown", "Unknown");
return View("Error", eInfo);
}
}

HandleErrorInfo constructor takes 3 arguments – Exception object, controller nameand Action


method Name.

Step 10 – Display Custom Error View on Invalid URL

In web.config define setting for “Resource not found error” as follows.

Hide Copy Code


<system.web>
<customErrors mode="On">
<error statusCode="404" redirect="~/Error/Index"/>
</customErrors>

Step 11 - Make ErrorController accessible to everyone

Apply AllowAnonymous attribute to ErrorController because error controller and index action
should not be bound to an authenticated user. It may be possible that user has entered invalid
URL before login.

Hide Copy Code


[AllowAnonymous]
public class ErrorController : Controller
{

Step 12 - Execute and Test

Execute the application and put some invalid URL in the address bar.
Talk on Lab 29

Is it possible to change the view name?

Yes, it’s not required to keep view name as “Error” always.

In that case we have to specify view name while attaching HandlError filter.

Hide Copy Code


[HandleError(View="MyError")]
Or
filters.Add(new HandleErrorAttribute()
{
View="MyError"
});

Is it possible to get different error view for different exceptions?

Yes, it is possible. In that case we have to apply handle error filter multiple times.

Hide Copy Code


[HandleError(View="DivideError",ExceptionType=typeof(DivideByZeroException))]
[HandleError(View = "NotFiniteError", ExceptionType =
typeof(NotFiniteNumberException))]
[HandleError]

OR

filters.Add(new HandleErrorAttribute()
{
ExceptionType = typeof(DivideByZeroException),
View = "DivideError"
});
filters.Add(new HandleErrorAttribute()
{
ExceptionType = typeof(NotFiniteNumberException),
View = "NotFiniteError"
});
filters.Add(new HandleErrorAttribute());

In above case we are adding Handle Error filter thrice. First two are specific to exception
whereas last one is more general one and it will display Error View for all other exceptions.

Understand limitation in above lab

The only limitation with above lab is we are not logging our exception anywhere.

Lab 30 – Exception Handling – Log Exception

Step 1 – Create Logger class

Create a new Folder called Logger in root location of the project.

Create a new class called FileLogger as follows inside Logger folder.

Hide Copy Code


namespace WebApplication1.Logger
{
public class FileLogger
{
public void LogException(Exception e)
{
File.WriteAllLines("C://Error//" + DateTime.Now.ToString("dd-MM-
yyyy mm hh ss")+".txt",
new string[]
{
"Message:"+e.Message,
"Stacktrace:"+e.StackTrace
});
}
}
}

Step 2 – Create EmployeeExceptionFilter class

Create a new class called EmployeeExceptionFilter inside Filters folder as follows.

Hide Copy Code


namespace WebApplication1.Filters
{
public class EmployeeExceptionFilter
{
}
}

Step 3 - Extend Handle Error to implement Logging

Inherit EmployeeExceptionFilter from HandleErrorAttribute class and override OnException


method as follows.
Hide Copy Code
public class EmployeeExceptionFilter:HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
base.OnException(filterContext);
}
}

Note: Make sure to put using System.Web.MVC in the top.HandleErrorAttribute class exists
inside this namespace.

Step 4 – Define OnException method

Include Exception logging code inside OnException method as follows.

Hide Copy Code


public override void OnException(ExceptionContext filterContext)
{
FileLogger logger = new FileLogger();
logger.LogException(filterContext.Exception);
base.OnException(filterContext);
}

Step 5 – Change Default Exception filter

Open FilterConfig.cs file and remove HandErrorAtrribute and attach the one we created in last
step as follows.

Hide Copy Code


public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
//filters.Add(new HandleErrorAttribute());//ExceptionFilter
filters.Add(new EmployeeExceptionFilter());
filters.Add(new AuthorizeAttribute());
}

Step 6 – Execute and Test

First of all create a folder called “Error” in C drive because that’s the place where error files are
going to be placed.

Note: If required change the path to your desired one.

Press F5 and execute the application. Navigate to Bulk Upload Option. Select above file and
click on Upload.
Output won’t be different this time. We will get a same Error View like before. Only difference
will be this time we will also find an error file created in “C:\\Errors” folder.

Talk on Lab 30

How come Error view is returned as a response when exception occurs?

In above lab we have overridden the OnException method and implemented exception logging
functionality. Now the question is, how come the default handle error filter is still working then?
It’s simple. Check the last line in the OnException method.

Hide Copy Code


base.OnException(filterContext);
It means, let base class OnException do the reaming work and base class OnException will
return ViewResult of the Error View.

Can we return some other result inside OnException?

Yes. Look at the following code.

Hide Copy Code


public override void OnException(ExceptionContext filterContext)
{
FileLogger logger = new FileLogger();
logger.LogException(filterContext.Exception);
//base.OnException(filterContext);
filterContext.ExceptionHandled = true;
filterContext.Result = new ContentResult()
{
Content="Sorry for the Error"
};
}

When we want to return custom response the first thing we should do is, inform MVC engine
that we have handled exception manually so don’t perform the default behaviour that is don’t
display the default error screen. This will be done with following statement.

Hide Copy Code


filterContext.ExceptionHandled = true

You can read more about exception handling in ASP.NET MVC here

Routing

So far we have discussed many concepts, we answered many questions in MVC except one basic
and important one.

“What exactly happens when end user makes a request?”

Well answer is definitely “Action method executes”. But my exact question is how come
controller and action method are identified for a particular URL request.

Before we start with our lab “Implement User Friendly URLs”, first let’s find out answer for
above question. You might be wondering why this topic is coming in the ending. I purposely kept
this topic at near end because I wanted people to know MVC well before understanding
internals.

Understand RouteTable

In Asp.Net MVC there is a concept called RouteTable which will store URL routes for an
application. In simple words it holds a collection defining possible URL patterns of an
application.
By default one route will be added to it as a part of project template. To check it open
Global.asax file. In Application_Start you will find a statement something like below.

Hide Copy Code


RouteConfig.RegisterRoutes(RouteTable.Routes);

You will find RouteConfig.cs file inside App_Start folder which contain following code block.

Hide Copy Code


namespace WebApplication1
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id =
UrlParameter.Optional }
);
}
}
}

As you can see in RegisterRoutes method already one default route is defined with the help of
routes.MapRoute method.

Routes defined inside RegisterRoutes method will be used later in the Asp.Net MVC request
cycle to determine the exact controller and action method to be executed.

If it’s required we can create more than one route using route.MapRoute function. Internally
defining route means creating Route object.

MapRoute function also attach RouteHandler to route object which will be MVCRouteHandler
in case of ASP.NET MVC by default.

Understand ASP.NET MVC request cycle

Before you start let me make you clear that we are not going to explain 100% request cycle here.
We will touch pass only important ones.

Step 1 – UrlRoutingModule

When end user make a request it first pass through UrlRoutingModule Object.
UrlRoutingModule is a HTTP Module.

Step 2 – Routing
UrlRoutingModule will get the first matching Route object from the route table collection. Now
for matching, request URL will be compared with the URL pattern defined in the route.

Following rules will be considered while matching.

 Number of parameters in the requests URL(other than domain name) and in the URL pattern
defined in the route
Example:

 Optional parameters defined in the URL pattern


Example:
 Static parameters defined in the parameter

Step 3 – Create MVC Route Handler

Once the Route object is selected, UrlRoutingModule will obtain MvcRouteHandler object from
Route object.

Step 4 – Create RouteData and RequestContext

UrlRoutingModule object will create RouteData using Route object, which it then uses to create
RequestContext.

RouteData encapsulates information about routes like name of the controller, name of the action
and values of route parameters.

Controller Name

In order to get the controller name from the request URL following simple rule is followed. “In
the URL pattern {controller} is the keyword to identify Controller Name”.

Example:

 When URL pattern is {controller}/{action}/{id} and request URL is


“http://localhost:8870/BulkUpload/Upload/5”, BulkUpload will be name of the controller.

 When URL pattern is {action}/{controller}/{id} and request URL is


“http://localhost:8870/BulkUpload/Upload/5”, Upload will be name of the controller.

Action Method Name

In order to get the action method name from the request URL following simple rule is followed.
“In the URL pattern {action} is the keyword to identify action method Name”.

Example:

 When URL pattern is {controller}/{action}/{id} and request URL is


“http://localhost:8870/BulkUpload/Upload/5”, Upload will be name of the action method.
 When URL pattern is {action}/{controller}/{id} and request URL is
“http://localhost:8870/BulkUpload/Upload/5”, BulkUpload will be name of the action method.

Route Parameters

Basically a URL pattern can contain following four things

1. {controller} -> Identifies controller name

2. {action} -> Identifies actionmethod name.

3. SomeString -> Example – “MyCompany/{controller}/{action}” -> in this pattern “MyCompany”


becomes compulsory string.

4. {Something} -> Example – “{controller}/{action}/{id}” -> In this pattern “id” is the route
parameter. Route parameter can be used to get the value in the URL itself at the time of request.

Look at the following example.

Route pattern - > “{controller}/{action}/{id}”

Request URL ->http://localhost:8870/BulkUpload/Upload/5

Testing 1

Hide Copy Code


public class BulkUploadController : Controller
{
public ActionResult Upload (string id)
{
//value of id will be 5 -> string 5
...
}
}

Testing 2

Hide Copy Code


public class BulkUploadController : Controller
{
public ActionResult Upload (int id)
{
//value of id will be 5 -> int 5
...
}
}

Testing 3

Hide Copy Code


public class BulkUploadController : Controller
{
public ActionResult Upload (string MyId)
{
//value of MyId will be null
...
}
}

Step 5 – Create MVCHandler

MvcRouteHandler will create the instance of MVCHandler passing RequestContext object.

Step 6 – Create Controller instance

MVCHandler will create Controller instance with the help of ControllerFactory (by default it
will be DefaultControllerFactory).

Step 7 – Execute method

MVCHandler will invoke Controller’s execute method. Execute method is defined inside
controller base class.

Step 8 – Invoke Action method

Every controller is associated with a ControllerActionInvoker object. Inside execute method


ControllerActionInvoker object invoke the correct action method.

Step 9 – Execute result.

Action method receives the user input and prepares the appropriate response data and then
executes the result by returning a return type. Now that return type may be ViewResult, may be
RedirectToRoute Result or may be something else.

Now I believe you have good understanding the concept of Routing so let make our Project
URLs more user-friendly with the help of routing.

Lab 31 – Implement User friendly URLs

Step 1 – Redefine RegisterRoutes method

Include additional routes in the RegisterRoutes method as follows.

Hide Copy Code


public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(
name: "Upload",
url: "Employee/BulkUpload",
defaults: new { controller = "BulkUpload", action = "Index" }
);

routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id =
UrlParameter.Optional }
);
}

As you can see now we have more than one route defined.

(Default Route is kept untouched.)

Step 2 – Change URL references

Open AddNewLink.cshtml from “~/Views/Employee” folder and change BulkUpload link as


follows.

Hide Copy Code


&nbsp;
<a href="/Employee/BulkUpload">BulkUpload</a>

Step 3 – Execute and Test

Execute the application and see the magic.

As you can see URL is no more in the form of “Controller/Action”. Rather it is more user
friendly but output is same.

I recommend you to defines some more routes and try some more URLs.
Talk on Lab 31

Does earlier URL work now?

Yes, earlier URL will work too.

Now Index action in the BulkUploadController is accessible from two URLs

1. “http://localhost:8870/Employee/BulkUpload”

2. “http://localhost:8870/BulkUpload/Index”

What is “id” in default route?

We already spoke about it. It’s called Route Parameter. It can be used to get values via URL. It’s
a replacement for Query String.

What is the difference between Route Parameter and Query String?

 Query String have size limitation whereas we can define any number of Route Parameters.

 We cannot add constraints to Query String values but we can add constraints to Route
Parameters.

 Default Value for Route Parameter is possible whereas default value for Query String is not
possible.

 Query String makes URL cluttered whereas Route Parameter keep it clean.

How to apply constraints to Route Parameter?

It can be done with the help of regular expressions.

Example: look at the following route.

Hide Copy Code


routes.MapRoute(
"MyRoute",
"Employee/{EmpId}",
new {controller=" Employee ", action="GetEmployeeById"},
new { EmpId = @"\d+" }
);

Action method will look like below.

Hide Copy Code


public ActionResult GetEmployeeById(int EmpId)
{
...
}

Now when someone make a request with URL “http://..../Employee/1” or


“http://..../Employee/111”, action method will get executed but when someone make a request
with URL “http://..../Employee/Sukesh” he/she will get “Resource Not Found” Error.

Is it a required to keep parameter name in action method same as Route Parameter Name?

Basically a single Route pattern may contain one or more RouteParameters involved in it. To
identify each route parameter independently it is must to keep parameter name in action method
same as Route Parameter Name.

Does sequence while defining custom routes matters?

Yes, it matters. If you remember UrlRoutingModule will take first matching route object.

In the above lab we have defined two routes. One custom route and one default route. Now let
say for an instance default route is defined first and custom route is defined second.

In this case when end user make a request with URL “http://.../Employee/BulkUpload” in the
comparison phase UrlRoutingModule finds that requested URL matches with the default route
pattern and it will consider “Employee” as the controller name and “BulkUpload” as the action
method name.

Hence sequence is very important while defining routes. Most generic route should be kept at the
end.

Is there an easier way to define URL pattern for Action method?

We can use Attribute based routing for that.

Let’s try it.

Step 1 – Enable Attribute based routing.

In RegisterRoutes method keep following line after IgnoreRoute statement.

Hide Copy Code


routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapMvcAttributeRoutes();

routes.MapRoute(
...

Step 2 – Define route pattern for an action method


Simply attach Route attribute to Action method to Index action of EmployeeController as
follows.

Hide Copy Code


[Route("Employee/List")]
public ActionResult Index()
{

Step 3 - Execute and Test

Execute the application and complete login process.

As you can see, we have same output but with different more User Friendly URL.

Can we define Route Parameters with attribute based routing?

Yes, look at the following syntax.

Hide Copy Code


[Route("Employee/List/{id}")]
publicActionResult Index (string id) { ... }

What about the constraints in this case?

It will be easier.

Hide Copy Code


[Route("Employee/List/{id:int}")]

We can have following constraints

1. {x:alpha} – string validation


2. {x:bool} – Boolean validation

3. {x:datetime} – Date Time validation

4. {x:decimal} – Decimal validation

5. {x:double} – 64 bit float point value validation

6. {x:float} – 32 bit float point value validation

7. {x:guid} – GUID validation

8. {x:length(6)} –length validation

9. {x:length(1,20)} – Min and Max length validation

10. {x:long} – 64 int validation

11. {x:max(10)} – Max integer number validation

12. {x:maxlength(10)} – Max length validation

13. {x:min(10)} – Min Integer number validation

14. {x:minlength(10)} – Min length validation

15. {x:range(10,50)} – Integer range validation

16. {x:regex(SomeRegularExpression)} – Regular Expression validation

What does IgnoreRoutes do in RegisterRoutes method?

IgnoreRoutes will be used when we don’t want to use routing for a particular extension. As a part
of MVC template following statement is already written in RegisterRoutes method.

Hide Copy Code


routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

It means if end user make a request with an extension “.axd” then there won’t be any routing
operation. Request will directly reach to physical resource.

We can define our own IgnoreRoute Statement as well.

Conclusion

With Day 6 we have completed our sample MVC project. Hope you have enjoyed the complete
series.
Wait!!! Where is Day 7?

Day 7 will be there my friends. In day 7 we will create a Single Page Application using MVC,
jQuery and Ajax. It will be more fun and more challenge.Stay tuned ☺

Your comments, Mails always motivates us do more. Put your thoughts and comments below or
send mail to SukeshMarla@Gmail.com

Connect us on Facebook, LinkedIn or twitter to stay updated about new releases.


Learn MVC Project in 7 Days – Day 7
Introduction

Its happy day. Finally we are at the last stage of “Learn MVC Project in 7 days” series. I believe
you have enjoyed all the previous days and learned something from it.

Please don’t forget to drop your comments/suggests/feedbacks at the end of the article.

Agenda

 Introduction

 What’s for the last day?

 Lab 32 – Make project organized

o Talk on Lab 32

 Lab 33 – Creating single page application – Part 1 - Setup

o What are Areas?

o Talk on Lab 33

 Lab 34 – Creating single page application – Part 2–Display Employees

 Lab 35 – Creating single page application – Part 3–Create Employee

o What’s next?

o Let’s plan

 Journey to find a solution

 Understand the problem

 Solution – a common data type

 Problem – what about complex data?

 Solution – A common data format standard

 Problem – XML format issues


 Solution - JSON

o Back to our lab

o Talk on Lab 35

 Lab 36 – Creating single page application – Part 4 – Bulk upload

 Conclusion

 Start with MVC 5

Complete Series

 Day 1

 Day 2

 Day 3

 Day 4

 Day 5

 Day 6

 Day 7

 Bonus Day 1

 Bonus Day 2

Lab 32 – Make project organized

This is not actually a lab related to any new functionality. This lab is just to make project more
structured and systematic.

Step 1 - Create solution folders

Right click the solution select Add>>New Solution Folder.


Name the folder as “View And Controller”.

Now repeat the step and create three more similar folders called “Model”, “ViewModel” and
“Data Access Layer”

Step 2 – Create Data Access Layer Project

Right click the Data Access Layer folder and create a new class library project called
“DataAccessLayer”.
Step 3 – Create Business Layer and Business Entities Project

Create two new class library projects inside Model folder and call it “BusinessLayer” and
“BusinessEntities” respectively.

Step 4 – Create ViewModel project

Create a new project class library project inside ViewModel folder and call it ViewModel.

Step 5 – Add references

First right click each project one by one. Select Add>>Reference and select references as below.

1. For DataAccessLayer select BusinessEntities

2. For BusinessLayer select DataAccessLayer and BusinessEntities

3. For MVC WebApplication select BusinessLayer,BusinessEntities, ViewModel

4. For BusinessEntities System.ComponentModel.DataAnnotations

Step 6 – Set project


1. Copy SalesERPDAL.cs from DataAccessLayer folder in the MVC project to newly
created DataAccessLayer class library project.

2. Remove DataAccessLayer folder from MVC (WebApplication1) project.

3. Copy Employee.cs, UserDetails.cs and UserStatus.cs from Model folder inthe MVC
project to newly created BusinessEntities class library project.

4. Copy EmployeeBusinessLayer.cs from Model folder in theMVC project to newly created


BusinessLayer class library project.

5. Remove Model folderfrom MVC project.

6. Copy all the classes from ViewModels folder in the MVC project to newly created
ViewModel class library project.

7. Remove ViewModels folder from MVC project

8. Move MVC project (WebApplication1) to “View And Controller” solution folder.

Step 7 – Build the project

Select Build>>Build Solution from menu bar.

You will get following error messages.


Step 8 – Solve errors

1. Add System.Web reference to ViewModel project

2. Use Nuget manager and Install Entity Framework in the DataAccessLayer and
BusinessLayer project. (If you are getting confused on how to use Nuget Manager then I
recommend you to look into Day 3)

Note: Entity Framework reference is required inside Business Layer because Business
Layer is directly connected to DataAccessLayer. As a proper architecture Business layer
should not be connected to DataAccessLayer directly. We can accomplish this with the
help of Repository pattern. Repository pattern will be completely out of the scope this
series.

3. Remove EntityFramework from MVC project.

 Right click the MVC project and select “Manage Nuget packages” option.

 Select “Installed Packages” in the left section of “Manage Nuget Packages” dialogue box.

 Right side section will display all the packages installed prior. Select EntityFramework
and click uninstall.

Step 9 – Build the solution

You will get following error.


Step 10 – Solve the error

Now we neither have SalesERPDAL reference nor have Entity Framework reference inside
MVC project. Adding those references in not a good practice. As a best practice Controller
should not be connected to Data Access Layer directly.

1. Create a new class called DatabaseSettings with a static method called SetDatabase inside
DataAccessLayer project as follows.

Hide Copy Code


using System.Data.Entity;
using WebApplication1.DataAccessLayer;
namespace DataAccessLayer
{
public class DatabaseSettings
{
public static void SetDatabase()
{
Database.SetInitializer(new
DropCreateDatabaseIfModelChanges<SalesERPDAL>());<saleserpdal>
}
}
}
</saleserpdal>

2. Create a new class called BusinessSettings with a static method called SetBusiness inside
BusinessLayer project as follows.

Hide Copy Code


using DataAccessLayer;

namespace BusinessLayer
{
public class BusinessSettings
{
public static void SetBusiness()
{
DatabaseSettings.SetDatabase();
}
}
}

3. Remove both the erroneous using statements from global.asax and also remove the
Database.SetInitializer statement. Invoke BusinessSettings.SetBusiness function as follows.

Hide Copy Code


using BusinessLayer;
.
.
.
BundleConfig.RegisterBundles(BundleTable.Bundles);
BusinessSettings.SetBusiness();

Build the application. Build will succeed.

Make sure to execute the application once.☻

Talk on Lab 32

What are solution folders?

Solution folders are just logical folders. They won’t actually get created in physical hard drive.
There only purpose will be making solution more systematic.

Lab 33 – Creating single page application – Part 1 - Setup

Now we will not make any changes to our existing controllers and views. We will create fresh
controllers and views for this lab. Reason for taking such step are,

1. Make existing options intact, so that later in the stage you can compare earlier version
and single page version and learn it better.

2. Implement and understand one more concept in Asp.Net MVC called Areas.

As I said for this lab we will create new controllers, views and ViewModels all together from the
scratch.

Only following things will be reused

 Existing Business Layer

 Existing Data Access Layer


 Existing Business entities

 Authentication and Exception filters

 FooterViewModel

 Footer.cshtml

Step 1 – Create a new Area

Right click the project and Select Add>>Area. A dialogue box will popup. Put it as SPA and
select ok.

It will create a new folder structure inside our project as follows.

Obviously Model folder related to the area is not required. Delete it.

What are Areas?

Areas are simply a way to implement modules in Asp.Net MVC project.

Every project is made up of more than one module. Example - Account Module, Customer
Relationship module, Payment gateway module etc.

In traditional application development style we usually use “Folders” to achieve this. We create
more than one folder inside single project. Each folder represents one module. We will keep all
the respective files of respective module in respective folders.
Now custom folders will be a big issue when it comes to Asp.Net MVC.

Let’s say in Asp.Net MVC we will use simple folders for implementing module.

 Now DataAccessLayer, BusinessLayer, BusinessEntities and ViewModels won’t create


any issue. They are simple classes so can be kept anywhere.

 Controllers - We can’t keep it anywhere. It must be kept inside Controller folder. But it is
not going to be big issue because from MVC 4 restriction over controller location was
removed. Now we can keep it wherever we want.

 Views -unfortunately for views it’s not possible. All the views must be placed inside
“~/Views/ControllerName” or “~/Views/Shared” folder.

This is where Areas comes to picture.

Step 2 – Create required ViewModels

Create a new folder called SPA in ViewModel class library project and create a ViewModel
called MainViewModel as follows.

Hide Copy Code


using WebApplication1.ViewModels;
namespace WebApplication1.ViewModels.SPA
{
public class MainViewModel
{
public string UserName { get; set; }
public FooterViewModel FooterData { get; set; }//New Property
}
}

Step 3–Create Index action method

Put following using statement in MainController.

Hide Copy Code


using WebApplication1.ViewModels.SPA;
using OldViewModel=WebApplication1.ViewModels;

Now create a new action method called Index inside MainController as follows.

Hide Copy Code


public ActionResult Index()
{
MainViewModel v = new MainViewModel();
v.UserName = User.Identity.Name;
v.FooterData = new OldViewModel.FooterViewModel();
v.FooterData.CompanyName = "StepByStepSchools";//Can be set to dynamic
value
v.FooterData.Year = DateTime.Now.Year.ToString();
return View("Index", v);
}

As you can see an alias called OldViewModelis added for WebApplication1.ViewModels


namespace. Now instead of writing WebApplication1.ViewModels.ClassName we can simply
write OldViewModel.ClassName.

Not specifying alias name will leads to ambiguity error. Both namesapces
WebApplication1.ViewModels.SPA and WebApplication1.ViewModels have some similar
classes.

Step 4 – Create Index View

Create a view associated with above index method as follows.

Hide Copy Code


@using WebApplication1.ViewModels.SPA
@model MainViewModel
<!DOCTYPE html>

<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Employee Single Page Application</title>

Step 5 – Execute and Test the application

Press F5 and execute the application. Complete the Login process and navigate to index action in
Main Controller.

Talk on Lab 33

Why SPA keyword is required before controller name?

When we add an area to an ASP.NET MVC application, Visual Studio creates a file named
[AreaName]AreaRegistration.cs containing a class that derives from AreaRegistration. This class
defines the AreaName property and the RegisterArea method, which registers the route
information for the new area.
In our case you can find that file with nameSpaArealRegistration.cs and will be located inside
“~/Areas/Spa” folder. RegisterArea method of SpaArealRegistration class contain following
code.

Hide Copy Code


context.MapRoute(
"SPA_default",
"SPA/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);

This is why, when it comes to controllers in the area we put SPA keyword before controller name

How come RegisterArea in SPAAreaRegistration class get invoked?

Open global.asax file. Very first line in Application_Start will be something like below.

Hide Copy Code


AreaRegistration.RegisterAllAreas();

The RegisterAllAreas method finds all types in the application domain that derive from
AreaRegistration and calls each of their RegisterArea methods.

Can we invoke MainController actions without using SPA?

Let’s make this question easy.

Question is will this URL works? “localhost:8870/Main/Index”

Answer is – Yes.

AreaRegistration class creates new route but it won’t remove other routes. Route defined in
RouteConfig class still work correctly. As I said before there is no restriction for controller
location. Hence it will work but output won’t be displayed properly because it won’t be able to
find the view. I suggest you to execute your application once and try it.

Lab 34 – Creating single page application – Part 2–Display Employees

Step 1 – Create ViewModel for displaying existing employees.

Create new ViewModel classes called EmployeeViewModel and EmployeeListViewModel in


SPA folder of ViewModel class library as follows.

Hide Copy Code


namespace WebApplication1.ViewModels.SPA
{
public class EmployeeViewModel
{
public string EmployeeName { get; set; }
public string Salary { get; set; }
public string SalaryColor { get; set; }
}
}
Hide Copy Code
namespace WebApplication1.ViewModels.SPA
{
public class EmployeeListViewModel
{
public List<employeeviewmodel> Employees { get; set; }
}
}
</employeeviewmodel>

Note: Both the ViewModels are exact replica of ViewModel created for Non-Spa application.
Only difference is this time BaseViewModel is not required.

Step 2 – Create EmployeeList Index

Create new action method called EmployeeList inside MainController as follows.

Hide Shrink Copy Code


public ActionResult EmployeeList()
{
EmployeeListViewModel employeeListViewModel = new EmployeeListViewModel();
EmployeeBusinessLayer empBal = new EmployeeBusinessLayer();
List<employee> employees = empBal.GetEmployees();

List<employeeviewmodel> empViewModels = new List<employeeviewmodel>();

foreach (Employee emp in employees)


{
EmployeeViewModel empViewModel = new EmployeeViewModel();
empViewModel.EmployeeName = emp.FirstName + " " + emp.LastName;
empViewModel.Salary = emp.Salary.Value.ToString("C");
if (emp.Salary > 15000)
{
empViewModel.SalaryColor = "yellow";
}
else
{
empViewModel.SalaryColor = "green";
}
empViewModels.Add(empViewModel);
}
employeeListViewModel.Employees = empViewModels;
return View("EmployeeList", employeeListViewModel);
}
</employeeviewmodel>

Note: HeaderFooterFilter is not required.

Step 3 – Create AddNewLink PartialView


Now we cannot use earlier AddNewLink partial view because anchor tags we had over there will
leads to full refresh. Our target is to create a “Single Page Application” hence there shouldn’t be
any full refresh.

Create a new partial view called AddNewLink.cshtml in the “~/Areas/Spa/Views/Main” folder.

Hide Copy Code


<a href="#" onclick="OpenAddNew();">Add New</a>

Step 4 – Create AddNewLink action method

Create a new action method called GetAddNewLink inside MainController as follows.

Hide Copy Code


public ActionResult GetAddNewLink()
{
if (Convert.ToBoolean(Session["IsAdmin"]))
{
return PartialView("AddNewLink");
}
else
{
return new EmptyResult();
}
}

Step 5 - Create EmployeeList View

Create a new partial view called EmployeeList in “~/Areas/Spa/Views/Main” folder.

Hide Copy Code


@using WebApplication1.ViewModels.SPA
@model EmployeeListViewModel
<div>
@{
Html.RenderAction("GetAddNewLink");
}

<table border="1" id="EmployeeTable">


<tr>
<th>Employee Name</th>

Step 6 – Set EmployeeList as initial screen

For this open Index.cshtml located in “~/Areas/Spa/Views/Main” folder and include


EmployeeList action result inside DivOptions div as follows.

Hide Copy Code


...
</div>
Step 7 - Execute and Test

Press F5 and execute the application.

Lab 35 – Creating single page application – Part 3–Create Employee

Step 1–Create AddNew ViewModels

Create a new ViewModel called CreateEmployeeViewModel in SPA folder of ViewModel class


library project as follows.

Hide Copy Code


namespace WebApplication1.ViewModels.SPA
{
public class CreateEmployeeViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Salary { get; set; }
}
}

Step 2 – Create AddNew action method

Put following using statement in MainController

Hide Copy Code


using WebApplication1.Filters;

Now create AddNew action method inside MainController as follows.

Hide Copy Code


[AdminFilter]
public ActionResult AddNew()
{
CreateEmployeeViewModel v = new CreateEmployeeViewModel();
return PartialView("CreateEmployee", v);
}

Step 3 – Create CreateEmployee Partial View

Create a new partial view called CreateEmployee in the “~/Areas/Spa/Views/Main” folder as


follows.

Hide Copy Code


@using WebApplication1.ViewModels.SPA
@model CreateEmployeeViewModel
<div>
<table>
<tr>
<td>
First Name:
</td>

Step 4– Include jQuery UI

Right click Project and select “Manage Nuget Manager”.

Search for “jQuery UI”.


Install jQuery UI.

It will add couple of JavaScript (.js) and Stylesheet (.css) files to the project.

Step 5- Include jQuery UI

Open “~/Areas/Spa/Views/Main/Index.cshtml” and Include jQuery.js,jQueryUI.js and all.cssas


follows. All these files are added as a part of jQuery UI package by Nuget manager.

Hide Copy Code


<head>
<meta name="viewport" content="width=device-width" />
<script src="~/Scripts/jquery-1.8.0.js"></script>
<script src="~/Scripts/jquery-ui-1.11.4.js"></script>
<title>Employee Single Page Application</title>
<link href="~/Content/themes/base/all.css" rel="stylesheet" />
...

Step 6 – Implement OpenAddNew function.

Create a new JavaScript function called OpenAddNew in


“~/Areas/Spa/Views/Main/Index.cshtml” as follows.

Hide Copy Code


<script>
function OpenAddNew() {
$.get("/SPA/Main/AddNew").then
(
function (r) {
$("<div id='DivCreateEmployee'></div>").html(r).
dialog({
width: 'auto', height: 'auto', modal: true, title:
"Create New Employee",
close: function () {
$('#DivCreateEmployee').remove();
}
});
}
);
}
</script>

Step 7– Execute and Test

Press F5 and execute the application.

Complete the login process and navigate to Index action in MainController. Finally click on Add
New hyperlink.

Step 8 –Create ResetForm function

Open CreateEmployee.cshtml view. Create ResetForm function in the top as following.

Hide Copy Code


@model CreateEmployeeViewModel
<script>
function ResetForm() {
document.getElementById('TxtFName').value = "";
document.getElementById('TxtLName').value = "";
document.getElementById('TxtSalary').value = "";
}
</script>

Step 9 –Create CancelSave function

Open CreateEmployee.cshtml view. Create CancelSave function in the top as following.

Hide Copy Code


document.getElementById('TxtSalary').value = "";
}
function CancelSave() {
$('#DivCreateEmployee').dialog('close');
}

What’s next?

Before we continue and follow the step 10 first let’s understand what we are supposed to next.

 End user click the Save Employee button.

 Values in the controls must be validated in client side.

 If all values are valid, all value will be transferred to server side.

 A new employee record must get saved in the database.

 CreateEmployee dialog box must get closed after that

 A grid get updated with new values.

Let’s plan

Validation

For validation we can use the same Validation JavaScript code we used in non-spa version of
project.

Save Employee

We will create a MVC action method to save employee and invoke it using jQuery Ajax.

Transfer of data from client side to server side

Earlier this was handled easily and automatically with the help of Form tag and Submit button.
Now we can’t follow that approach because it will leads to full refresh. Instead of that this time
we are using jQuery Ajax way which will let us invoke Server side MVC action method without
full page refresh.

Now the million dollar question is if call is manual, how data will be transferred from JavaScript
to MVC action method.

Journey to find a solution

Understand the problem


Whether it is JavaScript, .net or any other technology when you hear the word data what comes
to your mind at first place?

Its variables. We use variables to hold data temporarily and after that we may dump it into some
persistent storage like database.

In our case we are working with two technologies – JavaScript and Asp.Net MVC.

JavaScript is a one technology and Asp.Net MVC is another.

They cannot exchange their data or in simple words they cannot exchange their variable directly
with each other.

You may wondering,Why they can’t?

Both of them have variables. Both the technologies support datatypes like float, int and char then
why can’t they send variables directly to each other?

Answer is, they have it but they are not same.

Integer datatype in .Net is not required to be same as Integer datatype in other technology. They
may be different in size or may be in some other attribute.

Take a real time example.

A human being have legs, hands, eyes etc.

A dog also have things in common.

Are they both same? Definitely no. A human eye cannot be replaced with dog eye and vice versa.

Similarly we have concept of variables in all the technologies but they are not same.Repeating
the same sentence again “Integer in .net is different from Integer in Java”

Solution – a common data type

Industry have realized this problem in the past and thought about a datatype which will actually
be same all over. A data type which will have the ability to hold any data, we call it “a most
compatible data type” and that is string datatype.

String data type is all over and it can hold anything.

 We can convert integer data to string type and store it string variable.

 We can convert float data to string type and store it in string variable.

 …
 Any data can be stored in variable of type string.

Ultimate solution is “Every time something need to be sent from technology1 to technolgoy2,
technology1 will convert the data into string type and send it technology2 because there is 100%
surety that technology2 will understand string”.

Now this have become standard in the industry.

Problem – what about complex data?

Problem – what about complex data?

If yes what about complex data?

What if we want to transfer employee information from one technology to another?

In .Net “classes and objects” will be used to represent complex data.

Look at following example

Hide Copy Code


Employee e=new Employee();
e.EmpName= "Sukesh";
e.Address= "Mumbai";

In JavaScript “JavaScript objects” will be used to represent complex data.

Look at following example:

Hide Copy Code


var e={
EmpName= "Sukesh",
Address= "Mumbai"
};
Passing complex data from .Net to other technology means, passing Class Object from .net to
other technology and passing data from JavaScript to other technology means, passing JavaScript
objects from JavaScript to other technologies.

It won’t be possible directly. As per the standard first we will convert data (.Net object or
JavaScript object) to string type and then it will be send.

Solution – A common data format standard

Just like before, industry identified a common standard here. It said there should be a common
everybody should represent their data before they send. This is where XML comes to picture.

Every technology will convert its data to XML formatted string and then send it to another
technology. Just like string, XML is considered as standard format hence every technology know
about it.

Employee object created in above C# code may be represented in XML format as below.

Hide Copy Code


<employee></employee><Employee>
<EmpName>Sukesh</EmpName>
<Address>Mumbai</Address>
</Employee>

So the solution is, “Technology 1 will convert its complex data to string data represented in XML
format and then send that string to Technology2”

Problem – XML format issues

We have following issues with XML format

1. XML format increases the size of the overall string need to be sent.

More size of the string means more time it will take to transfer. It means less performance.

2. Second reason, which is the major reason is, XML is difficult to create and parse.
Let’s talk about it more.

 As I said before, every technology must create XML string based on data and it will send
that XML string across. Now in C# creating XML string from .Net object is easy with the
help of XML Serializers.
But what about JavaScript. In JavaScript there is neither we have concept of serializer nor
do wehave any readymade XML manipulation library. Hence when it comes to sending of
data from JavaScript to other technology we have to manually create XML string from
JavaScript object. Which is a very difficult task.

 When a technology receives data from other technology it is always going to XML
formatted string. Now in C# parsing XML string and creating .Net object out of it is
going to very easy with the help of XML Deserializers.
But what about JavaScript. In JavaScript we neither have XML Deserializers nor have
XML manipulation libraries hence parsing XML string is a very difficult task here.

Solution - JSON

In order to tackle the problems of XML format, industry came up with a new format called
JSON. It’s an abbreviation for “JavaScript Object Notation”.

Employee object created in above C# code may be represented in JSON format as below.

Hide Copy Code


{
EmpName: "Sukesh",
Address: "Mumbai"
}

Data represented in JSON format look like JavaScript object hence this format is named as JSON
(JavaScript Object Notation)

 As you can see its lightweight compared to earlier.

 Readymade functions are available in JavaScript for converting JavaScript object to


JSON formatted string and for parsing JSON formatted string to JavaScript object.

Following code explains creation and parsing of JSON string.

Hide Copy Code


var e={
EmpName= &ldquo;Sukesh&rdquo;,
Address= &ldquo;Mumbai&rdquo;
};
var EmployeeJsonString = JSON.stringify(e);//This EmployeeJsonString will be
send to other technologies.
Hide Copy Code
var EmployeeJsonString=GetFromOtherTechnology();
var e=JSON.parse(EmployeeJsonString);
alert(e.EmpName);
alert(e.Address);

Close dialog

For closing CreateEmployee dialog box we can use jQuery Api.

Update Grid

Grid updating can be done in one of the two ways.

1. With Partial View

a. Create a partial view for grid just like we did for CreateEmployee functionality.

b. Create a div with some id in EmployeeListview and display partial view (grid) inside it.

c. When Save Employee button is clicked get the updated grid in the form of partial view
result and replace the inner HTML of the grid div with new PartialViewResult.

I believe whatever lab we have completed so far will give you a nice idea onhow to achieve this
and hence I am keeping this as an assignment. Complete it and don’t forget to drop a comment
about the experience.

2. With manual code

In this approach MVC action method will return single EmployeeViewModel instead of
EmployeeListViewModel which will be received at JavaScript end and using JavaScript new row
will be inserted into the gridmanually. (EmployeeViewModel will be sent as JSON string from
MVC action method to JavaScript).

Back to our lab

Step 10 – Create SaveEmployee Action

Now create a new action called SaveEmployee in MainController as follows.

Hide Copy Code


[AdminFilter]
public ActionResult SaveEmployee(Employee emp)
{
EmployeeBusinessLayer empBal = new EmployeeBusinessLayer();
empBal.SaveEmployee(emp);

EmployeeViewModel empViewModel = new EmployeeViewModel();


empViewModel.EmployeeName = emp.FirstName + " " + emp.LastName;
empViewModel.Salary = emp.Salary.Value.ToString("C");
if (emp.Salary > 15000)
{
empViewModel.SalaryColor = "yellow";
}
else
{
empViewModel.SalaryColor = "green";
}
return Json(empViewModel);
}

For now just take Json method as a way to send Json String from MVC action method to
JavaScript.

Step 11 – Include Validation.js

Include Validation.js file created in one of the previous lab as follows.

Hide Copy Code


@using WebApplication1.ViewModels.SPA
@model CreateEmployeeViewModel
<script src="~/Scripts/Validations.js"></script>

Step 12–Create SaveEmployee function

Open CreateEmployee.cshtml view. Create SaveEmployee function in the top as follows.

Hide Shrink Copy Code


...
...

function SaveEmployee() {
if (IsValid()) {
var e =
{
FirstName: $('#TxtFName').val(),
LastName: $('#TxtLName').val(),
Salary: $('#TxtSalary').val()
};
$.post("/SPA/Main/SaveEmployee",e).then(
function (r) {
var newTr = $('<tr></tr>');
var nameTD = $('<td></td>');
var salaryTD = $('<td></td>');

nameTD.text(r.EmployeeName);
salaryTD.text(r.Salary);

salaryTD.css("background-color", r.SalaryColor);

newTr.append(nameTD);
newTr.append(salaryTD);
$('#EmployeeTable').append(newTr);
$('#DivCreateEmployee').dialog('close');
}
);
}
}
</script>

Step 13– Execute and Test

Press F5 and execute the application.

Talk on Lab 35

What does JSON method do?

It will return JSONResult.

JSONResult is the one of the child of ActionResult.

In Day 6 we spoke about MVC request cycle. Let go through it again.


ExecuteResult is declared as abstract in ActionResult class. All the children’s of ActionResult
class defines it in its own way. In Day 1 we spoke about ViewResult.In ViewResult class
ExecuteResult method will do following things.

 It will creates the object of ViewPageActivator class.

 It will choose the correct ViewEngine and passes ViewPageActivator object as argument
to ViewEngine’s constructor. ViewEngine create the object of View class

 It will invoke the RenderView method of View which will render final HTML output the
response.

When it comes to JsonResult, ExecuteResult method will,

 Set the response content type to “Application/Json”

 Using JavaScript Serializerit will convert the data passed to JSON formatted string

 Writes the final JSON formatted String to response stream.

Lab 36 – Creating single page application – Part 4 – Bulk upload

Step 1 – Create SpaBulkUploadController

Create a new AsyncController called SpaBulkUploadController

Hide Copy Code


namespace WebApplication1.Areas.SPA.Controllers
{
public class SpaBulkUploadController : AsyncController
{
}
}

Step 2 – Create Index Action

In the above controller create a new action method called Index as follows.

Hide Copy Code


[AdminFilter]
public ActionResult Index()
{
return PartialView("Index");
}

Step 3 – Create Index PartialView

Create a new PartialView called Index inside “~/Areas/Spa/Views/SpaBulkUpload” as follows.

Hide Copy Code


<div>
Select File : <input type="file" name="fileUpload" id="MyFileUploader"
value="" />
<input type="submit" name="name" value="Upload" onclick="Upload();" />
</div>

Step 4 – Create OpenBulkUpload method

Open Index.cshtml in “~/Areas/Spa/Views/Main” folder and create a JavaScript method called


Index.cshtml as follows.

Hide Copy Code


function OpenBulkUpload() {
$.get("/SPA/SpaBulkUpload/Index").then
(
function (r) {
$("<div
id='DivBulkUpload'></div>").html(r).dialog({ width: 'auto', height: 'auto',
modal: true, title: "Create New Employee",
close: function () {
$('#DivBulkUpload').remove();
} });
}
);
}
</script>
</head>
<body>
<div style="text-align:right">

Step 5 – Execute and Test


Press F5 and execute the application. Complete the login Process

Navigate to Index action of Main Controller and click the BulkUpload link.

Step 6 – Create FileUploadViewModel

Create a new view model class called FileUploadViewModel in SPA folder of ViewModel class
library.

Hide Copy Code


namespace WebApplication1.ViewModels.SPA
{
public class FileUploadViewModel
{
public HttpPostedFileBase fileUpload { get; set; }
}
}

Step 7 – Create Upload Action

Create a new Action method called Upload in SpaBulkUploadController as follows.

Hide Shrink Copy Code


[AdminFilter]
public async Task<actionresult> Upload(FileUploadViewModel model)
{
int t1 = Thread.CurrentThread.ManagedThreadId;
List<employee> employees = await Task.Factory.StartNew<list<employee>>
(() => GetEmployees(model));
int t2 = Thread.CurrentThread.ManagedThreadId;
EmployeeBusinessLayer bal = new EmployeeBusinessLayer();
bal.UploadEmployees(employees);
EmployeeListViewModel vm = new EmployeeListViewModel();
vm.Employees = new List<employeeviewmodel>();
foreach (Employee item in employees)
{
EmployeeViewModel evm = new EmployeeViewModel();
evm.EmployeeName = item.FirstName + " " + item.LastName;
evm.Salary = item.Salary.Value.ToString("C");
if (item.Salary > 15000)
{
evm.SalaryColor = "yellow";
}
else
{
evm.SalaryColor = "green";
}
vm.Employees.Add(evm);
}
return Json(vm);
}

private List<employee> GetEmployees(FileUploadViewModel model)


{
List<employee> employees = new List<employee>();
StreamReader csvreader = new StreamReader(model.fileUpload.InputStream);
csvreader.ReadLine();// Assuming first line is header
while (!csvreader.EndOfStream)
{
var line = csvreader.ReadLine();
var values = line.Split(',');//Values are comma separated
Employee e = new Employee();
e.FirstName = values[0];
e.LastName = values[1];
e.Salary = int.Parse(values[2]);
employees.Add(e);
}
return employees;
}
</employee>

As you can see this time instead of redirecting we are returning JsonResult.

Step 8 – Create Upload function

Open Index view in ~/Areas/Spa/Views/SpaBulkUpload” folder.

And create a JavaScript function called Upload as follows.

Hide Shrink Copy Code


<script>
function Upload() {
debugger;
var fd = new FormData();
var file = $('#MyFileUploader')[0];
fd.append("fileUpload", file.files[0]);
$.ajax({
url: "/Spa/SpaBulkUpload/Upload",
type: 'POST',
contentType: false,
processData: false,
data: fd
}).then(function (e) {
debugger;
for (i = 0; i < e.Employees.length; i++)
{
var newTr = $('<tr></tr>');
var nameTD = $('<td></td>');
var salaryTD = $('<td></td>');

nameTD.text(e.Employees[i].EmployeeName);
salaryTD.text(e.Employees[i].Salary);

salaryTD.css("background-color", e.Employees[i].SalaryColor);

newTr.append(nameTD);
newTr.append(salaryTD);

$('#EmployeeTable').append(newTr);
}
$('#DivBulkUpload').dialog('close');
});
}
</script>

Step 9 – Execute and Test

Create a text file for testing as follows.

Press F5 and execute the application.


Conclusion

Here we complete our 7 days of journey. We have completed a simple project using many
features in Asp.Net MVC. We have also discussed about many theoretical concepts in detail.

Soon I will release two more articles on MVC. It won’t be part of the series but it includes
couple of things which didn’t covered in these 7 days as a part of project
 Article 2 – Learn MVC Project in 7 days - Bonus day 1

Here we will create a SPA project again but with the help of Web API and angular

 Article 1 - Learn MVC Project in 7 days – Bonus day 1

Here we will speak about some MVC topics which are not covered in 7 days.

o Bundling and Minification

o Appliaction_Error

o Temp data

o Creating Custom helper classes

o MVC Unit Testing

o MVC dependency resolver


Learn MVC Project in 7 Days – Bonus day 1
Introduction

This article is a continuation article of the series “Learn MVC project in 7 days”.

 In the first 6 articles we have created a completed MVC Project from the scratch.

 In 7th day we have created a Single page version of same project.

 This one is going to be a bonus day for readers. Here we will understand importance of Web API
and angular and see a small demo on both of them.

Note: In this series I am not going to create a complete project using Web API and angular. I am
going to start a new series for that soon. Here we will just cover following three things.

 What and Why Web API?

 Demo on Web API

 What is Angular?

 Demo on angular.

 Demo on Angular with Web API

 Start with MVC 5

I request you to jump to the respective section directly based on your interest.

Complete Series

 Day 1

 Day 2

 Day 3

 Day 4

 Day 5

 Day 6

 Day 7
 Bonus Day 1

 Bonus Day 2

What and Why Web API?

Web API is an Asp.Net technology for creating HTTP based services. Just like Web Forms and
Asp.Net MVC, Web API is a flavour of Asp.Net hence it automatically get many abilities of
Asp.Net like Forms Authentication, Exception handling etc.

Let’s answer couple of questions about Web API. If you are not interested in theory of Web API I
recommend you to directly jump to the lab.

Web API is a third flavour of Asp.Net. Does it mean that, using Web API we create web
applications?

We are very clear about the purpose of Asp.Net. It’s meant for creating web applications.

Web applications are applications which can be accessed via Web. It’s never been sentenced that
“Web Applications must have UI”. They can be just some business applications which exposes
data via web.

Asp.Net Web Forms and Asp.Net MVC are the flavours of Asp.net which caters the UI part. It
will be used to create Web based UI applications.

How Web API is different from Web Services and WCF Services?

Web Service and WCF Service does the same thing. It exposes data to the outside world.

Then how come Web API is different from them?

Short answer is “Web Services and WCF Services are SOAP based services. Here HTTP will be
just used as a transport protocol. Web API is purely HTTP based service. Here there will not be
any SOAP involvement”.

Let’s understand it in detail.

Why WCF and Web Services need SOAP?

In order to understand this let’s talk about a scenario.

We want to send some data from Technology1 to Technology2 where Technology2 is a


WCF/Web Service and Communication must happen via internet/web.

Web means HTTP. HTTP will let us make requests to a particular URL and with that request it
let us pass some data as well.
Now as per the data transmission discussion we had in Day 7, Technology1 will convert its data
to XML string (or JSON string mostly) and then send it to Technology2.

Note: When .Net Web services or WCF services is the point of communication, data will be
always formatted as XML string.

Point’s worth discuss

 When a developer design a service he/she actually creates one or more methods inside service.
Each method is meant for some special functionality. We call it web methods. When it comes to
communication,Technology1 will actually invoke these methods fromthe service. Now in HTTP
we won’t have a provision for specifying method name. The only choice left is, when client sends
request via HTTP,somehow method name will be concatenated to data and will be sent as data
itself.
At service side, Service framework splits data (received from client) into actual data and method
name. Then it invokes the corresponding method in the service passing actual data as an
argument.

 When Technology1 will send data to the service, how come service make sure that data is sent
from valid client. It may be possible that someone who is not allowed to access the service is
tryingto send the data. To solve this problem just like method name solution Technology1 will
concatenate Validation credentials to the data and send them as one. At service side, Service
framework splitsdata (received from client) into Credentials, method name and actual data. It
validates the credentials and make sure that request is an authenticated request before making
web method call.

How Service extracts different parts from incoming data?

Now as per our final discussion, When Technology1 send data to service, data will actually
contain three things – Actual Data, Validation credentials and method name.

At service side it will be very difficult for a service framework to understand each part
independently because Service is a universal thing and it should work for everyone. Secondly
client can send data in any format. Example, client can send complete data in “Data|Credential|
MethodName” format or can send in “Credential|Data|MethodName” format. There is no fixed
format.

Solution - Standard envelop

To tackle this problem industry came up with a standard envelop concept called SOAP envelop.

SOAP is nothing but a specialized XML which will encapsulate everything which need to be sent
but in standard format. HTTP will send SOAP envelop from client to service and vice versa.

Below is the sample SOAP xml for the reference.

Hide Copy Code


<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Body xmlns:m="http://www.example.org/stock">
<m:MyMethodName>
<m:MyData>Data in Json or XML format</m: MyData >
</m: MyMethodName >
</soap:Body>
</soap:Envelope>

Note:

 As I said before when Service is Web Service or WCF service data will be represented as XML
string.

 When a service returns something same steps will be followed. Service will create SOAP XML
stringand client will extract response data from it.

What are the problems with SOAP?

SOAP is XMLat the end of the day, so it causes two issues.

 It increases the overall size of the data hence affects the performance.

 We spoke about complexities of XML in Day 7. We have learned how much difficult it will be for
lightweight frameworks (like JavaScript, Mobile frameworks etc)tocreate and parse XML string.

What will be the solution?

Solution will be pure HTTP based services. Services where there will not be any SOAP envelop.
HTTP will directly transfer data from one location to another. This is where REST principle
comes to picture.

REST says use the existing features of the web in more efficient manner and create services. It
say transfer data in the format they represented instead of putting them in SOAP envelop.
HTTP based services are completely based on REST principle hence they are also called as
REST based services.

What are the existing features of web?

 In web we have a concept of URL which will uniquely identifies a Resource.

 In web different actions will be identified with the help ofdifferent HTTP verbs. Example – HTTP
verb GET means Retrieve data, PUT means update data, POST means create data and DELETE
means Delete the data.

How industry implemented the solution?

Solution for Method Name

Now in case of SOAP based service (Web and WCF service) every service is identified by an
URL. In the same way REST service will be identified with the help of an URL.

Difference will be in case of REST service, the way we defined methods is going to be different.

 Either it will be definedas standard methods. Standard method means method name will be
fixed. It will either GET or POST or PUT or DELETE.

 Or it will define methods with any name but in that case every custom method will have a URL.

In either of the case sending method name as a parameter from client side is not required.

 In case of choice 1, client will make make a request to REST service via HTTP. Type of the request
will be either GET or POST or PUT or DELETE. Now at the service end, service framework will
check the type of request and correspondingly invoke the method in the service. Method name
problem get solved.

 In case of choice 2, client will make a request to RESET service method directly via HTTP. This is
possible because every method is going to have a unique URL.

Solution for security

When we say HTTP, we have a concept of HTTP header and HTTP body both of which have the
ability to carry some information. We can always pass credentials as a part of header and data as
part of body. To make sure that nobody able to see the data in header and body during
transmission we can implement SSL. It make one thing clear, Security will not be an issue.
What about the passing data?

In this case data will passed directly by HTTP in JSON or XML format. Mostly it will be JSON.

How come WCF REST is different from Web API?

WCF Rest was an earlier Microsoft implementation for creating REST based services.

WCF was never meant for REST. Its sole purpose was to support SOA. Creating REST services
using WCF involved too many steps and adding new feature in the future would have been big
issue for Microsoft.

A Non WCF developer will not be able create WCF REST service.

Asp.Net Web APIwill be much simpler and even a Non WCF developer will be able to create
HTTP based service using it.

Demo on Web API

Step 1 - Create a Web API project

Step 1.1 Open Visual studio and Click on File>>New>>Project. Select “Asp.Net Web
Application” from the dialog box, put some name and click Ok.
Step 1.2 Select Empty option,Web API checkbox in the next dialog box and click Ok.

Now before we proceed I would like to talk more about above this dialog box. In Day 1 where
we started our MVC project I purposely skipped the discussion on this dialog box.

Now in future there is not going to be separate Asp.Net MVC, Web API or Web Forms Project.
We have Asp.Netand we will create Asp.Net project.

In a single Asp.Net project at the same time we may have couple of options of type Web Forms
and couple of options of type MVC.
There are two sections in dialog box – Template and References.

Explanation 1

Let’s say we choose Empty template in the beginning.

Now if you want to create a MVC option you have to add couple of references in the project. So
manually right click the project, select add reference, choose System.Web.MVC and click Ok.
Now do the same for some more references.

Instead of that simply check MVC checkbox in the dialog box.

Above two options will create an empty project with all the referencesrequired for Asp.Net MVC
project.

If you believe that your project is also going to contain Web Forms or Web APIsthen simply
check the corresponding checkbox as well.

Explanation 2

Now you might be wondering what the other templates in the dialog box are?

It’s simple. Microsoft believe every project is going to ahve few things common. Like every
project is going to have Login screen, master or layout page, error page etc. Microsoft says
instead developer go and create them manually every time in every project let visual studio
create it automatically. If you take Web Forms template all these common files will be created in
Web Forms style. If you take MVC template all these common files will be create in MVC style.
Step 2 –Create API

Right click the controller folder and select Add>>Controller. This time choose “Web API 2
controller – Empty” option and click Add.

Put name of the controller as EmployeeController and click Add.

You will notice that a new class get created inheriting from ApiController. It’s going to be our
Web API.

Step 3 – Create Model

Create a new class called Employee inside Model folder as follows.

Hide Copy Code


namespace WebAPISample.Models
{
public class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Salary { get; set; }
}
}

Step 4 – Create GET action

Open EmployeeController put using statement as follows.

Hide Copy Code


using WebAPISample.Models;

Now create GET action as follows.

Hide Copy Code


public Employee GET()
{
Employee e = new Employee();
e.FirstName = "Sukesh";
e.LastName = "Marla";
e.Salary = 25000;
return e;
}

Step 5 – Execute and Test

Press F5 and execute the application. Make request to “/api/Employee” from browser.

Note: Above output will be applicable for only chrome browser. We will talk about in detail in
next section.

Talk on Web API Lab

Why Api keyword is specified in the URL?

Open Global.asax file. Application_Start will be defined as follows.

Hide Copy Code


protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
}

In the project, in App_Start folder you will find a file called WebApiConfig.cs. Open it.

It contains following code.

Hide Copy Code


namespace WebAPISample
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();

config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}

As you can see, Web API specific route is defined inside it.

This is the reason why “api” keyword is required.

How come GET method got invoked?

In this case our HTTP service“Employee” is considered as a resource which will be identified by
an URL “http://localhost:somePort/api/Employee”. When HTTP request is sent to this URL, Web
API engine check the type of request. In our case type of request is “Get” hence Web API engine
make Get method got invoked.

How come the request type becomes Get?

In this example we are using browser’s address bar to make the request. Request made by
browsers address bar will always leads to get request.

What about other requests?

In Web API simply create four methods named GET, POST, PUT, DELETE respectively.

Each method will depict one request type.

Now from a testing point of view GET method can be tested easily via browser’s address bar but
POST, PUT, DELETE cannot be directly requested via browser.Wehave to use some tool or
some UI which will does that for us with the help of some coding.

We are going to have a practical lab on same soon.

What if we want to define custom methods?

In real time scenario we always want to create more than one kind of Get/post/put/delete
functions. Example – GetCustomers, GetCustomerById, GetCustomerByDepartment.

In that case we have to define multiple routes or we have to change the default route.

Look at the following example.


Hide Copy Code
config.Routes.MapHttpRoute(
name: "SecondRoute",
routeTemplate: "api/GetCustomerById/{id} ",
defaults: new {controller= &ldquo;Customer&rdquo;, action=
&ldquo;GetCustomerById&rdquo; }
);
config.Routes.MapHttpRoute(
name: "ThridRoute",
routeTemplate: "api/{controller}/{action}"
);//generic route like Asp.Net MVC

How come it’s confirmed that its REST service?

Look at the response. There is no SOAP tags involved. We got direct data.

Similarly at the time of request we didn’t sent any SOAP XML. Simply made the request using
HTTP and done.

Why XML is returned as a response?

When we made a request to the service, it returned data in the form of XML.

Before I answer this, let me make you clear one thing. Yes, data is in XML format but SOAP
envelop is gone☻

Now as per the XML format is concerned, data cannot be send between different technologies
directly. It must be converted to either XML or JSON string and then transferred. In case of Web
API we have returned pure employee data which will get converted to XML string by Web API
engine and returned.

Do you think it’s an issue? Actually it’s a feature ☻

Web API have a very nice feature called Content negotiation. Client can negotiate for the output
content. If client asks for XML, Web API will return XML and if client asks for JSON, Web API
will return JSON.

In the last test I have used chrome browser. Check the same example in Internet explorer. You
will get JSON as response.

Does it mean that my web application will have compatibility issues?

No. Basically end user will never access Web APIs directly via browser’s address bar. They will
use some UI. UI will talk to Web API with the help of some programming languages like C#,
JavaScript etc. It means background code which access Web API is always going to be same.
When we access Web API using C# or JavaScript by default we get JSON but we can also
specify response content type and get XML.
What is Angular?

We use JavaScript to make static HTML dynamic. With JavaScript we change appearance, value
or structure of the existing HTML dynamically.

Angular is one of the most demanding JavaScript framework in industry now a days. So I believe
at least you should know the basics about it.

Angular is a JavaScript framework introduced by Google mainly focusing at Single Page


Applications.

Note: in this series I am just trying to make all of you familiar with AngularJS. It won’t contain
detailed angular topics.

Is AngularJS a library?

No it’s a framework.

What’s the difference between library and Framework?

Library provides the set of reusable APIs whereas framework does some special automation
along with providing reusable APIs.

Example –

JQuery is a reusable library which provides set of functions and make dom manipulation and
dom traversing easier.

.Net is Framework which provides reusable functionalities but it also handles compilation,
execution, it makes garbage collection run in the background and make sure unused memory get
cleared.

So Framework is something which does many things by its own.

Why angular is required?

In order to understand this we have to understand the problems of traditional JavaScript


programming.

(Read the following explanation again after completion of all the labs in this article)

I think you will be able to answer it well after looking at following sample.

Hide Copy Code


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script>
var SomeValue;
function SetValue() {
SomeValue= "Initial Value";
document.getElementById('MyTextbox').value = SomeValue;
}
function UpdateValue() {
SomeValue = "New Value";
}
</script>
</head>
<body >
<input type="text" id="MyTextbox" value="" disabled />
<input type="button" id="BtnClick" value="Click Me" />
</body>
</html>

What we are trying to achieve in above demo?

 There is variable called SomeValue and we are loading the value of that variable in textbox in
page load.

 When button is clicked value of the variable got updated to some new value.

Now let’s understand the problems with above sample code or in simple words traditional
JavaScript programming.

1. Let’s sometime in the future we have been asked to change the UI appearance. Let’s say client is
demanding a label or a span instead of textbox. It looks like a very easy change but don’t you
think it will also affect your JavaScript. So problem is every time we change the UI design there is
high possibility of JavaScript getting affected

2. Button click do update the value of variable but will it update the value in the textbox? NO. So
the problem is every time JavaScript value is updated an explicit update is required in UI.

3. JavaScript code we wrote is very much cluttered. You will not find a fix separation between
various parts. For an instance our JavaScript will hold both,

a. Logic part

I. Communication with server to get the new value

II. Validating inputs

III. Combine FirstName and LastName before using it.

b. Presentation part

I. Display salary in TxtSalary textbox


II. Textbox should be red in colour if salary is greater than 20000 or else in green
colour

Solution - angular

With Angular we get an ability where we will write our HTML and write JavaScript independent
of HTML. At runtime angular will connect JavaScript to HTML dynamically

Angular creates a two way binding between UI and JavaScript at runtime. Thus any change in UI
value will automatically JavaScript variables and any JavaScript change automatically reflect in
UI.

Binding is completely runtime hence we get a clear separation between presentation (HTML)
and logic (JavaScript). Angular brought MVW architecture in JavaScript programming world.

How angular works

For working with angular we need two thingsJavaScriptand HTML

Here is the step by step explanation on working of angular. Don’t worry if you won’tunderstand
it 100%,complete the demo and read it again.

1. JavaScript - In angular key concept is Module. Module acts like a container for different parts of
the application. Module mainly encapsulates following two things.

a. Model – which is the data to be displayed in UI. Model can also be something which will
decide how UI should be displayed.

b. Controller – which connects model to the UI

2. In angular there is a concept called Directives. They are special attributes which will be attached
to the HTML elements and they will change the default behaviour of those elements.

3. HTML - View will be designed using HTML. A single HTML may be broken down into multiple
independent sections with the help of HTML container elements like ‘table’, ‘div’ etc.
Each section will be treated as individual applications with the help of Angular directive “ng-
App”. “ng-App” attribute will be assigned to the module created in step 1.
In some cases entire HTML page is treated as one application. In that case “ng-App” directive will
be applied to body or HTML tag.

4. JavaScript – As I said in step1, every module will create one or more controllers.

5. HTML - Every application may contain one or more sub sections defined inside it with the help of
HTML container elements like ‘table’, ‘div’ etc. These sub sections will be dependent on each
other. Based on logical operation they will be divided. Each sub section will get its data from
different controllers. Which section will take data from which controller will be decided with the
help of special directive called “ng-controller”
6. HTML – Inside every sub section some HTML will be written each of which may get its data from
controller in the form of model.

7. Execution

a. When application is executed, at runtime angular parser will parse all theapplications in
the HTML.To identify applications it will search for ng-App directive.

b. Once the parsable element is found, angular will find ng-controller directive inside
parsable element and accordingly it creates the object of controller.

c. New child scope will be created and made available as an injectable parameter to the
Controller's constructor function as $scope. (Don’t worry about this point. You will get in
some time)

d. After that angular parses the HTML using data (model) exposed by controller.

Demo on Angular

Lab1– Simple Angular Demo

Step 1 – Download a Angular

We will use the same Web API project created in last labfor this demo.

Right click the project and select “Manage Nuget Packages”. Search for angular in online section
and install “AngularJs core”.
Step
2 –Create HTML

Create a new folder called HTML in the project and create a new HTML file called
SimpleAngular.html as follows.

Hide Copy Code


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>

</body>
</html>

Step 3 – Include Angular

Include Angular.js file in Simple.html file as follows

Hide Copy Code


<script src="../Scripts/angular.js"></script>

Step 4 - Create Angular module

Hide Copy Code


<script>
var MyModule = angular.module("MyAngularModule", []);
</script>

As you can see angular.module function takes two parameter. First parameter is the name of the
module and second parameter will be used to specify other dependent modules.

We will not get into the second parameter in this series.

Note: “MyAngularModule” is the name of the angular module where as “MyModule” is just a
JavaScript reference object,

Step 5–Create HTML appliaction

Attach ng-App directive to body tag as follows.

Hide Copy Code


</script>
</head>
<body ng-app="MyAngularModule">

</body>

As you can see this time entire body is considered as oneapplication.

Step 6–Create Controller

Create a controller inside module as follows.

Hide Copy Code


var MyModule = angular.module("MyAngularModule", []);
MyModule.controller("MyController", function ($scope) {

});
</script>

For now just take $scope as a variable which will encapsulate all the models required for view.
We will talk about it in detail soon.

Step 7 – Attach Controller to View

Simply define a sub section inside body with the help of ‘Div’ tag and attach controller to it.

Hide Copy Code


<body ng-app="MyAngularModule">

<div ng-controller="MyController">

</div>

</body>
Step 8 – Define Model data

In the controller function defined model data as follows.

Hide Copy Code


<script>
var MyModule = angular.module("MyAngularModule", []);
MyModule.controller("MyController", function ($scope) {
$scope.CustomerName = "Sukesh Marla";
$scope.Designation = "Corporate Trainer";
});
</script>

Step 9 – Display Model data in View

Use following HTML in view to display model data

Hide Copy Code


<body ng-app="MyAngularModule">

<div ng-controller="MyController">

<span>{{CustomerName}}</span>

<span> - </span>

<i>{{Designation}}</i>

</div>

</body>

Step 10 – Execute and Test

Press F5 and execute the application. Put the physical URL of the html file and check the output.

Talk on Lab 1

What is $scope

It’s a child scope. When angular parser find ng-Controller it creates two things.

 new instance of Controller

 new child scope


This new child scope is made available as an injectable parameter to the controllers constructor
function as $scope.

We define everything which is required for UI (view) as a member of this $scope.

What was {{}} signifies?

It’s called expression in angular. Angular parser will get the value of variable specified between
{{ and }} from current child scope and displays it.

What is MVW?

We will talk about this at end of the lab3 on angular

Lab 2- Change UI design

In this lab we have a small change requirement. Our requirement says “Display CustomerName
in disabled textbox”.

Step 1 – Change UI design to follows.

Hide Copy Code


<body ng-app="MyAngularModule">

<div ng-controller="MyController">

<input type="text" value="{{CustomerName}}" disabled />

<span> - </span>

<i>{{Designation}}</i>

</div>

</body>

Step 2 – Execute and Test

Press F5 and execute the application. Put the physical URL of the html file and check the output.

As you can see, change in the UI no more affects JavaScript code.


Lab 3 – Understand Two way binding

In this lab we will just take the above lab into next level.

Requirement

 Designation will not be displayed in UI anymore

 CustomerName textbox will be enabled

 CustomerName will also be displayed in span beside textbox

 Update button will be added to UI

 On Update click textbox value will be updated to “New Updated Value”

Step 1 –Change the UI part

Change the body content to following.

Hide Copy Code


<div ng-controller="MyController">

<input type="text" ng-model="CustomerName" />

<span>{{CustomerName}}</span><br />

<input type="button" value="Update"

ng-click="UpdateValue();" />

</div>

As you can see two new directives are introduced.

 ng-model
As I said before, directives will change the default behaviour of an HTML UI element. ng-model
will change the default behaviour of input control. Usually input control won’t do anything when
its value get updated but When ng-bind is attached it will create a two binding between model
and control. Henceas soon as model value get changed, UI value will be refreshed and every
time UI value get updated automatically model get updated.

 ng-click
Just like onclick,it will attach click event handler to the control but this time event handler is
going to be a part of current child scope. Hence inside event handler we get access to all the
current child scope elements including model.

Step 2 – Redefine controller


Redefine controller code to following

Hide Copy Code


<script>
var MyModule = angular.module("MyAngularModule", []);
MyModule.controller("MyController", function ($scope) {
$scope.CustomerName = "Sukesh Marla";
$scope.Designation = "Corporate Trainer";
$scope.UpdateValue = function () {
$scope.CustomerName = "New Updated Value";
}
});
</script>

Step 3 – Execute and Test

Press F5 and execute the application. Put the physical URL of the html file and check the output.

Talk on Lab 3

What is MVW?

In angular View means UI with which user will interact and Model means data required for
View.

Now let’s talk a little about Controller.

 Controller will controls the communication between View and Data (Model). Hence we can call it
as controller in MVC architecture.

 Controller not only encapsulate all the data required for view inside $scope but also it
encapsulate events in the view. Hence we can call controller as ViewModel in MVVM
architecture.
 • It also encapsulate the presentation logic. For instance let say we want to display some value
and then format in based on some condition. For example – display salary in red colour if it’s
greater than 2000 or else display it in blue colour. In Asp.Net MVC we handled such situation
with the help of ViewModel but when we speak about MVP architecture it’s the feature of
Presenter. Hence we can call it Presenter.

This is why we call it Model-View-Whatever. Whatever that can connect view and model.

Demo on Angular with Web API

Again this lab is going to be an upgrade for previous lab. In this lab,

 There will be two textboxes, one for CustomerName and one for Desingation

 We will get the initial value for textbox from Web API

 On button click current textbox value will be passed to Web API. Web API will upgrade the value
and return the new value back to angular.

Step 1 – Create Web API model

Create a new class called Customer in Model folder as follows.

Hide Copy Code


namespace WebAPISample.Models
{
public class Customer
{
public string CustomerName { get; set; }
public string Designation { get; set; }
}
}

Step 2 – Create Web API Controller

Create a new Web API called Customer in Controller folder.

Step 3 – Create GET action

Open CustomerController.cs file and put using statement as below.

Hide Copy Code


using WebAPISample.Models;

Now create a new action method called GET inCustomerController. Overall picture looks like
this.

Hide Copy Code


namespace WebAPISample.Controllers
{
public class CustomerController : ApiController
{
public Customer GET()
{
Customer c = new Customer();
c.CustomerName = "Sukesh Marla";
c.Designation = "Corporate Trainer";
return c;
}
}
}

Step 4 -Change Controller code in AngularJs side

Hide Copy Code


MyModule.controller("MyController", function ($scope,$http) {
$http.get("/api/Customer").then
(
function (r) {
$scope.Customer = r.data;
}
);
$scope.UpdateValue = function () {

}
});

What is $http?

To make life easier angular provides several useful services. Services are just wrapper over some
reusable functionalities.

Example $http service will let us make call to Server APIs.

When does the instance of $http get created?

Angular will create an instance of controller and new child scope when it finds the ng-controller
directive. Although services are injected into controller like $scope, services won’t get
instantiated in the beginning. It will get instantiated when it is first used.

Note: Instance of service will be created only once.After that same object will be reused across
all references. It strictly follows singleton pattern.

What is $http.get?

$http.get will make a get request to server APIs. It is going to be an asynchronous call. In simple
words next line after $http.get will execute even before server execution completes.

What is the purpose of “then” function used with $http.get?


As I said before $http.get makes service call asynchronously. So instead of returning an actual
value it will return a special object called Promise object.

Promise object exposes a function called “then” which will expect a parameter of type function.

Function passed to the “then” function will be executed automatically when execution of Web
API completes.

Step 5 – Change UI

Change the contents in the body section to following markup.

Hide Copy Code


<div ng-controller="MyController">

<input type="text" ng-model="Customer.CustomerName" />

<input type="text" ng-model="Customer.Designation" />

<input type="button" value="Update"

ng-click="UpdateValue();" />

</div>

Step 6 – Execute and Test

Press F5 and execute the application. Put the physical URL of the html file and check the output.

Note: You may get a little delay to textbox to get populate with values

Step 7 – Create POST action

Create a new action method called POST in CustomerController as follows.

Hide Copy Code


public Customer POST(Customer c)
{
c.CustomerName += " New";
c.Designation += " New";
return c;
}

Step 8 – Change UpdateValue function


Change the UpdateValue function in angular side as follows.

Hide Copy Code


<script>
var MyModule = angular.module("MyAngularModule", []);
MyModule.controller("MyController", function ($scope,$http) {
$http.get("/api/Customer").then
(
function (r) {
$scope.Customer = r.data;
}
);
$scope.UpdateValue = function () {
$http.post("/api/Customer", $scope.Customer).then
(
function (r) {
$scope.Customer = r.data;
}
);
}
});
</script>

Just like GET, POST will return promise object and everything else is same

$http.post will send post request to Web API and at server side Web API engine will make POST
action get executed.

Step 8 – Execute and Test

Press F5 and execute the application. Put the physical URL of the html file and check the output.

Complete magic of two way binding.


Learn MVC Project in 7 Days – Bonus Day 2
Introduction

This article is a continuation article of the series “Learn MVC project in 7 days”. As I promised
here is the second bonus day article in the series. This is the last article in the series. I believe
you have enjoyed the complete series. Thanks for all your support and wish you good luck.

Today we will speak about some topics on Asp.Net MVC which we have not covered in the
project.

 Introduction

 Understand TempData in Asp.Net MVC

o What is TempData?

o When the TempData values get removed?

o What will happen if the TempData values are not read?

o Keep and Peek methods

 Avoid CSRF attacks in Asp.Net MVC

 MVC bundling and Minification

o Understanding Bundling

o Understanding Minification

o Implementing bundling and minification in Asp.Net MVC

 Creating Customer Helper classes

 MVC Unit Testing

 Start with MVC 5

 Conclusion

Complete Series

 Day 1
 Day 2

 Day 3

 Day 4

 Day 5

 Day 6

 Day 7

 Bonus Day 1

 Bonus Day 2

Understand TempData in Asp.Net MVC

For this topic we won’t do any demo. TempData behaves differently in different situations.
Incorporating all of the scenario in single project is not possible. That’s why we will just try to
cover and understand all the scenarios step by step.

What is TempData?

TempData is a session with shorten life cycle. Just like session it’s a key value pair used to hold
user specific values. Difference between Session and TempData is, TempData let us maintain
data only within single request cycle.

To understand TempData properly you must understand the meaning “Single Request” properly

 User make a request via browser’s address bar which is handled by an action method. Let’s call it
Request 1.

 Now unless end user get a final response it will be called as request 1. Once end user get a
response request ends there.

 Now by clicking a hyperlink, button or again with the help of browser’s address bar end user can
make a new request.

Look at the following image to understand “single request cycle” and TempData
Code Example:

Hide Copy Code


public ActionResult M1()
{
TempData["a"] = "Value";
string s = TempData["a"].ToString(); // TempData will be available
return RedirectToAction("M2");
}

public ActionResult M2()


{
string s = TempData["a"].ToString(); //TempData will be available
return RedirectToAction ("M3");
}
public ActionResult M3()
{
string s = TempData["a"].ToString();// TempData will be available
return view ("Some View"); // TempData will be available inside view
also
}

It doesn’t matter if it is a view or an action method. Unless request completes values in the
TempData will be available.

When the TempData values get removed?

 At the end of the request, values in the TempData get removed automaticallyifvalues are marked
for deletion.

 Values will be marked for deletion as soon as we read it.

Example 1 -

Hide Copy Code


public ActionResult M1()
{
TempData["a"] = "Value";
return view("MyView");
}
...
...
...
View Code
...
...
@{
string s = TempData["a"].ToString(); // TempData is marked for deletion
}

Example 2 -

Hide Copy Code


public ActionResult M1()
{
TempData["a"] = "Value";
string s = TempData["a"].ToString(); // TempData is marked for deletion
return view("MyView"); // MyView can access TempData because it will be
deleted at the end of the request
}

Note: In above two examples values are marked for deletion as soon it get read. Now for the next
request this values won’t be available because at the end of the current request current TempData
get deleted.
What will happen if the TempData values are not read?

As per the final explanation we had, TempData values will be deleted at the end of the current
request considering they are marked for deletion in current request and they will get marked for
deletion only if we read it. What will happened if we won’t read it?

Simple answer, in that case TempData will be available to the next request as well. Now
TempData will get removed at the end of the next request if it is marked for deletion in next
request else this story continues.

Code Example

Hide Copy Code


public ActionResult M1()
{
TempData["a"] = "Value";
return view("MyView"); // TempData will be available inside view but
let&rsquo;s assume MyView won&rsquo;t read the value
}

//Immediate next request after M1 made by end user


public ActionResult M2()
{
string s = TempData["a"].ToString(); // TempData will be available and now
its marked for deletion
return view("MyView2"); // TempData will be available inside view also
because request is not ended yet.
}

In the above sample,

 End user make a request to Action method M1. It creates TempData which will be available
throughout that request, but neither inside M1 nor inside MyView values are read and hence
values won’t get removed at the end of the request.

 Next let’s say end user makes a fresh request to M2 action method via hyperlink or some other
way. Now TempData created during M1 action method will be available in M2 also. Inside M2
TempData values will be read and hence it get marked for deletion. Current request ends once
end user get a final response. In our case end user get the final response only after view
completes its rendering. Hence TempData will be available in the View also. Once the View
rendering is done TempData get removed.

Keep and Peek methods

Keep

Keep method makes the values in the TempData persistent for next request.

Example 1
Action method

Hide Copy Code


public ActionResult M1()
{
TempData["a"] = "Value";
TempData["b"] = "Value1";
TempData["c"] = "Value2";
TempData.Keep();
return view("MyView");
}

View

Hide Copy Code


...
...
@{
string s= TempData["a"].ToString();
string s1= TempData["b"].ToString();
string s2= TempData["c"].ToString();
}

In above example all three TempData values will be available to the next request as well.

Example 2 -

Action method

Hide Copy Code


public ActionResult M1()
{
TempData["a"] = "Value";
TempData["b"] = "Value1";

TempData.Keep();

TempData["c"] = "Value2";
return view("MyView");
}

View

Hide Copy Code


...
...
@{
string s= TempData["a"].ToString();
string s1= TempData["b"].ToString();
string s2= TempData["c"].ToString();
}
In the above sample only TempData with key “a” and “b” will be available for next request.
TempData with key “c” get removed at the end of current request.

Example 3 –

Action Method

Hide Copy Code


public ActionResult M1()
{
TempData["a"] = "Value";
TempData["b"] = "Value1";
TempData["c"] = "Value2";

TempData.Keep(&ldquo;a&rdquo;);

return view("MyView"); // TempData will be available inside view


}

View

Hide Copy Code


...
...
@{
string s= TempData["a"].ToString();
string s1= TempData["b"].ToString();
string s2= TempData["c"].ToString();
}

In the above sample only TempData with key “a” will be available in the next request.

TempData with key b and c will be removed the end of current request.

Peek

Peek will let us retrieve the TempData value without marking it for deletion.

Example without Peek:

Hide Copy Code


public ActionResult M1()
{
TempData["a"] = "Value";
return RedirectToAction("M2");
}
public ActionResult M2()
{
string s = TempData["a"].ToString(); //TempData will be marked for
deletion
return view ("Some View");
}
.
.
.
//Next request
public ActionResult M3()
{
string s = TempData["a"].ToString(); // Will get an Exception
&hellip;
}

In above example TempData values (created inside Action method M1) won’t be available for
next request because it already used in current request (in Action method M2).

When user make a fresh request to action method M3, null reference exception will be thrown.

Example with Peek:

Hide Copy Code


public ActionResult M1()
{
TempData["a"] = "Value";
return RedirectToAction("M2");
}
public ActionResult M2()
{
string s = TempData.Peek("a").ToString(); // TempData values will be read
but will not be marked for deletion
return view ("Some View");
}
.
.
.
public ActionResult M3()
{
string s = TempData["a"].ToString(); // Will just work
&hellip;
}

In above example TempData value will be available in next request also.

Avoid CSRF attacks in Asp.Net MVC

Now before we go and learn to avoid it, first let’s learn about it.

CSRF stands for Cross site request forgery.

Here hacker will develop a two faced UI. Two faced UI means, a UI which will do something
different according to end user but in reality it will do something different.

To understand it better let’s do a small demo.

Step 1 – Open Day 7 Project


Open the project we have completed in Day 7

Step 2 – Execute the project

Press F5 and execute the project. Complete the login process with Admin user.

Step 3 – Create forgery project

Open a fresh Visual studio. Select File >> New >> Project. Select Web section from left panel
and “Asp.Net Web Application” from right. Call it “ForgeryProject” and click Ok.

Select Empty template and Web Forms references and click Ok.

(In this demo you are creating this forgery project but in real time this will be created by
someone else who want to hack into your system.)

Step 4 – Create a DownloadEbook option

Create a HTML page called DownloadEbook.html in the newly created project as follows.

Hide Copy Code


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<form action="http://localhost:8870/Employee/SaveEmployee" method="post"
id="EmployeeForm">
<input type="hidden" name="FirstName" value="DummyFName" />
<input type="hidden" name="LastName" value="LName" />
<input type="hidden" name="Salary" value="35000" />
<input type="hidden" name="BtnSubmit" value="Save Employee" />
Congratulations!! You have won a free pdf of Learn MVC project in 7
days.
Email : - <input type="text" name="Whatver" value="" />
<input type="submit" name="MyButton" value="Send Link" />
</form>
</body>
</html>

Step 4 – Execute the project

Press F5 and execute the application.


Explanation: -

You were expecting to get a download pdf link but it actually created a new employee.

Let’s understand what exactly happened.

 End user is able to create an employee only if he is an Authenticated Admin user.

 In our case Admin user will login using his admin credentials and after sometime he will go and
open a new browser instance (or browser tab) and start doing some surfing. (Remember his
current session is active and he is still authenticated user for our application)

 All of the sudden above forgery page (created by some enemy) comes in front of him and he/she
click the “Send link” button.

 “Send link” button will actually send a post request to our application. You know what happens
next.

This is called CSRF attack.

Solution for this problem in tokens.

 In actual data entry screen server will inject a secret token in the form of hidden field.

 It means when post request is made from actual data entry screen, secret token will be sent as a
part of posted data.

 At server side received token will be validated against generated token and if they are not same
request won’t be served.
Now let’s implement solution for it.

Step 1 – Inject token in original data entry screen

Open CreateEmployee.cshtml from “~/Views/Employee” folder in the Day 7 project and inject
secret token as follows.

Hide Copy Code


<td colspan="2">
@Html.AntiForgeryToken()
<input type="submit" name="BtnSubmit" value="Save Employee"
onclick="return IsValid();" />
<input type="submit" name="BtnSubmit" value="Cancel" />
<input type="button" name="BtnReset" value="Reset" onclick="ResetForm();"
/>
</td>

Step 2 –Enable forgery validation on Action Method

Attach ValidateAntiForgeryToken attribute to SaveEmployee action method of


EmployeeController as follows.

Hide Copy Code


[AdminFilter]
[HeaderFooterFilter]
[ValidateAntiForgeryToken]
public ActionResult SaveEmployee(Employee e, string BtnSubmit)
{
switch (BtnSubmit)
{

Step 3 – Check the generated token in Data Entry screen

Press F5 and execute the application. Complete the login process. Navigate to AddNew screen
and check the view source.
Step 4 – Check forgery

Keep the project login open and execute the forgery project and perform the same testing we did
before.

Now it’s secured.

MVC bundling and Minification

Understanding Bundling

We cannot imagine a project without CSS and JavaScript file.

Bundling is concept of combining multiple JavaScript or CSS files into a single fileat runtime.
Now the million dollar question is why should we combine?

To understand this better let’s do a demo.

Step 1 – Execute the project


Execute our project again. Perform execution in chrome.

Step 2 – Open chrome developer tools

In chrome press “cntrl + shift + I” to open developer tools. Now navigate to “Network tab”

Step 3 – Open Login

Now make a request to Login page and check the network tab again.

If you remember we have implemented Unobtrusive client side validation in login view which
require three JavaScript files. So when Login View is requested it makes four request calls:-

 One for the Login View.

 Three requests for JavaScript files “jQuery.js”, “jQuery.validate.js” and


“jQuery.validate.unobtrusive.js”.

Just try to imagine a situation when we have lots of JavaScript file. It leads to multiple requests
thus decreases performance.

Solution will be combine all the JS files into single bundle and request it in a single request as a
single unit. This process is termed as bundling.

We will learn how to perform bundling using Asp.Net MVC soon.

Understanding Minification

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.

Hide Copy Code


// This is test
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 increases performance as
the file size has get reduced.

Hide Copy Code


var x=0;x=x+1;x=x*2;

Implementing bundling and minification in Asp.Net MVC

Step 1 – Create Script bundles

Open BundleConfig.cs file from App_Start folder. You will find a RegisterBundle method.
Remove all existing code inside it and redefine it as follows.

Hide Copy Code


public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/jqueryValidation").Include(
"~/Scripts/jquery-1.8.0.js").Include(
"~/Scripts/jquery.validate.js").Include(
"~/Scripts/jquery.validate.unobtrusive.js"));
}

Step 2 - Include bundle in Login View

Open Login.cshtml view from “~/Views/Authentication” folder.

Remove the references of three script files and include it has one bundle.

Hide Copy Code


<title>Login</title>
@Scripts.Render("~/bundles/jqueryValidation")
</head>
<body>

Step 3 – Execute and test

Execute the application and check the network tab again.

Unfortunately you will not find any difference.

Step 4 – Enable bundling and minification

Open Global.asax file and in put following line in the top of Application_Start event.

Hide Copy Code


BundleTable.EnableOptimizations = true;
Step 5 – Execute and Test

Perform the same test again.

As you can see a single file is requested instead of three. All three JavaScript files are bundled
into one. Check the size. It is just 294B. Earlier it was (289+294+310). It proves that
minification also did his work.

(Don’t forget to check the validation.☻)

In the same we create bundles for CSS files called StyleBundle.

Creating Customer Helper classes

It’s going to be C# more than Asp.Net MVC.

In this article we will create a custom helper function for submit button.

Step 1 – Create a CustomerHelperClass

Create a new folder called Extensions in the project and create a new class called
CustomHelperMethods inside it.

Step 2 – Make class a static class

Now make above class a static class because that’s going to be the first requirement for extension
methods.

Hide Copy Code


namespace WebApplication1.Extenions
{
public static class CustomHelperMethods
{
}
}

Step 3 –Create an extension method


Put using statement in the class follows

Hide Copy Code


usingSystem.Web.Mvc;

Create a new static extension method called Submit inside above class as follows.

Hide Copy Code


public static MvcHtmlString Submit(this HtmlHelper helper, string displayText)
{
return MvcHtmlString.Create
(
string.Format("<input type='submit' name=Btn{0} id=Btn{0} value={0}
/>",displayText)
);
}

Step 4 – Change Login View

Open Login View from “~/Views/Authenticate” folder and put using statement in the as the
follows.

Hide Copy Code


@using WebApplication1.Extenions

Now remove input type submit and put following code instead of that.

Hide Copy Code


...
...
@using (Html.BeginForm("DoLogin", "Authentication", FormMethod.Post))
{
@Html.LabelFor(c=>c.UserName)
@Html.TextBoxFor(x=>x.UserName)
@Html.ValidationMessageFor(x=>x.UserName)
<br />
@Html.LabelFor(c => c.Password)
@Html.PasswordFor(x => x.Password)
<br />

@Html.Submit("Login")
}
...
...

Step 5 - Execute and Test

Press F5 and execute the application. Check the output.


MVC Unit Testing

For this we will not do a complete demo. I want you to take it as an assignment.

For reference check below article.

http://www.codeproject.com/Articles/763928/WebControls

Potrebbero piacerti anche