Академический Документы
Профессиональный Документы
Культура Документы
As the article name says, learn MVC; so the agenda is simple, we are going to learn
ASP.NET MVC in 7 days.
The way we will learn MVC in this series of articles is by doing labs, looking at detailed
steps of how to achieve those labs, and also looking at demonstrative videos.
This article series is divided into 7 days with 35 hands-on labs and every day we will do 5
labs which will help us achieve our goals.
So get ready for day 1. For day 1, shown below is our agenda. We will start with an
introduction, do a simple Hello World, and finally in the 6th lab, we will create a simple
customer data entry screen using HTML Helper classes.
Lab
No.
1
2
3
Lab description
Here you can watch my .NET interview questions and answers videos on various topics
like WCF, Silverlight, LINQ, WPF, Design Patterns, Entity Framework, etc.
Even though Microsoft has always boasted about how the ASP.NET code-behind is
separate from the UI, in practical sense, its very difficult to decouple ASP.NET codebehind and do unit testing on it.
The ASP.NET code-behind is completely tied up with the ASP.NET HttpContext object
which makes unit testing very difficult. Just think os how to unit test the below ASP.NET
code-behind. How do I create an HttpCcontext object, how do I simulate the sender
and EventArgs objects of the button clicks, etc.
FYI: Many developers talk about mock tests, rhino mocks, etc., but still it is cryptic and
the complication increases with session variables, view data objects, and ASP.NET UI
controls creating further confusion.
As this controller class is a simple .NET class we can reuse and also do unit testing easily.
So lets see how we can create MVC application using MVC template provided by visual
studio.
Visual Studio 2010 or the free Visual Web Developer 2010 Express. These include
the ASP.NET MVC 2 template by default.
Visual Studio 2008 SP1 (any edition) or the free Visual Web Developer 2008
Express with SP1. These do not include ASP.NET MVC 2 by default; you must
also download and install ASP.NET MVC 2 from http://www.asp.net/mvc/.
So once you have all your pre-requisites it is time to start the first lab.
Once you click OK, you have a readymade structure with the appropriate folders where
you can add controllers, models, and views.
Once you add the new controller, you should see some kind of code snippet as shown
below:
Collapse | Copy Code
public class Default1Controller : Controller
{
//
// GET: /Default1/
public ActionResult Index()
{
return View();
}
}
The add view pops up a modal box to enter the view name which will be invoked when
this controller is called as shown in the figure below. For now, keep the view name same
as the controller name and also uncheck the master page check box.
Once you click on the OK button of the view, you should see a simple ASPX page with
the below HTML code snippet. In the below code snippet I have added This is my first
MVC application.
Collapse | Copy Code
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Index</title>
</head>
<body>
<div>
This is my first MVC application
</div>
</body>
</html>
If you append the proper controller on the URL you should be able to see the proper view.
<body>
<div>
<%: ViewData["CurrentTime"] %>
</div>
</body>
Create the class with three properties as shown in the below code snippet.
Collapse | Copy Code
public class Customer
{
private string _Code;
private string _Name;
private double _Amount;
public string Code
{
set
{
_Code = value;
}
get
{
return _Code;
}
}
public string Name
{
get
{
return _Name;
}
set
{
_Name = value;
}
}
The advantage of creating a strong typed view is you can now get the properties of the
class in the view by typing the model and . as shown in the below figure.
Below is the view code which displays the customer property value. We have also put an
if condition which displays the customer as a privileged customer if above 100 and a
normal customer if below 100.
Collapse | Copy Code
<body>
<div>
The customer id is <%= Model.Id %> <br />
The customer Code is <%= Model.CustomerCode %> <br />
<% if (Model.Amount > 100) {%>
This is a priveleged customer
<% } else{ %>
This is a normal customer
<%} %>
</div>
</body>
As soon as the end user enters details and submits data it redirects to a screen as shown
below. If the entered amount is less than 100 it displays normal customer, else it displays
privileged customer.
The advantage of creating a strong typed view is you can now get the properties of the
class in the view by typing the model and . as shown in the below figure.
Below is the view code which displays the customer property value. We have also put an
if condition which displays the customer as a privileged customer if above 100 and
normal customer if below 100.
You should also be able to test above 100 and below 100 scenarios.
The complete HTML code was written manually. In other words, it was less
productive. Its like going back to the dark ages where developers used to write
HTML tags in Notepad.
Collapse | Copy Code
Added to that, a lot of manual code was also written in the controller to flourish
the object and send data to the MVC view.
Collapse | Copy Code
In this lab we will see how to use MVC HTMLHelper classes to minimize manual coding
and increase productivity.
By using the HTMLHelper class you can create any HTML control like TextBox, Label,
ListBox, etc., just by invoking the appropriate function.
In order to create the form tag for HTML we need to use Html.BeginForm. Shown
below is the code snippet for that:
Collapse | Copy Code
<% using (Html.BeginForm("DisplayCustomer","Customer",FormMethod.Post))
{%>
-- HTML input fields will go here
<%} %>
The HTML helper beginform takes three input parameters: action name (method
inside the controller), controller name (actual controller name), and HTTP posting
methodology (POST or GET).
If you want to create a text box, simply use the TextBox function of the HTMLHelper
class as shown in the below code. This way you can create HTML controls using the
HTMLHelper class functions.
Collapse | Copy Code
Enter customer id :- <%= Html.TextBox("Id",Model)%> <br />
The above code snippet will generate the below HTML code:
Collapse | Copy Code
To create a data entry screen like the one shown below, we need to the use the below code
snippet.
[HttpPost]
public ActionResult DisplayCustomer(Customer obj)
{
return View(obj);
}
Lab description
http://youtu.be/KAKxm4eQP24?hd=1
http://youtu.be/1dlxtHuRw34?hd=1
So what we will do in this section is we will create a simple MVC application and we
will do unit test on the ASP.NET application using VSTS unit test framework.
The controller class at the end of the day is a simple .NET class. For instance if you
watch your project code closely, you can easily see the customer controller class as
shown below.
Collapse | Copy Code
public class CustomerController : Controller
{
...
....
public ViewResult DisplayCustomer()
{
Customer objCustomer = new Customer();
objCustomer.Id = 12;
objCustomer.CustomerCode = "1001";
objCustomer.Amount = 90.34;
return View("DisplayCustomer",objCustomer);
}
}
In simple words because this is a simple .NET class we can easily instantiate the class
and create automated unit tests for the same. Thats what exactly we are going to do in
our next steps.
Once you add the references you should see the MVC application in your project
references as shown in the below figure.
[TestMethod]
public void DisplayCustomer()
{
CustomerController obj = new CustomerController();
var varresult = obj.DisplayCustomer();
Assert.AreEqual("DisplayCustomer", varresult.ViewName);
}
On the test view right click on the test and run the selected test
case as shown below.
If everything goes well you should see green color indicating that
the test has passed or else you should see a red color with details
regarding why the test failed.
Introduction
At the end of the day MVC is nothing but URL mapped to controllers and controllers
mapped to actions.
For example when a user sends a request URL like www.questpond.com/locateproduct
from the browser, these actions are mapped with MVC controllers and MVC controllers
finally invokes those functions.
Below is a simple table which shows how the whole thing looks like.
Adding further to the complication we can have multiple URLs mapped to one controller
or you can have more than one controller mapped to a single URL. For instance you can
have www.questpond.com/contactus and www.questpond.com/aboutus mapped to a
single controller called as AboutUsController.
It would be great if we have some kind of mechanism by which we can configure these
mappings. Thats what exactly MVC routing is meant for. MVC routing helps to easily
configure and map the URL with the controllers.
All routing mapping are stored in to a collection called as routes. This collection
belongs to the namespace System.Web.Routing. To add a route you need to call the
MapRoute method and pass three parameters name,url and defaults.
Below is a print screen of the snippet of the maproute function.
Name is the key name by which the route will be identified from the collection.
Url defines what kind of URL format we want to connect with the controllers. For
instance in the below code snippet we are saying that View/ViewCustomer is the URL
format.
Defaults defines the controller class and action functions which will be invoked when
the URL is called. For instance in the below code we are saying that when
View/ViewCustomer is called it will invoke the Customer controller class and the
action function invoked will be DisplayCustomer.
In case your controller takes parameters you can use the {brackets. For instance in the
below code snippet we have used {to specify that we can have id parameter.
If you want to define the parameter as optional you can use the UrlParameter.Optional
enum.
The first thing is comment the default mapping code. We will explain the default
mapping code later.
Collapse | Copy Code
//routes.MapRoute(
// "Default", // Route name
// "{controller}/{action}/{id}", // URL with parameters
// new { controller = "Home", action = "Index", id =
UrlParameter.Optional }); // Parameter defaults
routes.MapRoute(
"View", // Route name
"View/ViewCustomer/{id}", // URL with parameters
new { controller = "Customer", action = "DisplayCustomer",
id = UrlParameter.Optional }); // Parameter defaults
If you remember we commented the default entry route. Lets understand what exactly
this default code meant.
"{controller}/{action}/{id}" defines that URL will be automatically named with the
convention of controller name / function action name / value. So if you have a controller
class with Customer and action function as Search then the URL will be structured as
http://xyz.com/Customer/Search automatically.
Collapse | Copy Code
//routes.MapRoute(
// "Default", // Route name
// "{controller}/{action}/{id}", // URL with parameters
// new { controller = "Home", action = "Index", id =
UrlParameter.Optional }); // Parameter defaults
class Customer
int Id { set; get; }
string CustomerCode { set; get; }
double Amount { set; get; }
}
}
The controller has a simple DisplayCustomer function which displays the customer
using the id value. This function takes the id value and looks up through the customer
collection. Below is the downsized reposted code of the function.
Collapse | Copy Code
[HttpGet]
public ViewResult DisplayCustomer(int id)
{
Customer objCustomer = Customers[id];
return View("DisplayCustomer",objCustomer);
}
In case you are new to regular expression we would advise you to go through this video
on regular expressions http://youtu.be/C2zm0roE-Uc?hd=1
So in order to accommodate the numeric validation we need to the specify the regex
constraint i.e. \d{1,2} in the maproute function as shown below. \d{1,2} in regex
means that the input should be numeric and should be maximum of length 1 or 2 , i.e.
between 0 to 99.
You can specify default values by saying id=0 as shown in the below code snippet. So
just in case if some one does not specify the value to the id it will take the value as zero
by default.
Collapse | Copy Code
routes.MapRoute(
"View", // Route name
"View/ViewCustomer/{id}", // URL with parameters
new { controller = "Customer", action = "DisplayCustomer",
id = 0 }, new { id = @"\d{1,2}" }); // Parameter defaults
If you try to specify value more than 100 you would get error as shown below. Please
note that the error is confusing but its the effect of the regex validation which is specified
on the maproute function.
If you try to specify a non-numeric value you should again get the same error which
confirms that our regex validation is working properly.
The most important point to note is that these validations are executed even before the
request reaches the controller functions.
In the next lab we will look in to how to define outbound URL in MVC views which will
help us to navigate from one page to other page.
Introduction
When we talk about web applications end users would like to navigate from one page to
other page. So as a simple developer your first thought would be to just give page names
as shown in the below figure.
So for example if you want to go and browse from home.aspx to about.aspx give the
anchor hyper link page name and things should be fine.
By doing that you are violating MVC principles. MVC principle says that hit should first
come to the controller but by specifying <a href=Home.aspx> the first hit comes to the
view. This bypasses your controller logic completely and your MVC architecture falls
flat.
Ideally the actions should direct which page should be invoked. So the hyperlink should
have actions in the anchor tags and not the page names i.e. direct view name.
Lets create a simple navigation between these 3 pages as shown below. From the home
view we would like to navigate to about and product view. From about and product view
we would like to navigate back to the home view.
If you want to create the anchor links using the HTML helper classes you can use the
action link function as shown in the below code snippet.
Collapse | Copy Code
The above code was for the products page , you can do the same type of navigations for
the about us and the home page.
Collapse | Copy Code
This is About us
<a href="GotoHome">Go Home</a><br />
While navigating you can see how the URLs are pointing to the actions rather than
absolute page names like home.aspx, aboutus.aspx etc which violates the complete MVC
principle.
Partial views.
Validations using data annotations.
Razor (MVC 3).
MVC Windows authentication
MVC Forms Authentication
In case you are coming to this section directly, please see the previous Labs to synch up.
<body>
<div>
<% Html.RenderPartial("MyView"); %>
</div>
</body>
Also ensure that the partial view is in the same folder where your main view is. In case
its not, then you need to also pass the path in the RenderPartial function. You can see
in the below figure I have moved the partial view in the main Views folder.
One more thing which is noticeable is that the icons for main view and partial are very
different. You can see the yellow border in the partial view icon which does not exist in
the main view icon.
Data annotations are nothing but metadata which you can apply on the model and the
MVC framework will validate using the metadata provided.
In this lab lets enforce validation by using data annotations. So the first thing is use Lab
4 and create a simple model and a strong typed data entry view. In case you have come
to this lab straight, please have a look at day 1 labs before proceeding ahead.
So assuming you have created the model and the strong typed view, lets start applying
data annotations.
Note: The view created should be a strong typed view.
Let's say we have a customer model and we want to ensure that the customer code field is
compulsory. So you can apply the attribute Required as shown in the below code
snippet. If the validation fails and you would like to display some error message, you can
pass the ErrorMessage also.
Collapse | Copy Code
We also need to code our HTML form to input data. Below is the code snippet for the
same. Please note, the EditorForModel function will automatically generate UI
controls looking at the model properties. So we do not need to create control individually
as we did for Lab 4.
<head runat="server">
<script src="<%= Url.Content("~/Scripts/MicrosoftAjax.debug.js") %>"
type="text/javascript"></script>
<script src="<%= Url.Content("~/Scripts/MicrosoftMvcAjax.debug.js") %>"
type="text/javascript"></script>
<script src="<%=
Url.Content("~/Scripts/MicrosoftMvcValidation.debug.js") %>"
type="text/javascript"></script>
<% Html.EnableClientValidation(); %>
</head>
Also note the call to the EnableClientValidation method due to which client side
validations are enabled.
Collapse | Copy Code
In case you want to use a Regular Expression, you can use the RegularExpression
attribute.
Collapse | Copy Code
[RegularExpression(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}")]
public string Email { get; set; }
If you want to check whether the numbers are in range, you can use the Range attribute.
Collapse | Copy Code
[Range(10,25)]
public int Age { get; set; }
Sometimes you would like to compare the values of a field with another field, we can use
the Compare attribute.
Collapse | Copy Code
public string Password { get; set; }
[Compare("Password")]
public string ConfirmPass { get; set; }
In case you want to get a particular error message , you can use the Errors collection.
If you have created the model object yourself you can explicitly call TryUpdateModel in
your controller to check if the object is valid or not.
Collapse | Copy Code
TryUpdateModel(NewCustomer);
In case you want add errors in the controller you can use AddModelError function.
Collapse | Copy Code
ModelState.AddModelError("FirstName", "This is my server-side error.");
In case you are feeling that whatever we have learnt in MVC 2 is a waste, no, not at all.
On the contrary MVC 3 is backwards compatible with MVC 2. So whatever you have
learnt in MVC 2 still holds true in MVC 3.
Now rather than discussing about all the new features lets focus on the biggest feature of
MVC3 which I personally think is a game changer, and that is Razor.
So whats Razor? just to answer short and sweet, its a type of view for MVC. In MVC 2
the default view was ASP.NET pages, i.e., Web form view. Now, the problem of web
form views was that it was not made thinking MVC in mind, so the syntaxes are a bit
heavy.
Developers demanded for a clean, lightweight view and with less syntactic noise: The
answer is Razor.
So lets create a simple lab to demonstrate the use of Razor views.
The Empty option creates a project with the least amount of files.
The Internet Application option creates a shell application which includes user
registration and authentication, navigation, and a consistent visual style.
The Intranet Application option is very much the same as Internet Application
with the only difference that the authentication takes place through a
domain/Active Directory infrastructure.
For now lets keep life simple and lets select the empty option. The second thing we need
to select is what kind of view we want, so lets select Razor and move ahead.
Once the project is created, you can see the Razor file with the name .cshtml. Now the
_ViewStart page is nothing but a common page which will be used by views for
common things like layout and common code.
Step 3: Add a view and invoke the same from the controller
Now go ahead and add a new view and invoke this view from the controller. Adding and
invoking the view from the controller remains the same as discussed in the previous
labs. Just remember to select the view as the Razor view.
@DateTime.Now
If you compare the above syntax with an ASPX view, you need to type the below code.
So isnt the syntax much simpler, neat, and lightweight?
Collapse | Copy Code
<%=DateTime.Now%>
Practice 5: To display @
In case you want to display @ just type it twice as shown in the below code snippet.
The display will be something as shown in the image below.
Tweet me @@Shivkoirala
If you execute the above code you would be surprised to see that it does not display as
HTML but as a simple display as shown below. Now thats not what we expect. We were
expecting a proper HTML display. This is done by Razor to avoid XSS attacks (I will
discuss about that in later sections).
But no worries, the Razor team has taken care of it. You can use the Html.Raw to
display the same as shown in the below code snippet.
Collapse | Copy Code
@{
For now we will not use that option, lets use the empty application option and create
from scratch so that we can understand better.
<authentication mode="Windows"/>
<authorization>
<deny users="?"/>
</authorization>
<appSettings>
<add key="webpages:Version" value="1.0.0.0"/>
<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
<add key="autoFormsAuthentication" value="false" />
<add key="enableSimpleMembership" value="false"/>
</appSettings>
Please note the user should be present in your Windows AD or local user group. Like in
my case Administrator is present in my local Windows user group.
In the next screen it will prompt which dependencies you want to include. For now I
have the Razor view so I have selected both the options.
Once you can see the dependent DLLs been added to the project.
Step 6: Publish
Once you have created the IIS application, its time to publish your application to the web
application folder. So click on Build and Publish as shown in the below figure. I have
used File system as the publish method, you can use your own choice.
If credentials are entered appropriately, you should be able to see the view.
Once we have checked the credentials the next step is to use the famous
FormsAuthentication class and set the cookie saying that this user is proper.
So that in the next request when the user comes he will not be validated again and again.
After the cookie is set redirect to the About view or else just stand on the Index
view.
Collapse | Copy Code
public ActionResult Login(){if ((Request.Form["txtUserName"] == "Shiv")
&& (Request.Form["txtPassword"] == "Shiv@123"))
{
FormsAuthentication.SetAuthCookie("Shiv",true);
return View("About");}else{
return View("Index");}
This is About us
Normally in ASP.NET this login URL points to an ASP.NET page, but in MVC it points
to an action i.e. /Home/Index. This action invokes the login credentials page.
Collapse | Copy Code
<authentication mode="Forms">
<forms loginUrl="~/Home/Index"
timeout="2880"/>
</authentication>