Learn MVC Project in 7 Days
Learn MVC Project in 7 Days
com/Articles/866143/Learn-MVC-step-by-step-in-days-Day
Introduction
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.
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.
“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”.
“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.
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:-
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.
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.
In the code behind you have written some logic which manipulates the text box values and the
back ground color.
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.
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 ?.
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.
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.
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.
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:-
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.
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.
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.
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.
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.
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.
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.
“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.
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.1. In the solution explorer, right click the controller folder and select Add>>Controller
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.
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.
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.
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.
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”;
They are simply methods of a class and not available publicly . In simple words these methods
can not be invoked from the web.
When we try to make request to above action method we will get following response.
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.
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 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”.
</body> </html>
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.
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?
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
ViewResult choose the correct ViewEngine and passes ViewPageActivator object as argument to
ViewEngine’s constructor.
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.
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?
Why MVC?
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
Talk on Lab 3
Talk on Lab 4
Talk on Lab 5
ViewModel a solution
Talk on Lab 6
Talk on Lab 7
Conclusion
View will get data from the controller in the form of Model.
Model
In Asp.Net MVC model represent the business data.
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.
Note: Make sure to put using statement in the top or else we have to put fully qualified name of
Employee class.
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"];
}
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.
ViewData holds objects internally. Every time a new value is added into it, it get boxed to object
type.
It means Display First Name followed by a space and then last name.
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.
ViewBag is just a syntactic sugar for ViewData. ViewBag uses the dynamic feature of C# 4.0 and
makes ViewData dynamic.
Continue with the same Lab 3 and replace Step 3 with following code snippet.
Talk on Lab 4
Yes, We can. Vice versa is also possible. As I said before, ViewBag is just a syntactic sugar for
ViewData,
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.
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.
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.
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.
Above statement make our View a strongly typed view of type Employee.
Now inside View simply type @Model and Dot (.) and in intellisense you will get all the
properties of Model (Employee) class.
Talk on Lab 5
Is it must to make View a strongly typed view always or can we go with ViewData or
ViewBag sometimes?
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.
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 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
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.
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
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.
It’s simple.
Controller handle the user interaction logic or in simple words, handles the user’s requests.
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
Model and ViewModel should be independent of each other. Controller will create and initialises
ViewModel object based on one or more Model object.
Create a new class called EmployeeViewModelinside ViewModels folder will looks like below.
In Lab 5 we had made our View a strongly type view of type Employee. Change it to
EmployeeViewModel
In GetView action method,get the model data and convert it to ViewModel object as follows.
vmEmp.UserName = "Admin"
return View("MyView", vmEmp);
}
Same output as Lab 5 but this time View won’t contain any logic.
Talk on Lab 6
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.
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.
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.
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
Talk on Lab 8
Organize everything
Lab 9 – Create Data Entry Screen
Talk on Lab 9
Talk on Lab 10
Talk on Lab 11
Talk on lab 13
Conclusion
Here we will use Sql Server and Entity Framework for creating Database and Database Access
layer respectively.
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.
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.
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.
Connect to the Sql Server and create new Database called “SalesERPDB”.
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”
using System.Data.Entity;
Open Employee class and put using statement at the topas follows.
Note: In above code snippet “TblEmployee” represents the table name. It automatically get
created in runtime.
DbSet will represent all the employees that can be queried from the database.
Step 8– Change Business Layer Code and get data from Database
Check the database. Now we have a table called TblEmployee with all the columns.
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.
Yes, in that case we have to define a constructor in Data Access Layer class as follows.
Organize everything
Just to make everything organized and meaningful let’s do couple of changes.
Step 1 - Rename
“TestController” to “EmployeeController”
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.
It decides the type of request. Request may be one of the following four types - get, post, put and
delete.
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).
When request is of type Get, Put or Delete, values will be sent as Query string parameters.
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.
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.
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.
How Textbox values are updated in Employee object inside action method?
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.
Yes it will, but in that case name of the control should be given accordingly.
Example
...
...
Note: Save button and Cancel button have same “Name” attribute value that is “BtnSubmit”.
In Head section of Html add a script tag and inside that create a JavaScript function called
ResetForm as follows.
Press F5 and execute the application. Navigate to the AddNew screen by clicking “Add New”
link.
Talk on Lab 11
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)
</form>
Step 2 – Change Submit button to normal button and post above form with the help of
JavaScript.
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:
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?
Now our Model class contain property names as FirstName, LastName and Salary. Hence default
model binder won’t work here.
Inside action method, retrieve posted values using Request.Form syntax and manually construct
the Model object as follows.
Create Custom Model Binder and replace default model binder as follows.
Step 2- Replace default model binder with this new model binder
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.
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.
Before we get into Data Annotation lets understand few more things about Model Binder
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.
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.
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.
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.
Open Employee class from Model folder and decorate FirstName and LastName property with
DataAnnotation attribute as follows.
Note: As you can see, When ModelState.IsValid is false response of SaveEmployee button click
is ViewResult pointing to “CreateEmployee” view.
This time we will format our UI a little with the help of “table” tag;
<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>
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.
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
StringthLength – Validates the string for maximum and minimum number of characters.
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”)
Yes, Not only integers but all value types because they can’t hold null values.
Make it nullable?
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.
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.
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.
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.
Open Employee.cs file and create a new class Called FirstNameValidation inside it as follows.
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.
Open Employee class and remove the default “Required” attribute from FirstName property and
attach FirstNameValidation as follows.
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 Authentication
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.
For repopulation we will simply reuse the Employee object created by Model Binder. Change
SaveEmployee Action method as follows.
...
...
...
...
...
...
...
...
...
...
...
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.
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
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:
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.
Yes, we can use HTML helper classes for that. We will talk about this in one of the upcoming
lab.
First of all let’s list down what all validations we require here.
Create a JavaScript File called “Validations.js” and keep it inside Scripts folder
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() {
if (FinalErrorMessage != "Errors:") {
alert(FinalErrorMessage);
return false;
}
else {
return true;
}
}
Simple put a reference of “Validations.js” file in the head section of “CreateEmployee” view as
follows.
Test 1
Test 2
Talk on Lab 16
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.
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
Yes, In case someone disables JavaScript, Server side validation keep everything in place.
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.
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.
Create new Model class called UserDetails inside Models folder as follows.
Crete a new view called Login inside “~/Views/Authentication” folder. Make it a strongly typed
view of type UserDetails.
@{
Layout = null;
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
</head>
<body>
<div>
@Html.LabelFor(c=>c.UserName)
@Html.TextBoxFor(x=>x.UserName)
<br />
<br />
</div>
</body>
</html>
As you can see, this time for generating View instead of Pure HTML we are using HtmlHelper
class.
Example 1:
Example 2:
Hide Copy Code
@using (Html.BeginForm("DoLogin", "Authentication", FormMethod.Post))
{
}
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”.
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.
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.
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.
This DoLogin action method will be invoked when Login button in Login view is clicked (Check
Step 3).
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.
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”).
Open Login View and add following code just above the @Html.BeginForm
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
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.
Yes.
When request is made via browser, all the associated cookies will be sent with the request.
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.
No. We have an alternative for it. We can use URI instead of cookies.
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.
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?
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.
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.
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.
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
Global level
Step 1 - Open FilterConfig.cs file from App_start folder.
Step 4 – Execute and Test the application in the same way we did before.
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.
<hr />
<div>
Press F5 and execute the application. Complete the login process and you will get to see
following output.
<a href="/Authentication/Logout">Logout</a></div>
<hr />
<div>
<table border="1">
Open AuthenticationController and add new action method called Logout as follows.
jQuery.valiadte.js
jquery.validate.unobtrusive
Open Login.cshtml and in head section include all three js files (in same sequence)/
Talk on Lab 21
Example:
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.
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
“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?
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.
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
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.
Right click the ViewModel folder and create a class called FooterViewModel as follows.
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.
@model FooterViewModel
<div style="text-align:right;background-color: silver;color: darkcyan;border:
1px solid gray;margin-top:2px;padding-right:10px;">
</div>
Open EmployeeListViewModel class and add a new property to hold Footer data as follows.
In our example Footer (Partial View) is going to be displayed as a part of 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.
Open EmployeeController and in Index action method set value to FooterData property as
follows.
Open Index.cshtml and display Footer Partial View after table tag as follows.
Press F5. Navigate to Index view. (I believe, you know how to do it now.)
Talk on Lab 22
Just like Html.RenderPartial, Html.Partial will be used to display Partial View in the View.
Html.RenderPartial will write result of the Partial View directly to the HTTP response stream
whereas Html.Partial will return result as MvcHtmlString.
As per MSDN “MvcHtmlString represents a HTML-encoded string that should not be encoded
again”.
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 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.
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.
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.
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.
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.
As a best practice we must create Partial View for header also but to keep Initial labs simpler we
had kept it inline.
Session
Action Filters
Right click the Models folder and select “Add New Item”.
Select “Code File” option from the dialog box.
Delete IsValidUser function and create a new function called GetUserValidity as follows.
As you can see, we are using session variable for identifying whether the user is a admin user or
non admin user.
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.
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.
Open EmployeeController and create a new action method called “GetAddNewLink” as follows.
Html.RenderAction executes the Action Method and writes result directly to response stream.
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.
Create a new folder called Filters in Project and create a new class called AdminFilter.
Step 2 – Create Filter
Note: To use ActionFilterAttribute you have to put using System.Web.Mvc in the top.
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
Yes, we already spoke about such behaviour in “Talk on Lab 22” section.
Just like Html.RenderAction, Html.Action will execute the action method and display the result
in View.
Html.RenderAction will write result of the action method execution directly to the HTTP
response stream whereas Html.Action will return result as MvcHtmlString.
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 [email protected]
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
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
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.
As you can see BaseViewModel encapsulates everything required for Layout Page
Remove UserName and FooterData properties from EmployeeListViewModel class and inherit it
from BaseViewModel.
Right click shared folder. Select Add>>MVC 5 Layout Page. Put name as MyLayout and click
ok.
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
</head>
<body>
<div>
@RenderBody()
</div>
</body>
</html>
Simply put following statements in the top of the layout page and make it strongly typed layout.
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.
Open Index.cshtml and in the top you will find following code.
@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.
Open Index.cshtml and in the top you will find following code.
Follow the same Step 7 procedure and define sections in CreateEmployee View. This time there
will be one addition. We will also define HeaderSection.
@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">
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.
Real reason for such error is, we have not initialized Header and FooterData in AddNew action.
Talk on Lab 25
When we first created in the Layout page it had one razor stamen something like below.
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
Yes we can. We can create a layout page which will use some other layout page. Syntax will be
same.
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.
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?
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.
Remove Header and FooterData code from Index, AddNew and SaveEmployee methods (in the
Employee Controller).
Create a new class called HeaderFooterFilter in Filters folder and upgrade it to Action filter by
inheriting it from ActionFilterAttribute class
Override OnActionExecuted in HeaderFooterFilter class. In this method get the current view
model and attach Header and Footer Data.
OnActionExecuted will be used to add post processing logic to action method execution.
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 [email protected]
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
2. Asynchronous controllers.
Create a new controller called BulkUploadController and an action method called Index Action
as follows.
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.
Kindly note that view name should be index.cshtml and should be placed in
“~/Views/BulkUpload” folder.
@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.
Create a sample file like below and save it somewhere in the computer.
Press F5 and execute the application. Complete the login process and navigate to BulkUpload
option by clicking link.
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
Adding client side and server side validation to this option will be an assignment for readers. I
will give you a hint.
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.
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.
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.
Example – Our login form will send following post request to the server
All input values are sent as one part in the form of key/value pair connected via “&”.
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.
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".
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.
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.
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.
No, response time will remain same. Here thread will get freed for serving other requests.
It can be done easily with the help of two keywords – async and await.
As you can see we are storing thread id in a variable in the beginning and in the end of action
method.
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.
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.
Now before you do anything more in the output, navigate to code and put a breakpoint at the last
line.
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.
Exception Filters will be used in the same way other filters are used. We will use them as an
attribute.
Enable them.
Apply them as an attribute to an action method or to a controller. We can also apply exception
filter at global level.
Exception filter will take control of the execution and start executing code written inside it
automatically as soon exception occurs inside action method.
In the last lab in our project we have implemented BulkUpload option. Now there is high
possibility of error in the input file.
Create a sample upload file just like before but this time put some invalid value.
Press F5 and execute the application. Navigate to Bulk Upload Option. Select above file and
click on Upload.
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.
<!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>
As we discussed before after we enable exception filter we attach them to action method or to
controller.
Open FilterConfig.cs file from App_Start folder. In RegisterGlobalFilters method you will see
that HandleError filter is already attached at global level.
If required remove global filter and attach it at action or controller level as below.
In order to achieve this convert Error view to strongly typed view of type HandleErrorInfo class
and then display error messages in the view.
<!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>
Perform the same testing but this time we will get following Error view.
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.
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.
Execute the application and put some invalid URL in the address bar.
Talk on Lab 29
In that case we have to specify view name while attaching HandlError filter.
Yes, it is possible. In that case we have to apply handle error filter multiple times.
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.
The only limitation with above lab is we are not logging our exception anywhere.
Note: Make sure to put using System.Web.MVC in the top.HandleErrorAttribute class exists
inside this namespace.
Open FilterConfig.cs file and remove HandErrorAtrribute and attach the one we created in last
step as follows.
First of all create a folder called “Error” in C drive because that’s the place where error files are
going to be placed.
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
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.
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.
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.
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.
You will find RouteConfig.cs file inside App_Start folder which contain following code block.
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.
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.
Number of parameters in the requests URL(other than domain name) and in the URL pattern
defined in the route
Example:
Once the Route object is selected, UrlRoutingModule will obtain MvcRouteHandler object from
Route object.
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:
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:
Route Parameters
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.
Testing 1
Testing 2
Testing 3
MVCHandler will create Controller instance with the help of ControllerFactory (by default it
will be DefaultControllerFactory).
MVCHandler will invoke Controller’s execute method. Execute method is defined inside
controller base class.
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.
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.
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
1. “http://localhost:8870/Employee/BulkUpload”
2. “http://localhost:8870/BulkUpload/Index”
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.
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.
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.
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.
routes.MapMvcAttributeRoutes();
routes.MapRoute(
...
As you can see, we have same output but with different more User Friendly URL.
It will be easier.
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.
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.
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 [email protected]
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
o Talk on Lab 32
o Talk on Lab 33
o What’s next?
o Let’s plan
o Talk on Lab 35
Conclusion
Complete Series
Day 1
Day 2
Day 3
Day 4
Day 5
Day 6
Day 7
Bonus Day 1
Bonus Day 2
This is not actually a lab related to any new functionality. This lab is just to make project more
structured and systematic.
Now repeat the step and create three more similar folders called “Model”, “ViewModel” and
“Data Access Layer”
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.
Create a new project class library project inside ViewModel folder and call it ViewModel.
First right click each project one by one. Select Add>>Reference and select references as below.
3. Copy Employee.cs, UserDetails.cs and UserStatus.cs from Model folder inthe MVC
project to newly created BusinessEntities class library project.
6. Copy all the classes from ViewModels folder in the MVC project to newly created
ViewModel class library 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.
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.
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.
2. Create a new class called BusinessSettings with a static method called SetBusiness inside
BusinessLayer project as follows.
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.
Talk on Lab 32
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.
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.
FooterViewModel
Footer.cshtml
Right click the project and Select Add>>Area. A dialogue box will popup. Put it as SPA and
select ok.
Obviously Model folder related to the area is not required. Delete it.
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.
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.
Create a new folder called SPA in ViewModel class library project and create a ViewModel
called MainViewModel as follows.
Now create a new action method called Index inside MainController as follows.
Not specifying alias name will leads to ambiguity error. Both namesapces
WebApplication1.ViewModels.SPA and WebApplication1.ViewModels have some similar
classes.
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Employee Single Page Application</title>
Press F5 and execute the application. Complete the Login process and navigate to index action in
Main Controller.
Talk on Lab 33
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.
This is why, when it comes to controllers in the area we put SPA keyword before controller name
Open global.asax file. Very first line in Application_Start will be something like below.
The RegisterAllAreas method finds all types in the application domain that derive from
AreaRegistration and calls each of their RegisterArea methods.
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.
Note: Both the ViewModels are exact replica of ViewModel created for Non-Spa application.
Only difference is this time BaseViewModel is not required.
It will add couple of JavaScript (.js) and Stylesheet (.css) files to the project.
Complete the login process and navigate to Index action in MainController. Finally click on Add
New hyperlink.
What’s next?
Before we continue and follow the step 10 first let’s understand what we are supposed to next.
If all values are valid, all value will be transferred to server side.
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.
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.
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.
They cannot exchange their data or in simple words they cannot exchange their variable directly
with each other.
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?
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.
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”
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.
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”.
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.
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.
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”
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.
Data represented in JSON format look like JavaScript object hence this format is named as JSON
(JavaScript Object Notation)
Close dialog
Update Grid
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.
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).
For now just take Json method as a way to send Json String from MVC action method to
JavaScript.
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>
Talk on Lab 35
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.
Using JavaScript Serializerit will convert the data passed to JSON formatted string
In the above controller create a new action method called Index as follows.
Navigate to Index action of Main Controller and click the BulkUpload link.
Create a new view model class called FileUploadViewModel in SPA folder of ViewModel class
library.
As you can see this time instead of redirecting we are returning JsonResult.
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>
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
Here we will speak about some MVC topics which are not covered in 7 days.
o Appliaction_Error
o Temp data
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.
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 is Angular?
Demo on angular.
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
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.
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”.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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
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.
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.
You will notice that a new class get created inheriting from ApiController. It’s going to be our
Web API.
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.
In the project, in App_Start folder you will find a file called WebApiConfig.cs. Open it.
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.
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.
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.
In Web API simply create four methods named GET, POST, PUT, DELETE respectively.
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.
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 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.
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.
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.
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.
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.
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.
(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.
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
b. Presentation part
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.
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.
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
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.
</body>
</html>
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.
Note: “MyAngularModule” is the name of the angular module where as “MyModule” is just a
JavaScript reference object,
</body>
});
</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.
Simply define a sub section inside body with the help of ‘Div’ tag and attach controller to it.
<div ng-controller="MyController">
</div>
</body>
Step 8 – Define Model data
<div ng-controller="MyController">
<span>{{CustomerName}}</span>
<span> - </span>
<i>{{Designation}}</i>
</div>
</body>
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.
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?
In this lab we have a small change requirement. Our requirement says “Display CustomerName
in disabled textbox”.
<div ng-controller="MyController">
<span> - </span>
<i>{{Designation}}</i>
</div>
</body>
Press F5 and execute the application. Put the physical URL of the html file and check the output.
In this lab we will just take the above lab into next level.
Requirement
<span>{{CustomerName}}</span><br />
ng-click="UpdateValue();" />
</div>
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.
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.
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.
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.
Now create a new action method called GET inCustomerController. Overall picture looks like
this.
}
});
What is $http?
To make life easier angular provides several useful services. Services are just wrapper over some
reusable functionalities.
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.
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
ng-click="UpdateValue();" />
</div>
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
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.
Press F5 and execute the application. Put the physical URL of the html file and check the output.
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
o What is TempData?
o Understanding Bundling
o Understanding Minification
Conclusion
Complete Series
Day 1
Day 2
Day 3
Day 4
Day 5
Day 6
Day 7
Bonus Day 1
Bonus Day 2
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:
It doesn’t matter if it is a view or an action method. Unless request completes values in the
TempData will be available.
At the end of the request, values in the TempData get removed automaticallyifvalues are marked
for deletion.
Example 1 -
Example 2 -
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
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
Keep method makes the values in the TempData persistent for next request.
Example 1
Action method
View
In above example all three TempData values will be available to the next request as well.
Example 2 -
Action method
TempData.Keep();
TempData["c"] = "Value2";
return view("MyView");
}
View
Example 3 –
Action Method
TempData.Keep(“a”);
View
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.
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.
Now before we go and learn to avoid it, first let’s learn about it.
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.
Press F5 and execute the project. Complete the login process with Admin user.
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.)
Create a HTML page called DownloadEbook.html in the newly created project as follows.
You were expecting to get a download pdf link but it actually created a new employee.
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.
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.
Open CreateEmployee.cshtml from “~/Views/Employee” folder in the Day 7 project and inject
secret token as follows.
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.
Understanding Bundling
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?
In chrome press “cntrl + shift + I” to open developer tools. Now navigate to “Network tab”
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:-
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.
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.
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.
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.
Remove the references of three script files and include it has one bundle.
Open Global.asax file and in put following line in the top of Application_Start event.
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.
In this article we will create a custom helper function for submit button.
Create a new folder called Extensions in the project and create a new class called
CustomHelperMethods inside it.
Now make above class a static class because that’s going to be the first requirement for extension
methods.
Create a new static extension method called Submit inside above class as follows.
Open Login View from “~/Views/Authenticate” folder and put using statement in the as the
follows.
Now remove input type submit and put following code instead of that.
@Html.Submit("Login")
}
...
...
For this we will not do a complete demo. I want you to take it as an assignment.
http://www.codeproject.com/Articles/763928/WebControls