Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
1K views

Developing ASP - Net MVC 4 Web Applications

This module discusses developing ASP.NET MVC 4 models. It covers creating model classes, using data annotations, validating user input, and accessing data using Entity Framework. The module contains lessons on creating MVC models and working with data.
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1K views

Developing ASP - Net MVC 4 Web Applications

This module discusses developing ASP.NET MVC 4 models. It covers creating model classes, using data annotations, validating user input, and accessing data using Entity Framework. The module contains lessons on creating MVC models and working with data.
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 585

 Module 03:

Aspecto destacadoNotaExpandir aspecto destacadoExpandir nota

Developing ASP.NET MVC 4 Models


Contents:
Module Overview

Lesson Creating MVC Models


1:

Lesson Working with Data


2:

Lab: Developing ASP.NET MVC 4 Models

Module Review and Takeaways

Module Overview
Most web applications need to interact with various types of data or objects. An
e-commerce application, for example, helps manage products, shopping carts,
customers, and orders. A social networking application might help manage users,
status updates, comments, photos, and videos. A blog is used to manage blog
entries, comments, categories, and tags. When you write an MVC web
application, you create an MVC model to model the data for your web
application. Within this model, you create a model class for each type of object.
The model class describes the properties of each type of object and can include
business logic that matches business processes. Therefore, the model is a
fundamental building-block in an MVC application and a good place to start
when you write code. Models interact with the information store that underlies
your site, which is usually a database. Therefore, you need to understand data
access techniques and technologies to write models. In this module, you will see
how to create the code for models and access data by using Entity Framework
and LINQ.

Objectives

After completing this module, you will be able to:

Add a model to an MVC application and write code in it to implement the


o
business logic.
o Create a new SQL Azure database to store data for the web application.

Lesson 1 : Creating MVC Models


An MVC model is a collection of .NET Framework classes. When you create a
model class, you define the properties and methods that suit the kind of object the
model class describes. You can describe these properties in code so that MVC
can determine how to render them in a webpage and how to validate user input.
You need to know how to create and describe models, and how to modify the
manner in which MVC creates model class instances when it runs your web
application.

Lesson Objectives
After completing this lesson, you will be able to:

o Describe how to create MVC models and develop business logic.


Use the display and edit data annotations to assign attributes to views and
o
controllers.
o Validate user input with data annotations.
o Describe model binders.
o Describe model extensibility.
o Add a model to an MVC 4 web application.

Developing Models

Every website presents information about various types of objects. In your web
application, you need to define model classes for these objects.

When you implement a functional requirement in your web application, you


usually start by creating a model class. The model class will probably be revised
when you create the controller and views for the model, and then later during the
iterations that happen during the project. If you follow the Agile Development
model or Extreme Programming, you begin with a simple understanding of the
class—perhaps its name and

a few properties. Then, you discuss with users and add details to the planned
model class with the complete set of properties and its relationships to other
classes. When developing the model, you can refer to use cases or user stories to
ensure that these model details are correct.
When you feel that you fully understand the requirements for a model, you can
write model classes to implement the requirements. The following lines of code
illustrate how to create an example model class named Photo.

Example Model Class

public class Photo

public int PhotoID { get; set; }

public string Title { get; set; }

public byte[] PhotoFile { get; set; }

public string Description { get; set; }

public DateTime CreatedDate { get; set; }

public string Owner { get; set; }

public virtual ICollection<Comment> Comments { get; set; }

Notice that the model class does not inherit from any other class. Also, notice
that you have created public properties for each property in the model and
included the data type, such as integer or string in the declaration. You can create
read-only properties by omitting the set; keyword.

The Photo class includes a property called Comments. This is declared as a


collection of Comment objects and implements one side of the relationship
between photos and comments.
The following lines of code illustrate how you can implement the Comment
model class.

Comment Model Class

public class Comment

public int CommentID { get; set; }

public int PhotoID { get; set; }

public string UserName { get; set; }

public string Subject { get; set; }

public string Body { get; set; }

public virtual Photo Photo { get; set; }

Notice that the Comment class includes a PhotoID property. This property
stores the ID of the Photo that the user commented on, and it ties the comment to
a single photo. Also, notice that the Comment class includes a Photo property,
which returns the Photo object that the comment relates to. These properties
implement the other side of the relationship between photos and comments. The
instances of model classes are usually created in a controller action and passed to
a view to display.

The following code example shows how a controller action can create a new
photo object from the photo model class and pass it to the Display view.

Instantiating a Photo in a Controller Action


Photo newPhoto = new Photo();

newPhoto.Title = "This is an Example Photo";

newPhoto.Owner = User.Identity.Name;

newPhoto.CreatedDate = DateTime.Today;

return View("DisplayView", newPhoto);

In the Display view, you can render the Title property of a photo by using the
Model object in the Razor code that you write, as the following code shows.

Rendering a Property from a Model Class

<div id="photo-title">

@Model.Title

</div>

Using Display and Edit Data Annotations on Properties

The model classes usually specify three attributes for each property:

o The name of the property, for example, Title


o The data type of the property, for example, String
The access levels of the property, for example, the get and set keywords to
o
indicate read and write access

Additionally by using attributes, you can supply

additional metadata to describe properties to

ASP.NET MVC. The MVC runtime uses this metadata to determine how to
render each property in views for displaying and editing. These attributes are
called display and edit annotations.

For example, property names in C# cannot contain spaces. On a rendered


webpage, you may often want to include spaces in a property label. For example,
you might want to render a property called CreatedDate with the label Created
Date. To provide MVC with this information, you can use the DisplayName
annotation.

When you use MVC, you can indicate how you want a property to be named on a
view by using the DisplayName annotation, as the following lines of code
illustrate.

Setting the DisplayName Annotation

[DisplayName("Created Date")]

public CreatedDate { get; set; }

If you have a DateTime property, you can use display and edit data annotations
to inform MVC what format you want the property displayed in.

In the following lines of code, the CreatedDate property is a DateTime and the
DisplayFormat data annotation is used to indicate to MVC that only the day,
month, and year values should be displayed.

Setting the DataType and DisplayFormat


[DisplayName("Created Date")]

[DataType(DataType.DateTime)]

[DisplayFormat(DataFormatString = "{0:MM/dd/yy}", ApplyFormatInEditMode =

true)]

public DateTime CreatedDate { get; set; }

All the data annotations that are provided with ASP.NET MVC 4 are included in
the System.ComponentModel.DataAnnotations namespace.

Additional Reading: To read more about all the data annotations provided with
MVC 4, see http://go.microsoft.com/fwlink/?LinkID=288949&clcid=0x409

Question: In the code on the slide, how can you recognize the display and edit
annotations and distinguish them from other code?

Validating User Input with Data Annotations

You can use data annotations in MVC models to set validation criteria for user
input. Input validation is the process by which MVC checks data provided by a
user or a web request to ensure that it is in the right format. The following
example shows a webpage form that collects some information from the user:

o Name. This is required input. The user must enter some data in this field.
o Height. This must be an integer between 0 and 400.
Email Address. This is required input. The value entered must be a valid email
o
address.

In the following example, when the user submits the form, you want MVC to
create a new instance of the Person model and use it to store the data in the
database. However, you want to ensure that the data is valid before it is stored.

To ensure that the data is valid, you can define the Person model class by using
the following lines of code.

Using Validation Data Annotations

public class Person

public int PersonID { get; set; }

[Required]

public string Name { get; set; }

[Range(0, 400)]

public int Height { get; set; }

[Required]

[RegularExpression(".+\\@.+\\..+")]

public string EmailAddress { get; set; }

The Required, Range, StringLength, and RegularExpression annotations


implement input validation in MVC. If users do not enter data that satisfies the
criteria specified for each property, the view displays a standard error message
that prompts the user to enter the correct data. In the earlier example, you can see
that the user must enter a Name and a Height between 0 and 400. For the
EmailAddress property, the user must enter a value that matches the regular
expression. The regular expression in the example is a simple expression that
requires an @ symbol and a dot.

To specify the error message that the user sees when data is not valid, you can
use the ErrorMessage property on the validation data annotations, as the
following code illustrates.

Setting a Validation Error Message

[Required(ErrorMessage="Please enter a name.")]

public string Name { get; set; }

Note: You will see how to ensure that the validation error message is displayed
in a view.

Additional Reading: For more examples of validation data annotations see


http://go.microsoft.com/fwlink/?LinkID=288950&clcid=0x409

Additional Reading: For more information about the regular expressions that
you can use to check user input, see
http://go.microsoft.com/fwlink/?LinkID=288951&clcid=0x409

Question: You want to ensure that users enter a password that is longer than six
characters. How should you do this by using a validation data annotation?

What Are Model Binders?


A model binder is a component of an ASP.NET MVC application that creates an
instance of a model class, based on the data sent in the request from the web
browser. ASP.NET MVC includes a default model binder that meets the needs of
most web applications. However, you must know how the default model binder
works with other components to use it properly. In addition, you may choose to
create a custom model binder for advanced situations.

What Does a Model Binder Do?

A model binder ensures that the right data is sent

to the parameters in a controller action method. This enables MVC to create


instances of model classes that satisfy the user’s request. The default model
binder, for example, examines both the definition of the controller action
parameters and the request parameters to determine which request values to pass
to which action parameter.

This model binding process can save developers a lot of time and avoid many
unexpected run-time errors that arise from incorrect parameters. MVC includes a
default model binder with sophisticated logic that passes parameters correctly in
almost all cases without complex custom code.

The Controller Action Invoker and the Default Model Binder

To understand the default model binding process, consider the following request
from a web browser:
http://www.adventureworks.com/product/display/45

This request identifies three aspects:

o The model class that interests the user. The user has requested a product.
The operation to perform on the model class. The user has requested that the
o
product be displayed.
The specific instance of the model class. The user has requested that the
o
product with ID 45 be displayed.

The request is received by an object called the controller action invoker. The
controller action invoker of the MVC runtime calls a controller action and passes
the correct parameters to it. In the example, the action invoker calls the Display
action in the Product controller and passes the ID “45” as a parameter to the
action, so that the right product can be displayed.

The ControllerActionInvoker class is the default action invoker. This action


invoker uses model binders to determine how parameters are passed to actions.

How the Default Model Binder Passes Parameters

In a default MVC application, there is only one model binder for the
ControllerActionInvoker to use. This binder is an instance of the
DefaultModelBinder class. The default model binder passes parameters by
using the following logic:

The binder examines the definition of the action that it must pass parameters
1. to. In the example, the binder determines that the action requires an integer
parameter called PhotoID.
The binder searches for values in the request that can be passed as parameters.
In the example, the binder searches for integers because the action requires an
integer. The binder searches for values in the following locations, in order:
2.
Form Values. If the user fills out a form and clicks a submit button, you can
a.
find parameters in the Request.Form collection.
Route Values. Depending on the routes that you have defined in your web
application, the model binder may be able to identify parameters in the
b.
URL. In the example URL, “45” is identified as a parameter by the default
MVC route.
Query Strings. If the user request includes named parameters after a
c. question mark, you can find these parameters in the Request.QueryString
collection.
Files. If the user request includes uploaded files, these can be used as
d.
parameters.

Notice that if there are form values and route values in the request, form values
take precedence. Query string values are only used if there are no form values
and no route values available as parameters.

Model Extensibility

The MVC architecture has been designed to provide extensibility so that


developers can adapt the architecture to unusual or unique requirements. For
example, the default action invoker, ControllerActionInvoker, can be replaced
by your own action invoker if you want to implement your own invoking logic.

Two ways in which you can extend the MVC handling of MVC models are to
create custom data annotations and custom model binders.

Custom Validation Data Annotations


You can use data annotations to indicate to MVC how to validate the data that a
user enters in a form or passes in query strings. The four built-in validation
attributes in MVC 4, Required, Range, StringLength, and RegularExpression,
are very flexible. However, in some situations, such as the following examples,
you may want to run some custom validation code:

Running a Data Store Check. You want to check the data entered against data
o
that has already been stored in the database or in another database store.
o Comparing Values. You want to compare two entered values with each other.
Mathematical Checks. You want to calculate a value from the entered data and
o
check that value is valid.

In such situations you can create a custom validation data annotation. To do this,
you create a class that inherits from the
System.ComponentModel.DataAnnotations.ValidationAttribute class.

The following lines of code illustrate how to create a custom validation data
annotation.

Creating Custom Validation Data Annotation

[AttributeUsage(AttributeTargets.Field)]

public class LargerThanValidationAttribute : ValidationAttribute

public int MinimumValue { get; set; }

//Constructor

public LargerThanValidationAttribute (int minimum)

MinimumValue = minimum;
}

//You must override the IsValid method to run your test

public override Boolean IsValid (Object value)

var valueToCompare = (int)value;

if (valueToCompare > MinimumValue)

return true;

else

return false;

After you have created a custom validation data attribute, you can use it to
annotate a property in your model, as the following lines of code illustrate.

Using a Custom Validation Data Annotation

[LargerThanValidationAttribute(18)]
public VoterAge { get; set; }

Custom Model Binders

The default controller action invoker receives requests and calls the right action
on the right controller to fulfill the request. The default action invoker uses model
binders to identify parameters in the request and pass all of them to the right
parameters in the action. This mechanism ensures that query strings, route values,
form values, and uploaded files are available for the action to work with.

The default model binder is sophisticated and flexible, but sometimes, you may
want to customize its behavior to pass parameters in an unusual way. You can do
this by creating a custom model binder and registering it with the MVC runtime.

The following lines of code show how to create a simple custom model binder to
pass parameters from the form collection by implementing the IModelBinder
interface.

A Simple Custom Model Binder

public class CarModelBinder : IModelBinder

public object BindModel (ControllerContext controllerContext,

ModelBindingContext

bindingContext)

//Get the color for the car from the request form

string color = controllerContext.HttpContext.Request.Form["color"];

//Get the brand for the car from the request form
string brand= controllerContext.HttpContext.Request.Form["brand"];

//Create a new instance of the car model

Car newCar = new Car();

newCar.color = color;

newCar.brand = brand;

//return the car

return newCar;

The code example assumes that you have a model class in your MVC application
called, Car. It also assumes that any request for a Car object includes values for
color and brand in the form collection. This situation can easily be handled by
the default model binder. However, this example demonstrates how model
binders can locate values from the context of the request and pass those values to
the right properties in the model. You can add custom code to implement extra
functionality.

Additional Reading: You can see more examples of custom model binders at
the following locations:

o http://go.microsoft.com/fwlink/?LinkID=288952&clcid=0x409
o http://go.microsoft.com/fwlink/?LinkID=288953&clcid=0x409

Question: You want to ensure that when a user types a value into the Car Model
Number box when adding a new car to the website, the text entered is not already
used by another car in the database. Would you use a custom validation data
annotation or a custom model binder for this?
Demonstration: How to Add a Model
In this demonstration, you will see how to create a model in an ASP.NET MVC 4
web application and add model classes to the web application. You will also see
how to add data annotations and create a custom validation data annotation.

Demonstration Steps
On the File menu of the Start Page - Microsoft Visual Studio window,
1.
point to New, and then click Project.
In the navigation pane of the New Project dialog box, expand Installed,
2.
expand Templates, and then expand Visual C#.
Under Visual C#, click Web, and then, in the result pane, click ASP.NET
3.
MVC 4 Web Application.
4. In the Name box of the New Project dialog box, type OperasWebSites.
5. In the New Project dialog box, click Browse.
In the Location text box, navigate to Allfiles (D):\Democode\Mod03, and
6.
then click Select Folder.
7. In the New Project dialog box, click OK.
In the Select a Template list of the New ASP.NET MVC 4 Project dialog
8.
box, click Empty, and then click OK.
In the Solution Explorer pane of the OperasWebSite - Microsoft Visual
9.
Studio window, right-click Models, point to Add, and then click Class.
In the Name box of the Add New Item - OperasWebSites dialog box, type
10.
Opera.cs, and then click Add.
In the Opera class of the Opera.cs code window, type the following code.

public int OperaID { get; set; }

11. public string Title { get; set; }

public int Year { get; set; }


public string Composer { get; set; }
Place the mouse cursor at the end of the OperaID property code, press Enter,
and then type the following code.

12. [Required]

[StringLength(200)]

In the Required data annotation, right-click Required, point to Resolve, and


13.
then click using System.ComponentModel.DataAnnotations.
Place the mouse cursor at the end of the Year property, press Enter, and then
type the following code.
14.
[Required]

Place the mouse cursor at the end of the Opera class, press Enter, and then
type the following code.

public class CheckValidYear : ValidationAttribute


15.
{

In the CheckValidYear class, type the following code.

public override bool IsValid(object value)

16.
int year = (int)value;

if (year < 1598)

{
return false;

else

return true;

In the CheckValidYear class, type the following code.

public CheckValidYear()

17. ErrorMessage = "The earliest opera is Daphne, 1598, by Corsi, Peri,

and

Rinuccini";

In the Opera class, place the mouse cursor at the end of the Title property
code, press Enter, and then type the following code.
18.

[CheckValidYear]
On the Build menu of the OperasWebSites - Microsoft Visual Studio
19. window, click Build Solution, and then note that the application is being
built.
In the OperasWebSites - Microsoft Visual Studio window, click the Close
20.
button.
Lesson 2: Working with Data
All web applications present information and almost all web applications require
a data store for that information. By rendering webpages by using data from a
data store, you can create a web application that changes continually in response
to user input, administrative actions, and publishing events. The data store is
usually a database, but other data stores are occasionally used. In MVC
applications, you can create a model that implements data access logic and
business logic. Alternatively, you can separate business logic, in model classes,
from data access logic, in a repository. A repository is a class that a controller
can call to read and write data from and to a data store. The .NET Framework
includes the Entity Framework and LINQ technologies, which make data access
code very quick to write and simple to understand. In addition, you will see how
to build a database-driven website in MVC.

Lesson Objectives
After completing this lesson, you will be able to:

o Connect an application to a database to access and store data.


o Describe the features of the Entity Framework.
o Use LINQ to write queries for selecting, filtering, and grouping data.
Create separate model classes and corresponding repository classes by using
o
Entity Framework code.
o Explain how to access data in models and repositories.

Connecting to a Database
Most websites use a database to store dynamic data. By including this data in
rendered HTML pages, you can create a dynamic web application with content
that changes frequently. For example, you can provide administrative webpages
that enable company employees to update the product catalog and publish news
items. Products and items are stored in the database. As soon as they are stored,
users can view and read them. The employees do not need to edit HTML or
republish the website to make their changes visible.

Some websites may store data in other locations, such as a directory service, but
databases are the most widely used data store.

ADO.NET and Databases

When you create .NET Framework applications, including MVC web


applications, you can use the ADO.NET technology to access databases.
ADO.NET classes are contained in the System.Data namespace. ADO.NET
supports a wide range of databases by using different data providers. For
example:

Microsoft SQL Server. This is an industry-leading database server from


o Microsoft. ADO.NET includes the SqlClient provider for all SQL Server
databases.
Microsoft SQL Server Express. This is a free version of SQL Server that
o
includes a wide range of database functionality and is very flexible. Some
advanced capabilities, such as database clustering, are not possible with SQL
Express. The SqlClient provider is used for SQL Express.
Microsoft SQL Server Compact. This version of SQL is also free and uses .sdf
o files to store data on the hard disk. ADO.NET includes the SqlServerCe
provider for SQL Compact databases.
Oracle Databases. This is a widely-used database server. ADO.NET includes
o
the OracleClient provider for all Oracle databases.
OLE DB. This is a standard that many different databases adhere to. ADO.NET
o
includes the OleDb provider for all OLE DB databases.
ODBC. This is another older standard that many different databases adhere to.
ADO.NET includes the Odbc provider for all ODBC databases. In general, you
o
should use an OLE DB provider, if it is available, instead of an ODBC
provider.

You can also use third-party ADO.NET providers to access other databases.

Cloud Databases

The database of a web application is usually located on the same server as the
web application itself or on a dedicated database server at the same physical site.
However, if you have a fast, reliable Internet connection, you can consider using
a cloud database. Furthermore, if you have chosen to host a web application in
the cloud, a cloud database is a logical storage solution. The Microsoft cloud
database service is called SQL Database and is a part of Windows Azure.

Windows Azure SQL Database has the following advantages:

Databases run in Microsoft data centers with the best connectivity and
o
reliability.
o Microsoft guarantees up to 99% uptime.
You do not need to build and maintain your own database servers or employ
o
database administrators.
o You can scale up the databases very easily.
o You pay only for the data that you use and distribute.
You can use Windows Azure SQL Database with ADO.NET by using the
SqlClient provider.

Connecting an MVC Web Application to a Database

To use ADO.NET and connect to a database, you need to add two items to your
application:

o Add a reference to the System.Data namespace.


Add a connection string to the Web.config file. This string specifies the
o provider, the location of the database, the security properties, and other
properties depending on the provider.

The following markup shows how to add a connection string to Web.config to


connect to a SQL Express database called, PhotoSharingDB, by using the
credentials that the web application runs under.

Connecting to SQL Express

<connectionStrings>

<add name="PhotoSharingDB"

connectionString="Data Source=.\SQLEXPRESS;Initial

Catalog=PhotoSharingDB;" +

"Integrated Security=SSPI"

providerName="System.Data.SqlClient"/>

</connectionStrings>

The following connection string connects to a Windows Azure SQL database.

Connecting to Windows Azure SQL Database


<connectionStrings>

<add name="PhotoSharingDB"

connectionString="Server=tcp:example.database.windows.net,1433;Database=P

hotoSharingDB;"

"User ID=Admin@example;Password=Pa$$w0rd;Trusted_Connection=False;" +

"Encrypt=True;Connection Timeout=30;PersistSecurityInfo=true"

providerName="System.Data.SqlClient"/>

</connectionStrings>

The <connectionStrings> tag must appear within the <configuration> tag, after
the <configSections> tag.

Additional Reading: The MVC web application templates in Microsoft Visual


Studio 2012 include ADO.NET references so you need not add them. However,
you must add connection strings. Some of the templates, such as the Internet site
template, include SQL Server Express membership databases with connection
strings.

The Entity Framework


Developers write code that works with classes and objects. By contrast, databases
store data in tables with columns and rows. Database administrators create and
analyze databases by running Transact-SQL queries. You can choose to build and
run Transact-SQL queries in your ADO.NET code. However, ADO.NET
includes the Entity Framework—this technology enables you to read and write
data to and from a database by using classes and objects.

Entity Framework is an Object Relational Mapping (ORM) framework. An ORM


framework maps the

tables and columns found in a database to objects and their properties that you
can call from .NET code.

Entity Framework Workflows

The way you use Entity Framework in your application depends on the manner in
which you want to build your database. The three Entity Framework workflows
available are database-first, model-first, and code-first:

Database First. You can use the database-first workflow when you have a pre-
existing database or if you prefer to create a new database by defining table,
columns, views, and other database schema objects. In this workflow, Entity
o Framework examines the database and creates an XML file with an .edmx
extension called the model file. The model file describes classes that you will
be able to work with, in code. You can adjust the model by using a designer in
Visual Studio and then writing code against the Entity Framework classes.
Model First. You can use the model-first workflow when you do not yet have a
database and you prefer to design your model by using an ORM modeling tool.
In this workflow, you create the .edmx file in the Visual Studio designer and
then write code against the model classes generated by the designer. When you
o
run the application, Entity Framework creates the database tables and columns
to support the model. In this workflow, Visual Studio can also create a
connection string for you and insert it into Web.config, based on the database
that you specify.
Code First. You can use the code-first workflow if you prefer to create a model
by writing .NET Framework classes. In this workflow, there is no model file.
o
Instead, you create model classes in C# or Visual Basic. When you run the
application, Entity Framework creates the database.

Adding an Entity Framework Context

When you use Entity Framework in the code-first workflow, you must ensure
that the framework creates the right database and tables to store your model
classes. To do this, create a class that inherits the Entity Framework DbContext
class. You will use this class in controllers when you want to manipulate data in
the database. Within this class, add a DbSet<> property for each database table
you want Entity Framework to create in the new database.

The following code shows how to add an Entity Framework context to your
model.

An Entity Framework Context Class

public class PhotoSharingDB : DbContext

public DbSet<Photo> Photos { get; set; }

public DbSet<Comment> Comments { get; set; }


}

In the earlier example, Entity Framework looks for a connection string with the
name, PhotoSharingDB, to match the name of the DbContext class. Entity
Framework creates the database at the location that the connection string
provides, and creates two tables in the new database:

Photos: This table will have columns that match the properties of the Photo
o
model class.
Comments: This table will have columns that match the properties of the
o
Comment model class.

Question: You have a Microsoft Visio diagram, which a business analyst created
that shows all the model classes for your web application and their relationships.
You want to re-create this diagram in Visual Studio. Which Entity Framework
workflow should you use?

Using an Entity Framework Context

Now that you have defined the Entity Framework context and model classes, you
can use them in MVC controllers to pass data to views for display.

The following code shows how to use the Entity Framework context in a
controller to pass a single photo, or a collection of photos, to views.

Using an Entity Framework Context in a Controller


public class PhotoController : Controller

//Creating a reference to the Entity

Framework context class

private PhotoSharingDB db = new PhotoSharingDB();

//This action gets all the photos in the database and passes them to

the Index view

public ActionResult Index()

return View("Index", db.Photos.ToList());

//This action gets a photo with a particular ID and passes it to the

Details view

public ActionResult Details(int id = 0)

Photo photo = db.Photos.Find(id);

if (photo == null)

return HttpNotFound();

return View("Details", photo);

}
}

Using Initializers to Populate Databases

If you are using the code-first or model-first workflow, Entity Framework creates
the database the first time you run the application and access data. The database
remains empty if you have created the database schema but not populated it with
data rows.

You can use an initializer class to populate the database with sample data. This
technique ensures that there is sample data to work with, during development.

The following lines of code show how to create an initializer class that adds two
Photo objects to the Photos table in the database.

An Example Entity Framework Initializer

public class PhotoSharingInitializer : DropCreateDatabaseAlways

<PhotoSharingDB>

//Override the Seed method to populate the database

protected override void Seed(PhotoSharingDB context)

//Create a list of Photo objects

var photos = new List<Photo>

new Photo {
Title = "My First Photo",

Description = "This is part of the sample data",

UserName = "Fred"

},

new Photo {

Title = "My Second Photo",

Description = "This is part of the sample data",

UserName = "Sue"

};

//Add the list of photos to the database and save changes

photos.ForEach(s => context.Photos.Add(s));

context.SaveChanges();

After you have created an initializer, you need to ensure that it runs by adding a
line of code to the Global.asax file in the Application_Start method, as the
following example illustrates.

Running the Initializer in Global.asax

protected void Application_Start()


{

//Seed the database with sample data for development. This code should

be removed for

production.

Database.SetInitializer<PhotoSharingDB>(new

PhotoSharingInitializer());

Question: You have created an Entity Framework context class in your model,
added an initialize, and called Database.SetInitializer() from Global.asax. When
you run the application, no database is created and no model objects displayed on
the webpages. What have you forgotten to do?

Using LINQ to Entities

Language Integrated Query (LINQ) is a set of extensions to Visual C# and Visual


Basic that enable you to write complex query expressions.

You can use these expressions to extract data from databases, enumerable
objects, XML documents, and other data sources. The expressions are similar to
Transact-SQL queries, but use C# or VB keywords so that you may get
IntelliSense support and error checking in Visual Studio.
What Is LINQ to Entities?

LINQ to Entities is the version of LINQ that works

with Entity Framework. LINQ to Entities enables you to write complex and
sophisticated queries to locate specific data, join data from multiple objects,
update data, and take other actions on objects from an Entity Framework context.
If you are using Entity Framework, you can write LINQ queries wherever you
require a specific instance of a model class, a set of objects, or for more complex
application needs. You can write LINQ queries in query syntax, which resembles
SQL syntax, or method syntax, in which operations such as “select” are called as
methods on objects.

Example LINQ Queries

In the following lines of code, you can see how to obtain a list of the most recent
photos in the database. Both query syntax and method syntax examples are
included.

Using LINQ to Get Recent Photos

//This list will store the photos that are returned

List<Photo> photos;

//This is the Entity Framework context

PhotoSharingDB context = new PhotoSharingDB();

if (number == 0)

//If a number of photos is not specified, we’ll get all the photos in

the database
//This example is in method syntax.

photos = context.Photos.ToList();

else

//The number specifies how many of the most recent photos the user

requests

//Use a LINQ query with both query and method syntax to get these from

the database

photos = (from p in context.Photos

orderby p.CreatedDate descending

select p).Take(number).ToList();

Additional Reading: To read many more example LINQ queries, see


http://go.microsoft.com/fwlink/?LinkID=288954&clcid=0x409

Demonstration: How to Use Entity Framework Code


In this demonstration, you will see how to add a connection string, an Entity
Framework context, and an initializer to the web application.

Demonstration Steps
In the Solution Explorer pane of the OperasWebSite - Microsoft Visual
1.
Studio window, click web.config.
In the web.config code window, place the mouse cursor at the end of the
</appsettings> tag, press Enter, and then type the following code.

<connectionStrings>

<add name="OperasDB"

connectionString=

"Data Source=(LocalDB)\v11.0;" +

2. "AttachDbFilename=" +

"|DataDirectory|\Operas.mdf;" +

"Integrated Security=True"

providerName=

"System.Data.SqlClient" />

</connectionStrings>

In the Solution Explorer pane of the OperasWebSite - Microsoft Visual


3. Studio window, right-click References, and then click Manage NuGet
Packages.
In the OperasWebSite - Manage NuGet Packages window, click Online,
4.
click EntityFramework, and then click Install.
5. On the License Acceptance page, click I Accept.
6. In the OperasWebSite - Manage NuGet Packages window, click Close.
7. In the Microsoft Visual Studio dialog box, click Yes to All.
In the Solution Explorer pane, right-click Models, point to Add, and then
8.
click Class.
In the Name box of the Add New Item - OperasWebSite dialog box, type
9.
OperasDB, and then click Add.
In the OperasDB.cs code window, locate the following code.
10.
using System.Web;

Place the mouse cursor at the end of the located code, press Enter, and then
type the following code.
11.
using System.Data.Entity;

In the OperasDB.cs code window, locate the following code.


12.
public class OperaDB

Append the following code to the existing line of code.


13.
: DbContext

In the OperaDB class, type the following code.

14. public DbSet<Opera> Operas

{ get; set; }

In the Solution Explorer pane, right-click Models, point to Add, and then
15.
click Class.
In the Name box of the Add New Item - OperasWebSite dialog box, type
16.
OperasInitializer, and then click Add.
In the OperasInitializer.cs code window, place the mouse cursor at the end of
the System.web namespace code, press Enter, and then type the following
17. code.

using System.Data.Entity;

In the OperasInitializer.cs code window, locate the following code.


18.
public class OperasInitializer

Append the following code to the existing line of code.

19. : DropCreateDatabaseAlways

<OperasDB>

In the OperasInitializer class code block, type the following code, press
Spacebar, and then click, Seed(OperasDB context).
20.
override

In the Seed method, place the mouse cursor after the call to base.Seed, press
Enter, and then type the following code.

var operas = new List<Opera>

new Opera {

Title = "Cosi Fan Tutte",

21. Year = 1790,

Composer = "Mozart"

};

operas.ForEach(s =>

context.Operas.Add(s));
context.SaveChanges();

On the Build menu of the OperasWebSite - Microsoft Visual Studio


22. window, click Build Solution, and then note that the application is built
successfully.
In the Solution Explorer pane, right-click Controllers, click Add, and then
23.
click Controller.
24. In the Controller Name box, type OperaController.
In the Template box, click MVC controller with read/write actions and
25.
views, using Entity Framework.
26. In the Model Class box, click Opera (OperasWebSite.Models).
In the Data context class box, click OpersDB (OperasWebSite.Models),
27.
and then click Add.
In the Solution Explorer pane, in the Views/Operas folder, double-click
28.
Create.cshtml.
In the Create.cshtml code window, locate and delete the following code.

@section Scripts {

29.
@Script.Render("~/bundles/jqueryval")

On the DEBUG menu of the OperasWebSite - Microsoft Visual Studio


window, click Start Debugging
30.
Note: The Internet Explorer window is displayed with an error message. The
error message is expected because the home page view has not been added
In the Address bar of the Internet Explorer window, append the existing URL
31.
with opera/index and then click the Go to button.
32. On the Index page, click Create New.
In the Title box of the result page, type Carmen, and then, in the Year box,
33.
type 1475.
In the Composer box, type Bizet, and then click Create.
34.
Note: An error message is displayed by the custom validator.
35. In the Year box, type 1875, and then click Create.
36. In the Internet Explorer window, click the Close button.
In the OperasWebSite - Microsoft Visual Studio window, click the Close
37.
button.

Data Access in Models and Repositories

In MVC applications, you can place the data access code in the model, along
with the business logic. However, many software architects prefer to separate
these two types of code because they serve different purposes:

Business Logic. This code defines the objects that the web application manages,
o
their properties, and their relationships with each other.
Data Access Logic. This code defines the operations necessary to persist data to
a

database. This includes operations to


o
create new records, read records, update records, and delete records in database
tables. A single object in the business logic layer may take data from multiple
database tables. This abstraction is handled by the data access logic.
MVC does not require you to separate business and data access logic, and you
can create MVC model classes that implement both layers. This is often done in
small or simple web applications with small development teams. In these
scenarios, Entity Framework classes are used directly in the model classes.

In more complex situations, you need to place the business logic in MVC model
classes and place the data access logic in dedicated classes called repositories.
When you take this approach, model classes are independent of the database
structure and do not include code that depends on database table names, column
names, or view names. This approach makes it easier to redesign the database or
move to a different data store or data access technology, without the need to re-
code your entire application. Using this approach, you employ the Entity
Framework in your repository classes, but not in your model classes.

How to Separate Model Classes and Repositories

If you do choose to separate business logic and data access logic, you must take
the following steps for each model class:

Define an interface for the repository class. This interface declares the methods
1.
that the repository class uses to read and write data from and to the database.
Create and write code for the repository class. This class must implement all
2.
the data access methods declared in the interface.
3. Remove all data access code from the model class.
Modify the controller class to use the repository class. Instead, create an
4.
instance of the repository class and call its methods to create the model.

A Simple Example Model Class and Repository Class

To illustrate how to separate model classes and repository classes, the following
examples implement a comment on a photo.

The Comment model class helps users to comment on a photo, as the following
lines of code illustrate.
The Comment Model Class

public class Comment

public int CommentID { get; set; }

public int PhotoID { get; set; }

public string CommentText { get; set; }

public virtual Photo Photo { get; set; }

This interface for a comment repository class defines just one method to get the
comments for a given photo, as the following lines of code illustrate.

The ICommentRepository Interface

public interface ICommentRepository {

ICollection<Comment> GetComments (int PhotoID);

The CommentRepository class implements the GetComments method as the


following lines of code illustrate.

The CommentRepository Class

public class CommentRepository : ICommentRepository

public ICollection<Comment> GetComments(int PhotoID)


{

//Implement entity framework calls here.

The CommentsController class uses the repository class, instead of calling


Entity Framework methods, as the following lines of code illustrate.

The CommentsController Class

public class CommentsController : Controller

ICommentRepository commentRepository = new CommentRepository;

public ActionResult DisplayCommentsForPhoto (int PhotoID)

//Use the repository to get the comments

ICollection<Comments> comments =

commentRepository.GetComments(PhotoID);

return View("DisplayComments", comments);

}
Note: By using the ICommentRepository interface, the code makes it easy to
replace CommentRespository with another implementation if you need to.
However, the CommentController code still creates a CommentRespository
object. You have to modify the object to make the replacement.

In an even better architecture, you can replace CommentRepository with a


different implementation of ICommentRepository without any changes to the
CommentController class. This is an extremely flexible and adaptable approach
and is called a loosely coupled architecture.

Loosely coupled architectures are also essential for unit testing.

Lab: Developing ASP.NET MVC 4 Models


Scenario

You are planning to create and code an MVC model that implements your plan
for photos and comments in the Adventure Works photo sharing application. The
model must store data in a Windows Azure SQL database and include properties
that describe photos, comments, and their content. The model must enable the
application to store uploaded photos, edit their properties, and delete them in
response to user requests.

Objectives

After completing this lab, you will be able to:

o Create a new ASP.NET MVC 4 project in Visual Studio 2012.


Add a new model to the ASP.NET MVC 4 web application and add properties
o
to the model.
Use display and edit data annotations in the MVC model to assign property
o
attributes to views and controllers.
Use Visual Studio to create a new Windows Azure SQL database and connect
o
to the database.
o Add Entity Framework code to the model classes in the MVC model.
Use display and edit data annotations in the MVC model to assign property
o
attributes to views and controllers.

Estimated Time: 30 minutes

Virtual Machine: 20486B-SEA-DEV11

Username: Admin

Password: Pa$$w0rd

Note: In Hyper-V Manager, start the MSL-TMG1 virtual machine if it is not


already running.

Exercise 1: Creating an MVC Project and Adding a Model

Scenario

In this exercise, you will:

o Create a new MVC 4 web application in Visual Studio 2012.


o Add model classes to the web application.

The main tasks for this exercise are as follows:

1. Create a new MVC project.


2. Add a new MVC model.

Task 1: Create a new MVC project.

Start the virtual machine, and log on with the following credentials:

1. o Virtual Machine: 20486B-SEA-DEV11


o User name: Admin
o Password: Pa$$w0rd
Start Visual Studio 2012 and create a new ASP.NET MVC 4 web application
by using the following information:

o Name: PhotoSharingApplication
2. o Location: Allfiles (D):\Labfiles\Mod03
o Solution name: PhotoSharingApplication
o Create directory for solution: True
o Project template: Empty

Task 2: Add a new MVC model.

Add a new model class to the PhotoSharingApplication project by using the


following information:
1.
o Class name: Photo
Add another model class to the PhotoSharingApplication project by using the
following information:
2.
o Class name: Comment

Results: After completing this exercise, you will be able to create an MVC 4 web
application and add model classes to the web application.

Exercise 2: Adding Properties to MVC Models

Scenario

In this exercise, you will:

o Add properties to the Photo and the Comment model classes.


o Implement a relationship between model classes.

The main tasks for this exercise are as follows:

1. Add properties to the Photo model class.


2. Add properties to the Comment model class.
3. Implement a relationship between model classes.

Task 1: Add properties to the Photo model class.

Add a primary key property to the Photo model class by using the following
information:

1. o Scope: public
o Property name: PhotoID
o Data type: integer
o Access: Read and write
Add a title property to the Photo model class by using the following
information:

2. o Scope: public
o Property name: Title
o Data type: string
o Access: Read and write
Add an image property to the Photo model class and store the MIME type of
image by using the following information:

o Scope: public
3. o Property names: PhotoFile, ImageMimeType
o Data type for the image: byte []
o Data type for MIME type: string
o Access: Read and write
Add a description property to the Photo model class by using the following
information:

4. o Scope: public
o Property name: Description
o Data type: String
o Access: Read and write
Add a date property to the Photo model class by using the following
information:

5. o Scope: public
o Property name: CreatedDate
o Data type: DateTime
o Access: Read and write
Add a user name property to the Photo model class by using the following
information:

6. o Scope: public
o Property name: UserName
o Data type: string
o Access: Read and write

Task 2: Add properties to the Comment model class.

Add a primary key to the Comment model class by using the following
information:

1. o Scope: public
o Property name: CommentID
o Data type: integer
o Access: Read and write
Add a PhotoID property to the Comment model class by using the following
information:

2. o Scope: public
o Property name: PhotoID
o Data type: integer
o Access: Read and write
Add a user name property to the Comment model class by using the following
information:

3. o Scope: public
o Property name: UserName
o Data type: string
o Access: Read and write
Add a subject property to the Comment model class by using the following
information:

4. o Scope: public
o Property name: Subject
o Data type: string
o Access: Read and write
Add a body text property to the Comment model class by using the following
information:

5. o Scope: public
o Property name: Body
o Data type: string
o Access: Read and write

Task 3: Implement a relationship between model classes.

Add a new property to the Photo model class to retrieve comments for a given
photo by using the following information:

o Scope: public
1. o Property name: Comments
o Data type: a collection of Comments
o Access: Read and write
o Include the virtual keyword
Add a new property to the Comment model class to retrieve the photo for a
given comment by using the following information:

o Scope: public
2. o Property name: Photo
o Property type: Photo
o Access: Read and write
o Include the virtual keyword

Results: After completing this exercise, you will be able to add properties to
classes to describe them to the MVC runtime. You will also implement a one-to-
many relationship between classes.

Exercise 3: Using Data Annotations in MVC Models

Scenario

In this exercise, you will:

Add data annotations to the properties to help MVC web application render
o
them in views and validate user input.

The main tasks for this exercise are as follows:

1. Add display and edit data annotations to the model.


2. Add validation data annotations to the model.

Task 1: Add display and edit data annotations to the model.


Add a display data annotation to the Photo model class to ensure that the
1.
PhotoFile property is displayed with the name, Picture.
Add an edit data annotation to the Photo model class that ensures the
2.
Description property editor is a multiline text box.
Add the following data annotations to the Photo model class to describe the
3. CreatedDate property:
o Data type: DateTime
o Display name: Created Date
o Display format: {0:MM/dd/yy}
Add an edit data annotation to the Comment model class that ensures that the
4.
Body property editor is a multiline text box.

Task 2: Add validation data annotations to the model.

Add a validation data annotation to the Photo model class to ensure that the
1.
users complete the Title field.
Add validation data annotations to the Comment model class to ensure that the
2. users complete the Subject field and enter a string with a length shorter than
250 characters.

Results: After completing this exercise, you will be able to add property
descriptions and data annotations to the two model classes in the MVC web
application.

Exercise 4: Creating a New Windows Azure SQL Database

Scenario

In this exercise, you will:

Add Entity Framework code to the Photo Sharing application in code-first


o
mode.
o Create a new SQL database in Windows Azure.
o Use the SQL database to create a connection string in the application.

The main tasks for this exercise are as follows:

1. Add an Entity Framework Context to the model.


2. Add an Entity Framework Initializer.
3. Create a Windows Azure SQL database and obtain a connection string.
Task 1: Add an Entity Framework Context to the model.

Use the NuGet Package Manager to add Entity Framework 5.0 to the
1.
application.
Add a new class called PhotoSharingContext to the Models folder and ensure
2.
that the new class inherits the System.Data.Entity.DbContext class.
Add public DbSet properties to Photos and Comments to enable Entity
3.
Framework to create database tables called Photos and Comments.

Task 2: Add an Entity Framework Initializer.


Add a new class called PhotoSharingInitializer to the Models folder and ensure
that the new class inherits the DropCreateDatabaseAlways
1.
<PhotoSharingContext> class.
Open the getFileBytes.txt file from the following location and add all the text
of the file as a new method to the PhotoSharingInitializer class:
2.
o File path: Allfiles (D):\Labfiles\Mod03\CodeSnippets
3. Override the Seed method in the PhotoSharingInitializer class.
Create a new list of Photo objects in the Seed method. The list should contain
one photo object with the following properties:

o Title: Test Photo


4. o Description: <A description of your choice>
o UserName: NaokiSato
o PhotoFile: getFileBytes("\\Images\\flower.jpg")
o ImageMimeType: image/jpeg
o CreatedDate: <Today’s date>
Add each photo object in the photos list to the Entity Framework context and
5.
then save the changes to the context.
Create a new list of Comment objects in the Seed method. The list should
6. contain one Comment object with the following properties:
o PhotoID: 1
o UserName: NaokiSato
o Subject: Test Comment
o Body: This comment should appear in photo 1
Add the comment list to the Entity Framework context and save the comment
7.
to the database.
Open Global.asax and add a line of code to the Application_Start method
that calls Database.SetInitializer, passing a new PhotoSharingInitializer
object. Also add the following namespaces:
8.
o using System.Data.Entity;
o using PhotoSharingApplication.Models;

Task 3: Create a Windows Azure SQL database and obtain a connection


string.

Log on to the Windows Azure portal by using the following information:

1. o Portal address: http://www.windowsazure.com/


o User name: <your Windows Live user name>
o Password: <your Windows Live password>
Create a new database server and a new database by using the following
information:

o Database name: PhotoSharingDB


2. o Database server: New SQL Database Server
o Login name: <your first name>
o Login password: Pa$$w0rd
o Login password confirmation: Pa$$w0rd
o Region: <a region close to you>
In the list of allowed IP addresses for the PhotoSharingDB database, add the
3. following IP address ranges:
o Rule name: First Address Range
o Start IP Address: <first address in range>
o End IP Address: <last address in range>
Obtain the connection string for the PhotoSharingDB database and add it to the
4.
Web.config file.
5. Build the Photo Sharing application.

Results: After completing this exercise, you will be able to create an MVC
application that uses Windows Azure SQL Database as its data store.

Exercise 5: Testing the Model and Database

Scenario

In this exercise, you will:

o Add a controller and views to the MVC web application.


o Run the web application.

The main tasks for this exercise are as follows:

1. Add a controller and views.


2. Add an image and run the application.

Task 1: Add a controller and views.

Add a new controller to the PhotoSharingApplication project by using the


following information:

o Name: PhotoController
1. Template: MVC Controller with read/write actions and views, using
o
Entity Framework
o Model class: Photo
o Data context class: PhotoSharingContext
o Views: Razor(CSHTML)

Task 2: Add an image and run the application.

Create a new top-level folder, and copy an image to the new folder by using
the following information:

1. o New folder name: Images


o Image to be copied: flower.JPG
o Location of the image: Allfiles (D):\Labfiles\Mod03\Images
Run the application by debugging, and access the following relative path:
2.
o /photo/index

Results: After completing this exercise, you will be able to add controllers,
views, and images to an MVC web application and test the application by
displaying data from a Windows Azure SQL database.

Question: You are building a site that collects information from customers for
their accounts. You want to ensure that customers enter a valid email address in
the Email property. How would you do this?

Question: You have been asked to create an intranet site that publishes a
customer database, created by the sales department, to all employees within your
company. How would you create the model with Entity Framework?

Module Review and Takeaways


The heart of an MVC web application is the model. This is because the model
classes describe the information and objects that your web application manages.
In this module, you have seen how to create your model, define relationships
between the model classes, describe how to display, edit, and validate properties,
and how to extend MVC model handling capabilities. You have also seen how to
bind model classes to database tables by using Entity Framework and how to
query object in the model by writing LINQ code.
Best Practice: If you have a pre-existing database for a web application, use
Entity Framework in the database-first workflow to import and create your model
and its classes.

Best Practice: If you want to create a new database for a web application and
prefer to draw your model in a Visual Studio designer, use Entity Framework in
the model-first workflow to create your model and its classes.

Best Practice: If you want to create a new database for a web application and
prefer to write code that describes your model, use Entity Framework in the
code-first workflow to create your model and its classes.

Best Practice: If you want to separate business logic from data access logic,
create separate model classes and repository classes.

Common Issues and Troubleshooting Tips

Common Issue Troubleshooting Tip

The website cannot connect to or create a database.

Review Question(s)

Question: At the end of the first iteration of your project, you have a website that
displays photos that users upload. However, during development, the database is
empty and users must upload several photos to the site so they can test the
functionality. Your manager wants you find some way to populate the database
whenever it is deployed to the test server. How can you do this?
Module 04: Developing ASP.NET MVC 4
Controllers
Contents:
Module Overview

Lesson Writing Controllers and Actions


1:

Lesson Writing Action Filters


2:

Lab: Developing ASP.NET MVC 4 Controllers

Module Review and Takeaways

Module Overview
MVC controllers respond to browser requests, create model objects, and pass
them to views for rendering and displaying in the web browser. If required,
controllers can also perform other actions, such as saving model class changes to
the database. Controllers are central to MVC applications. You need to
understand the functioning of controllers to be able to create the right model
objects, manipulate them, and pass them to the right views.

To maximize the re-use of code in controllers, you must know how to program
action filters. You can use action filters to run code before or after every action in
your web application, on every action in a controller, or on other combinations of
controller actions.

Objectives

After completing this module, you will be able to:

Add a controller to a web application that responds to user actions specified in


o
the project design.
o Write code in action filters that runs before or after a controller action.

Lesson 1 : Writing Controllers and Actions


A controller is a .NET Framework class that inherits from the
System.Web.Mvc.Controller base class. Controllers respond to user requests.
Within a controller class, you create actions to respond to user requests. Actions
are methods within a controller that return an ActionResult object. The
ActionResult object is often a view that displays a response to the user request;
however, it can also yield other types of results. To process incoming user
requests, manage user input and interactions, and implement relevant application
logic, you need to know how to create controllers and actions. You must also
know how to create parameters in action code blocks and pass objects to actions.

Lesson Objectives
After completing this lesson, you will be able to:

Describe how a controller responds to user actions in an MVC 4 web


o
application.
Write controller actions to respond to web browser requests, create model
o
classes, and call views.
Explain how to use parameters passed in a browser request to a controller
o
action and use them to change the action result.
o Explain how to pass information to views that have model classes.
o Create a controller and actions.
o Describe controller factories.

Responding to User Requests

When an MVC web application receives a request from a web browser, the
following events happen in sequence:

An MvcHandler object creates a controller factory. The controller factory is


the object that instantiates a controller to respond to the request. Usually, this
factory is a DefaultControllerFactory object, but you can create a custom
1. controller factory, if necessary. The MvcHandler object chooses the controller
factory based on the RequestContext object, which has

information about the request that the user made.


The controller factory creates a Controller object, and the MvcHandler calls
2.
the Execute method in that controller.
The ControllerActionInvoker examines the RequestContext object and
3.
determines the action to call in the Controller object.
The ControllerActionInvoker uses a model binder to determine the values to
4.
be passed to the action as parameters.
The ControllerActionInvoker runs the action. Often, the action creates a new
instance of a model class, perhaps by querying the database with the
parameters that the invoker passed to it. This model object is passed to a view,
to display results to the user. Action methods can do many other things such as
5. rendering views and partial views, redirecting to other websites, displaying
snippets of content, or displaying other files.

Note: The routing engine determines which controller and action receives a
request. Routing is not covered in this section.

The User Request

Users of web browsers make requests either by typing a URL into the Address
bar of the browser, or by clicking a link to some address within your website.
Such links can either be within your website, in which case you can control how
they are rendered, or from an external website. Whether the request originates
from within the website or from an external website, it can include information
that controller actions can use as parameters. Consider the following examples:

http://www.adventureworks.com/: This URL is the home page of the website


o
and specifies no further information.
http://www.adventureworks.com/photo: This URL specifies an extra value,
o
photo. By default, the MvcHandler interprets this as the name of a controller.
http://www.adventureworks.com/photo/index: This URL specifies a second
o value, index. By default, the MvcHandler interprets this as the name of an
action within the controller.
http://www.adventureworks.com/photo/display/1: This URL specifies a third
o value, 1. By default, the ControllerActionInvoker interprets this as a
parameter to pass to the action method.
http://www.adventureworks.com/photo/display?id=1: This URL includes a
o
query string, id=1. The model binder examines the Display actions in the
Photo controller. If it finds an action with a parameter called id, it calls that
action and passes 1 as a parameter.

Note: You can modify the preceding logic in several ways. For example, you
can create routes that interpret the preceding URLs differently. The examples
are true when only the default route exists.

Let us consider that a user requests a controller called photo, by typing the URL
in the Address bar of a web browser. By default, the MVC
DefaultControllerFactory, names this controller class as PhotoController. You
should keep to this convention when you create and name controllers. Otherwise,
you will receive unexpected 404 errors and controllers will not work as intended.
If you create a custom controller factory, you can define your own naming
convention for controller classes.

The Microsoft Visual Studio project templates include a folder named


Controllers. This is a good location to create your controllers. Microsoft Visual
Studio places controllers in the projectname.Controllers namespace, by default.

The following example shows the code in an MVC controller class called,
PhotoController. The controller has a single action called Index, which returns
a list of Photo items from the Entity Framework context.

A Simple Controller Class

public class PhotoController : Controller

private ContextDB context = new ContextDB();

public ActionResult Index ()

return View("Index", context.Photos.ToList());


}

Question: What is the convention that you should follow while creating
controllers?

Writing Controller Actions

Controllers encapsulate user interaction logic for an MVC web application. You
specify this logic by writing actions. An action is a method within the controller
class. The code you write within an action method determines how the controller
responds to the request, and the model class and view that MVC uses to display a
webpage in the browser.

Note: When you add a new controller to an MVC application, Visual Studio
presents scaffolding options to help you create action

methods and associated views. For example, if you specify a model class and
Entity Framework context class, Visual Studio can create scaffold index and
details, and create, edit, and delete action methods in your new controller. You
can use these as a starting point for your code. As you become more experienced
with action methods, you may prefer to select the Empty MVC Controller
template and write your own methods without scaffold code.

Controller actions are public methods that return an ActionResult object.


Alternatively, actions can return objects of many other classes that derive from
the ActionResult class. For example, you can write code for a controller with an
Index action to obtain all Photo objects and pass them to the Index view.

When you want to display a specific model object, you must obtain the correct
instance from the database. The following code shows how to display the first
Photo object.

A Details Action

public ActionResult First ()

Photo firstPhoto = context.Photos.ToList()[0];

if (firstPhoto != null)

return View("Details", firstPhoto);

else

return HttpNotFound();

Some user actions are in two parts. For example, to create a new Photo, a user
can make an HTTP GET request to the following URL:
http://www.adventureworks.com/photo/create.
The following code shows an action that responds to a GET request, to display a
new photo form.

A Create Action for the GET Request

public ActionResult Create ()

Photo newPhoto = new Photo();

return View("Create", newPhoto)

The Create view displays a form where users can fill photo details, such as the
title, description, and so on. When a user clicks the Submit button, the web
browser makes an HTTP POST request.

The following action method responds to a POST request. Note that the method
name is the same, but the [HttpPost] annotation is used to specify that this action
responds to the HTTP POST verb.

A Create Action for the POST Request

[HttpPost]

public ActionResult Create (Photo photo)

if (ModelState.IsValid)

context.Photos.Add(photo);
context.SaveChanges();

return RedirectToAction("Index");

else

return View("Create", photo);

Note that the ModelState.IsValid property is used to check whether the user has
submitted valid data. You can specify data validation by using validation data
annotations in the model class. If the data is valid, the model object is added and
saved. Otherwise, the application displays the Create view again, so that the user
can correct the invalid data.

Note: For the preceding code to work, the Create view must contain a form that
uses the POST method.

Possible Return Classes

Action methods are usually defined with the ActionResult class as the return
type. ActionResult is a base class, and you can use a range of derived classes to
return different responses to the web browser.

Controller actions usually return a view and pass a model class to it, for display.
You can create an action that calls the View() helper, and creates and returns a
ViewResult object. The View() helper is available when you derive from the
base Controller class.
Alternatively, you can return an HTTP error. For example, you can create an
action such that if a Photo object is not found, the code creates a 404 not found
error by using the HttpNotFound() helper.

Sometimes, you may want to return a file from an action method. For example,
let us consider that in a Photo model, the image file is stored as a byte array in
the database. To display this byte array as an image on a webpage, the action
must return it as a .jpeg file, which can be used for the src attribute of an <img>
HTML tag. To return files, you can use the File() helper to return a
FileContentResult object. You can use this technique in the GetImage action.

Other possible action results include:

PartialViewResult. You can use this action to generate a section of an HTML


o page, but not a complete HTML page. Partial views can be re-used in many
views throughout a web application.
RedirectToRouteResult. You can use this action result to redirect the web
o
browser to another action method or another route.
RedirectResult. You can use this action result to redirect to a specific URL,
o
either inside your web application or to an external location.
ContentResult. You can use this action result to return text to the web browser.
You can return plain text, XML, a comma-separated table, or other text
o
formats. This text can be rendered in the web browser or parsed with client-side
code.

Child Actions

When an action returns a complete view, MVC sends a new complete webpage to
the web browser for display. Sometimes, you may want to call an action from
within a view, to return a piece of content for display within a webpage. A child
action is an action method that can return a small piece of content in this manner.
The FileContentResult is often a good example of a child action, because the
image returned usually forms part of a webpage. Partial views also support child
actions.
To declare an action method as a child action, you can use the
[ChildActionOnly] annotation. This annotation ensures that the action method
can be called only from within a view by using the Html.Action() helper. Using
this method, you can prevent a user from calling the child action directly by
typing the correct URL into the Address bar.

Question: What are the various ActionResult return types that you can write as
code while creating a controller?

Using Parameters

When users request webpages, they often specify information other than the
name of the webpage itself. For example, when they request a product details
page, they may specify the name or catalog number of the product to display.
Such extra information is referred to as parameters. You must understand how to
determine in code what parameters the user sent in their request.

The ControllerActionInvoker and the DefaultModelBinder classes obtain


parameters from a user request and pass them to action methods. The
DefaultModelBinder can locate

parameters in a posted form, the routing values, the query string, or in the posted
files. If the model binder finds a parameter in the action method that matches the
name and type of a parameter from the request, the action method is called and
the parameter is passed from the request. This arrangement enables you to obtain
and use parameters in your actions. For example, if a user requests the URL
http://www.adventureworks.com/photo/getphotobytitle/?title=myfirstphoto, you
can easily obtain title values in your action method.

The following example code shows how to determine the value of the title
parameter in a controller action.

Using a Query String Parameter

public ActionResult GetPhotoByTitle (string title)

var query = from p in context.Photos

where p.Title == title

select p;

Photo requestedPhoto = (Photo)query.FirstOrDefault();

if (requestedPhoto != null)

return View("Details", requestedPhoto);

else

return HttpNotFound();

}
Note that the action method code uses the parameter title to formulate a LINQ to
Entities query. In this case, the query searches for a Photo with the specified
Title. Parameters in action methods are frequently used in this manner.

Note: The example works if the DefaultModelBinder passes parameters. If you


create a custom model binder in your application, you must ensure that it passes
parameters in the correct manner. Otherwise, the action method cannot access the
parameters that the user specified in the request.

Question: How does DefaultModelBinder pass parameters?

Passing Information to Views

You can pass a model object, such as a Photo, from the action method to the
view by using the View() helper method. This is a frequently-used method to
pass information from a controller action to a view. This is because this method
adheres closely to the Model-View-Controller pattern, in which each view
renders the properties found in the model class, which the view receives from the
controller. You should use this approach wherever possible.

However, in some cases, you may want to augment the information in the model
class with

some extra values. For example, you may want to send a title, which needs to be
inserted in the page header, to the view. Furthermore, some views do not use
model classes. The home page of a website, for example, often does not have a
specific model class. To help in these situations, you can use two other methods
to provide extra data: ViewBag and ViewData.

Using The ViewBag

The ViewBag is a dynamic object that is part of the base controller class.
Because it is a dynamic object, you can add properties that are of any type to it,
in the action method. In the view, you can use the ViewBag object to obtain the
values added in the action.

You can add properties to the ViewBag object in the action method as illustrated
in the following lines of code.

Adding Properties to the ViewBag Object

ViewBag.Message = "This text is not in the model object";

ViewBag.ServerTime = DateTime.Now;

To obtain and use the same properties in a view, you can use the following Razor
code.

Using ViewBag Properties

<p>

The message of the day is: @ViewBag.Message

</p>

<p>

The time on the server is: @ViewBag.ServerTime.ToString()

</p>

Using The ViewData Dictionary


The ViewBag object was added to MVC in version 3. In the earlier versions, you
could pass extra data to views by using the ViewData dictionary. This feature is
still available in MVC 4 for backward compatibility and for developers who
prefer to use dictionary objects. In fact, ViewBag is a dynamic wrapper above
the ViewData dictionary. This means that you could save a value in a controller
action by using ViewBag and read the same value back out by using ViewData.

In action methods, you can add data to the ViewData dictionary by using
key/value pairs as the following lines of code illustrate.

Adding Data to the ViewData

ViewData["Message"] = " This text is not in the model object"

ViewData["ServerTime"] = DateTime.Now;

To obtain and use the same values in a view, you can use the following Razor
code.

Using ViewData Values

<p>

The message of the day is: @ViewData["Message"]

</p>

<p>

The time on the server is: @((DateTime)ViewData["ServerTime"])

</p>

In the examples, note that you can cast any ViewData values other than strings.

Question: Do ViewBag and ViewData serve different purposes?


Demonstration: How to Create a Controller
In this demonstration, you will see how to create a controller and write common
actions in the controller.

Note: At the end of this demonstration, the application will not include views.
Therefore, the application cannot display webpages.

Demonstration Steps
In the Solution Explorer pane of the OperasWebSite - Microsoft Visual
1. Studio window, right-click Controllers, point to Add, and then click
Controller.
In the Controller Name box of the Add Controller dialog box, type
2.
OperaController.
3. In the Template box, click Empty MVC controller, and then click Add.
In the OperaController.cs code window, locate the following code.
4.
using System.Web.MVC;
Place the mouse cursor at the end of the System.Web.MVC namespace, press
Enter, and then type the following code.

5. using System.Data.Entity;

using OperasWebSite.Models;

In the OperaController class code block, press Enter, type the following
code, and then press Enter.

6. private OperasDB contextDB =

new OperasDB();

In the Index action code block, select the following code.


7.
return View();

Replace the selected code with the following code.

return View("Index",
8.

contextDB.Operas.ToList());

Place the mouse cursor at the end of the Index action code block, press Enter,
and then type the following code.

public ActionResult Details (int id)


9.
{

In the Details action code block, type the following code.

Opera opera =

contextDB.Operas.Find(id);

if (opera != null)

10.
return View("Details", opera);

else

return HttpNotFound();
}

Place the mouse cursor at the end of the Details action code block, press
Enter twice, and then type the following code.

11. public ActionResult Create ()

}
In the Create action code block, type the following code.

12. Opera newOpera = new Opera();

return View("Create", newOpera);

Place the mouse cursor at the end of the Create action code block, press
Enter twice, and then type the following code.

[HttpPost]
13.
public ActionResult Create

(Opera newOpera)

}
Place the mouse cursor in the Create action code block with the HTTP verb
POST, and then type the following code.

if (ModelState.IsValid)

14. {

contextDB.Operas.Add(newOpera);

contextDB.SaveChanges();
return

RedirectToAction("Index");

else

return View("Create", newOpera);

On the FILE menu of the OperasWebSite - Microsoft Visual Studio


15.
window, click Save Controllers\OperaControllers.cs.
In the OperasWebSite - Microsoft Visual Studio window, click the Close
16. button.
Note: The message, “Save changes to the following items?” is displayed.
In the Microsoft Visual Studio dialog box, note that the message, “Save
17.
changes to the following items?” is displayed, and then click Yes.

What Are Controller Factories?


A controller factory is an MVC component that instantiates the controller classes
that you create.

For example, when a user requests a list of Photo model objects, a controller
factory should create an instance of the PhotoController class. An action
invoker then calls one of the action methods in that class, and a model binder
passes parameters to it.

The MVC framework includes a built-in DefaultControllerFactory class that is


suitable for most web applications. However, you must understand how
DefaultControllerFactory

determines the controller class that it needs to create. Occasionally, you may
need to create a custom controller factory to implement your own controller
creation logic.

How the DefaultControllerFactory Class Locates a Controller


Class

The DefaultControllerFactory class identifies controller classes by using the


following criteria:

o The class scope must be public.


o The class must not be marked as abstract.
o The class must not take generic parameters.
o The class must have a name that ends with Controller.
o The class must implement the IController interface.

When the MVC web application starts, DefaultControllerFactory creates a list


of all the classes in the application that satisfy these criteria. This list helps to
create the correct controller rapidly. To write a controller, you must ensure that
all the above mentioned criteria are implemented. Usually, you meet the
IController interface criterion by inheriting from the base Controller class.
By default, the DefaultControllerFactory mandates all controller classes to end
with the word Controller. For example, following this convention, for the Photo
model class, you would create a controller called PhotoController.

Creating a Custom Controller Factory

Occasionally, you might want to implement a custom controller factory. There


are two common reasons for doing this:

To modify the criteria for selecting controllers. The criteria described earlier
are suitable for most web applications, but sometimes, you may want to change
o
them. For example, you may not want to name controllers with Controller at
the end, or you may want to add extra criteria of your own.
To support direct injection for testing. Direct injection is a programming
technique that lets you specify classes at run time, instead of specifying classes
o when writing code. This is helpful for unit testing because you can inject a test
class with mock data, instead of real data. The DefaultControllerFactory class
does not support direct injection.

The following code shows how to create a custom controller factory by


implementing the IControllerFactory interface.

A Custom Controller Factory

public class AdWorksControllerFactory : IControllerFactory

public IController CreateController (RequestContext requestContext,

string

ControllerName)

Type targetType = null;


if (ControllerName == "Photo")

targetType = typeof(PhotoController);

else

targetType = typeof(GeneralPurposeController);

return targetType == null ? null :

(IController)Activator.CreateInstance(targetType);

public SessionStateBehavior

GetControllerSessionBehavior(RequestContext

requestContext,

string controllerName)

return SessionStateBehavior.Default;

public void ReleaseController(IController controller)


{

IDisposable disposable = controller as IDisposable;

if (disposable != null)

disposable.Dispose();

You must implement the CreateController, GetControllerSessionBehavior,


and ReleaseController methods for any custom controller factory you create.

For example, if the controller name passed to a controller factory is “Photo”, then
the PhotoController is used. Otherwise, the GeneralPurposeController is
used. The logic in a real custom controller should be more sophisticated than in
this example. However the example illustrates the minimal required code to
create a custom controller factory.

Registering a Custom Controller Factory

Even if you create a custom controller factory in your application, MVC will still
use the DefaultControllerFactory class, unless you register your custom
factory.

You register a custom controller factory by using the ControllerBuilder class in


the Global.asax file, as the following lines of code show.

Registering a Custom Controller Factory


protected void Application_Start()

ControllerBuilder.Current.SetControllerFactory(new

AdWorksControllerFactory());

Question: Can you create a controller that does not end with “Controller”?

Lesson 2: Writing Action Filters


In some situations, you may need to run code before or after controller actions
run. Before a user runs any action that modifies data, you might want to run the
code that checks the details of the user account. If you add such code to the
actions themselves, you will have to duplicate the code in all the actions where
you want the code to run. Action filters provide a convenient way to avoid code
duplication. You need to know how to create and use action filters in your web
application, and when to use them.

Lesson Objectives
After completing this lesson, you will be able to:

o Describe action filters.


o Create action filters.
o Determine when to use action filters.

What Are Filters?


The MVC programming model enforces the separation of concerns. For example,
the business logic in model classes is separate from the input logic in controllers
and the user interface logic in views. Each model class is also clearly distinct
from other model classes. However, there are scenarios where requirements may
be relevant to many parts of your application and cut across logical boundaries.
For example, authorization must be done for many sensitive actions and
controllers, regardless of the model and views that they return. These types of
requirements are known as

cross-cutting concerns. Some common examples of cross-cutting concerns


include authorization, logging, and caching.

Filters

Filters are MVC classes that you can use to manage cross-cutting concerns in
your web application. You can apply a filter to a controller action by annotating
the action method with the appropriate attribute. For example, an action
annotated with the [Authorize] attribute, can be run only by authenticated users.
You can also apply a filter to every action in a controller by annotating the
controller class with the attribute.

Filter Types

There are four types of filters that you can use in MVC. These filters run at
slightly different stages in the request process.
Filter Type Interface Default Class Description

Authorization IAuthorizationFilter AuthorizeAttribute Runs before


any other
filter and
before the
code in the
action
method.
Used to
check a
user’s access
rights for the
action.

Action IActionFilter ActionFilterAttribute Runs before


and after the
code in the
action
method.

Result IResultFilter ActionFilterAttribute Runs before


and after a
result is
returned
from an
action
method.

Exception IExceptionFilter HandleErrorAttribute Runs only if


the action
method or
another filter
Filter Type Interface Default Class Description

throws an
exception.
Used to
handle errors.

Question: Which filter type will you use for the following actions?

1. Intercepting an error
2. Modifying a result
3. Authorizing users
4. Inspecting a returned value

Creating and Using Action Filters

If you have a cross-cutting concern in your web application, you can implement
it by creating a custom action filter or a custom result filter. You can create
custom filters by implementing the IActionFilter interface or the IResultFilter
interface. However, the ActionFilterAttribute base class implements both the
IActionFilter and IResultFilter interfaces for you. By deriving your filter from
the ActionFilterAttribute class, you can create a single filter that can run code
both before and after the action runs, and both before and after the result is
returned.
The following code shows how an action filter is used to write text to the Visual
Studio Output window in the order in which the IActionFilter and IResultFilter
events run. Place this code in a class file within your web application.

A Simple Custom Action Filter

public class SimpleActionFilter : ActionFilterAttribute

public override void OnActionExecuting(ActionExecutingContext

filterContext)

Debug.WriteLine("This Event Fired: OnActionExecuting");

public override void OnActionExecuted(ActionExecutedContext

filterContext)

Debug.WriteLine("This Event Fired: OnActionExecuted");

public override void OnResultExecuting(ResultExecutingContext

filterContext)

Debug.WriteLine("This Event Fired: OnResultExecuting");

}
public override void OnResultExecuted(ResultExecutedContext

filterContext)

Debug.WriteLine("This Event Fired: OnResultExecuted");

Note: You can also create a custom authorization filter by implementing the
IAuthorizationFilter interface. However, the default AuthorizeAttribute
implementation is highly useful and satisfies almost all authentication
requirements. You should be careful when overriding the default security code in
MVC or any other programming model. If you do so without a full understanding
of the implications, you can introduce security vulnerabilities that a malicious
user can exploit.

Using a Custom Action Filter

After you have created a custom action filter, you can apply it to any action
method or class in your web application by annotating the method or class with
the action filter name.

In the following lines of code, the SimpleActionFilter is applied to the Index


action of the Photo controller.

Using A Custom Action Filter

public class PhotoController : Controller

ContextDB contextDB = new ContextDB();


[SimpleActionFilter]

public ActionResult Index()

return View("Index", contextDB.Photos.ToList());

Question: What are the advantages of custom action filters?

Discussion: Action Filter Scenarios

Consider the following scenarios. In each case, discuss with the rest of the class
whether the scenario requires a custom filter, or can be solved with a built-in
filter type, or cannot be solved with filters.

You are writing a photo sharing application and you want to enable each user
to discuss photos, cameras, lenses, and other photography equipment with
1. other users whom they have marked as their friends.

Other users should be prevented from seeing these discussions.


You want to ensure that when MVC calls the GetImage action method, the ID
2.
in the query string is passed as a parameter.
You are writing a photo sharing application and you want to prevent
3.
unauthenticated users from adding comments to a photo.
You want to prevent malicious users from intercepting the credentials entered
4. by users in the logon form for your web application. You want to ensure that
the credentials are encrypted.

Lab: Developing ASP.NET MVC 4 Controllers


Scenario

You have been asked to add a controller to the photo sharing application that
corresponds to the Photo model class that you have created in an earlier module.
The controller should include actions that respond when users upload photos, list
all photos, display a single photo, and delete photos from the application. You
should also add an action that returns the photo as a .jpg file to show on a
webpage.

The members of your development team are new to ASP.NET MVC and they
find the use of controller actions confusing. Therefore, you need to help them by
adding a component that displays action parameters in the Visual Studio Output
window whenever an action runs. You will add an action filter to achieve this.

Note: The controllers and views that you have added in Lab 2 were to test your
new model classes. They have been removed from the project to create the actual
controllers. You will create temporary views to test these controllers at the end of
this lab.

Objectives

After completing this lab, you will be able to:

o Add an MVC controller to a web application.


Write actions in an MVC controller that respond to user operations such as
o
create, index, display, and delete.
o Write action filters that run code for multiple actions.
Lab Setup

Estimated Time: 60 minutes

Virtual Machine: 20486B-SEA-DEV11

User name: Admin

Password: Pa$$w0rd

Note: In Hyper-V Manager, start the MSL-TMG1 virtual machine if it is not


already running.

Before starting the lab, you need to enable the Allow NuGet to download
missing packages during build option, by performing the following steps:

o On the TOOLS menu of the Microsoft Visual Studio window, click Options.
o In the navigation pane of the Options dialog box, click Package Manager.
Under the Package Restore section, select the Allow NuGet to download
o
missing packages during build checkbox, and then click OK.

Exercise 1: Adding an MVC Controller and Writing the Actions

Scenario

In this exercise, you will create the MVC controller that handles photo
operations. You will also add the following actions:

Index. This action gets a list of all the Photo objects and passes the list to the
o
Index view for display.
Display. This action takes an ID to find a single Photo object. It passes the
o
Photo to the Display view for display.
Create (GET). This action creates a new Photo object and passes it to the
o Create view, which displays a form that the visitor can use to upload a photo
and describe it.
Create (POST). This action receives a Photo object from the Create view and
o
saves the details to the database.
Delete (GET). This action displays a Photo object and requests confirmation
o
from the user to delete the Photo object.
o DeleteConfirmed (POST). This action deletes a Photo object after confirmation.
GetImage: This action returns the photo image from the database as a JPEG
o
file. This method is called by multiple views to display the image.

The main tasks for this exercise are as follows:

1. Create a photo controller.


2. Create the Index action.
3. Create the Display action.
4. Write the Create actions for GET and POST HTTP verbs.
5. Create the Delete actions for GET and POST HTTP verbs.
6. Create the GetImage action.

Task 1: Create a photo controller.

Start the virtual machine, and log on with the following credentials:

1. o Virtual Machine: 20486B-SEA-DEV11


o User name: Admin
o Password: Pa$$w0rd
2. Open the PhotoSharingApplication.sln file from the following location:
3. File path: Allfiles (D):\Labfiles\Mod04\Starter\PhotoSharingApplication
Create a new controller for handling photo objects by using the following
information:
4.
o Controller name: PhotoController
o Template: Empty MVC controller
Add using statements to the controller for the following namespaces:
5.
o System.Collections.Generic
o System.Globalization
o PhotoSharingApplication.Models
In the PhotoController class, create a new private object by using the following
information:

o Scope: private
6.
o Class: PhotoSharingContext
o Name: context

Instantiate the new object by calling the PhotoSharingContext constructor.

Task 2: Create the Index action.

Edit the code in the Index action by using the following information:

1. o Return class: View


o View name: Index
o Model: context.Photos.ToList()

Task 3: Create the Display action.

Add a method for the Display action by using the following information:

o Scope: public
1. o Return Type: ActionResult

o Name: Display
o Parameters: One integer called id
Within the Display action code block, add code to find a single photo object
2.
from its ID.
3. If no photo with the right ID is found, return the HttpNotFound value.
4. If a photo with the right ID is found, pass it to a view called Display.
Task 4: Write the Create actions for GET and POST HTTP verbs.

Add a method for the Create action by using the following information:

1. o Scope: public
o Return type: ActionResult
o Name: Create
Add code to the Create action that creates a new Photo and sets its
2.
CreatedDate property to today’s date.
3. Pass the new Photo to a view called Create.
Add another method for the Create action by using the following information:

o HTTP verb: HTTP Post


o Scope: public
4. o Return type: ActionResult
o Name: Create
o First parameter: a Photo object called photo.
o Second parameter: an HttpPostedFileBase object called image.
Add code to the Create action that sets the photo.CreatedDate property to
5.
today’s date.
If the ModelState is not valid, pass the photo object to the Create view. Else,
if the image parameter is not null, set the photo.ImageMimeType property to
the value of image.ContentType, set the photo.PhotoFile property to be a
6.
new byte array of length, image.ContextLength, and then save the file that the
user posted to the photo.PhotoFile property by using the
image.InputStream.Read() method.
Add the photo object to the context, save the changes, and then redirect to the
7.
Index action.

Task 5: Create the Delete actions for GET and POST HTTP verbs.

Add a method for the Delete action by using the following information:
1.
o Scope: public
o Return type: ActionResult
o Name: Delete
o Parameter: an integer called id
2. In the Delete action, add code to find a single photo object from its id.
3. If no Photo with the right id is found, return the HttpNotFound value
4. If a Photo with the right id is found, pass it to a view called Delete.
Add a method called DeleteConfirmed by using the following information:

o HTTP verb: HTTP Post


o ActionName: Delete
5. o Scope: public
o Return type: ActionResult
o Name: DeleteConfirmed
o Parameter: an integer called id
6. Find the correct photo object from the context by using the id parameter.
Remove the photo object from the context, save your changes and redirect to
7.
the Index action.

Task 6: Create the GetImage action.

Add a method for the GetImage action by using the following information:

o Scope: public
1. o Return type: FileContentResult

o Name: GetImage
o Parameter: an integer called id
2. Find the correct photo object from the context by using the id parameter.
If the photo object is not null, return a File result constructed from the
3. photo.PhotoFile and photo.ImageMimeType properties, else return the null
value.
4. Save the file.
Results: After completing this exercise, you will be able to create an MVC
controller that implements common actions for the Photo model class in the
Photo Sharing application.

Exercise 2: Optional—Writing the Action Filters in a Controller

Scenario

Your development team is new to MVC and is having difficulty in passing the
right parameters to controllers and actions. You need to implement a component
that displays the controller names, action names, parameter names, and values in
the Visual Studio Output window to help with this problem. In this exercise, you
will create an action filter for this purpose.

Complete this exercise if time permits.

The main tasks for this exercise are as follows:

1. Add an action filter class.


2. Add a logValues method to the action filter class.
3. Add a handler for the OnActionExecuting event.
4. Register the Action Filter with the Photo Controller.

Task 1: Add an action filter class.

Create a new class for the action filter by using the following information:

1. o Name: ValueReporter

o Folder: Controllers
Add using statements to the controller for the following namespaces:

2. o System.Diagnostics
o System.Web.Mvc
o System.Web.Routing
Ensure that the ValueReporter class inherits from the ActionFilterAttribute
3.
class.

Task 2: Add a logValues method to the action filter class.

Add a method to the ValueReporter class by using the following information:

o Scope: private
1. o Return type: void

o Name: logValues
o Parameter: a RouteData object called routeData.
Within the logValues method, call the Debug.WriteLine method to send the
2. name of the controller and action to the Visual Studio Output window. For the
category, use the string, “Action Values”.
Within the logValues method, create a foreach loop that loops through the var
3.
items in routeData.Values.
In the foreach loop, call the Debug.WriteLine method to send the key name
4.
and value to Visual Studio Output window.

Task 3: Add a handler for the OnActionExecuting event.

In the ValueReporter action filter, override the OnActionExecuting event


1.
handler.
In the OnActionExecuting event handler, call the logValues method, and pass
2.
the filterContext.RouteData object.
3. Save the file.

Task 4: Register the Action Filter with the Photo Controller.

Open the PhotoController class and add the ValueReporter action filter to
1.
the PhotoController class.
2. Save the file.
Results: After completing this exercise, you will be able to create an action filter
class that logs the details of actions, controllers, and parameters to the Visual
Studio Output window, whenever an action is called.

Exercise 3: Using the Photo Controller

Scenario

In this exercise, you will:

Create a temporary index and display views by using the scaffold code that is
o
built into the Visual Studio MVC application template.
Use the views to test controllers, actions, and action filters, and run the Photo
o
Sharing application.

The main tasks for this exercise are as follows:

1. Create the Index and Display views.


2. Use the GetImage action in the Display view.
3. Run the application and display a photo.

Task 1: Create the Index and Display views.

1. Compile the PhotoSharingApplication project to build the solution.


Add a new view to the Index action method of the PhotoController class by
using the following information:

o Folder: Views/Photo
2. o Name: Index
o View type: Strong
o Model class: Photo
o Scaffold template: List
Add a new view to the Display action method of the PhotoController class by
using the following information:

o Folder: Views/Photo
3. o Name: Display
o View type: Strong
o Model class: Photo
o Scaffold template: Details

Task 2: Use the GetImage action in the Display view.

In the Display.cshtml code window, after the code that displays the
1. model.Title property, add a code that runs if the Model.PhotoFile property is
not null.
Within the if code block, render an <img> tag. Use the following information:

2. o Tag: <img>
o Width: 800px
o Source: Blank
In the src attribute of the <img> tag, add a call to the Url.Action helper by
using the following information:

3. o Controller: Photo
o Action: GetImage
o Parameters: Model.PhotoID
4. Save the file.
5. Build the solution.

Task 3: Run the application and display a photo.

Start debugging the application and access the following relative path:
1.
o Path: /photo/index
If you completed Exercise 2, in the Output pane of the
PhotoSharingApplication - Microsoft Visual Studio window, locate the last
2.
entry in the Action Values category to verify whether there are any calls to the
Display and the GetImage actions.
3. Display an image.
If you completed Exercise 2, in the Output pane of the
PhotoSharingApplication - Microsoft Visual Studio window, locate the last
4.
entry in the Action Values category to verify whether there are any calls to the
Display and the GetImage actions.
5. Stop debugging and close Microsoft Visual Studio.

Results: After completing this exercise, you will be able to create an MVC
application with views that you can use to test controllers, actions, and action
filters.

Question: What will happen if you click the Edit or Delete links in the Index
view in the Lab?

Question: Why did you use the ActionName annotation for the
DeleteConfirmed action in the PhotoController class?

Question: In the lab, you added two actions with the name, Create. Why is it
possible to add these actions without using the ActionName annotation?

Module Review and Takeaways


In this module, you have seen the pivotal role that controllers and actions take in
the construction of an MVC web application. Controllers and actions ensure that
the application responds correctly to each user request, create instances of model
classes, and pass the model class to a view for display. In the next module, you
will see how to create and code views to implement the user interface for your
application.

Best Practice: Unless you have a good reason not to, keep to the convention that
each controller should be named to match the corresponding model class, with
“Controller” appended. For example, for the Photo model class, the controller
should be called PhotoController. By maintaining this convention, you create a
logically named set of model and controller classes, and can use the default
controller factory.

Best Practice: Take great care if you choose to override the built-in
AuthorizeAttribute filter because it implements permissions and security for the
web application. If you carelessly modify the security infrastructure of the MVC
framework, you may introduce vulnerabilities in your application. Instead, use
the built-in filter wherever possible.

Review Question(s)

Question: You want to ensure that the CreatedDate property of a new Photo
object is set to today’s date when the object is created. Should this value be set in
the Photo model class constructor method or in the PhotoController Create
action method?

Module 05: Developing ASP.NET MVC 4 Views


Contents:
Module Overview

Lesson Creating Views with Razor Syntax


1:

Lesson Using HTML Helpers


2:
Lesson Re-using Code in Views
3:

Lab: Developing ASP.NET MVC 4 Views

Module Review and Takeaways

Module Overview
Views are one of the three major components of the MVC programming model.
You can construct the user interface for your web application by writing views. A
view is a mixture of HTML markup and code that runs on the web server. You
need to know how to write the HTML and code found in a view and use the
various helper classes built into MVC. You also need to know how to write
partial views, which render sections of HTML that can be re-used in many places
in your web application. The knowledge of creating views will help you develop
webpages that present dynamic content.

Objectives

After completing this module, you will be able to:

o Create an MVC view and add Razor markup to it to display data to users.
Use HTML helpers in a view to render controls, links, and other HTML
o
elements.
o Re-use Razor markup in multiple locations throughout an application.

Lesson 1 : Creating Views with Razor Syntax


When a user makes a request to an MVC web application, a controller responds.
Often, the controller action instantiates a model object, for example, a Product.
The controller might get the Product by querying the database, by creating a new
Product, or by performing some other step. To display the Product, the
controller creates a view and passes the Product to it. The view builds a
webpage by inserting properties from the Product, and sometimes, from other
sources, into HTML markup. MVC sends the completed webpage to the browser.
To create views, you must understand how MVC interprets the code you place in
views and how a completed HTML page is built. By default, the Razor view
engine performs this interpretation, but you can also use other view engines. If
you take time to understand Razor, you will find it to be an excellent and
versatile view engine that gives a great degree of control over the rendered
HTML. Other view engines have very different syntaxes, which you may prefer
if you have worked with earlier versions of ASP.NET or other server-side web
technologies, such as Ruby on Rails.

Lesson Objectives
After completing this lesson, you will be able to:

o Add views to an MVC 4 web application.


o Use the @ symbol in a Razor view to treat code as content.
o Describe the features of Razor syntax.
o Bind views to model classes to display data.
o Explain how to render HTML that is accessible to visitors with low vision.
o List a few alternative view engines to the Razor view engine.

Adding Views
In an MVC application, there is usually one controller for every model class. For
example, a model class named Product usually has a controller called
ProductController that contains all the actions relevant to products. There may
be some controllers that do not correspond to any model classes, such as the
HomeController.

However, each controller can have multiple views.

For example, you may want to create the following views for Product objects:

Details. The details view can display a Product, its price, catalog number, and
o
other details.
o Create. The create view can enable users to add a new Product in the catalog.
Edit. The edit view can enable users to modify the properties of an existing
o
Product.
Delete. The delete view can enable users to remove a Product from the
o
catalog.
o Index. The index view can display all the Product objects in the catalog.

By convention, an MVC web application creates all views within the top-level
Views folder. Within this folder, there is a folder for each controller in the
application. In the preceding example, the Views folder would contain a Product
folder. This folder would contain the Details, Create, Edit, Delete, and Index
views.
If you use the Razor view engine and the C# language, views are files with a
.cshtml extension. If you use the Razor view engine and the Visual Basic
language, views are files with a .vbhtml extension. Other view engines use
different extensions.

How to Create a View File

You can add a view file in Visual Studio by performing the following steps:

In the Solution Explorer pane, select the folder where you want to create the
1. view. For example, for a controller named ProductController, MVC expects
view files to be located in the Views/Product folder.
2. Right-click the selected folder, point to Add, and then select View.

Alternatively, you can create a view file for a particular controller action by
opening the controller code file, right-clicking the action, and then clicking Add
View. If you create a view by using the controller code file, some properties in
the Add View dialog box are filled in by default.

The following table describes the properties that you must complete in the Add
View dialog box.

Property Description

View name This is the name of the view. The view file name is this name
with the appropriate extension added. The name you choose
should match the name returned by the corresponding
controller action. If the action controller does not specify the
name of the view to use, MVC assumes the name of the view
matches the name of the controller action.

View engine By default, you can select the Razor or ASPX view engines
in this list. Other engines may be available if you have
installed them.
Property Description

Create a When you select this check box, you bind the view to a
strongly- specific model class, such as a Product class. When you use
typed view strongly-typed views, you get additional IntelliSense and
error checking help in Visual Studio as you write code in the
view.

Model class If you create a strongly-typed view, you need to specify the
model class to bind to the view. Visual Studio will use this
class when it formulates IntelliSense prompts and checks for
compile-time errors.

Scaffold A scaffold template is a basic view that Visual Studio can use
template to create the view. If you specify a model class for the view,
Visual Studio can create simple templates for Create, Edit,
Details, Delete, and List views. When you become more
experienced in using views, you may prefer to build a view
from the empty scaffold template, rather than use populated
scaffold templates.

Reference When you select this check box, links to common client-side
script script files are included in the view. These links include the
libraries jQuery JavaScript library.

Create as a A partial view is a section of Razor code that you can re-use
partial view in multiple views in your application.

Use a layout A layout or master page can be used to impose a standard


or master layout and branding on many pages within the web
page application.

Note: You will see other view engines later in this module.
Question: You are using the Razor view engine and Visual Basic to create
views. You right-click the Delete action in the CustomerController.vb file.
What is the name of the view file that Visual Studio will create by default?

Differentiating Server Side Code from HTML

The Razor view engine interprets view files and runs any server-side code
contained in the view files. To do this, Razor must distinguish server-side code
from HTML content that should be sent to the browser unchanged.

The Razor view engine looks for the @ symbol to identify server-side code.

In the following code example, Razor runs the line with the @ symbol as C#
code on the web server.

This code example displays the value of the Title property of the model class.

Using @ to Declare Server-Side Code

<p>Razor will not interpret any character in this line as code, because

there is no “at”

symbol</p>

<p>

The photo title is:


@Model.Title

</p>

A section of code marked with the @ symbol is referred to as a Razor code


expression. In Razor syntax, you mark the start of a Razor code expression with
the @ symbol, but unlike the ASPX view engine, Razor lacks an expression
ending symbol. Instead, Razor infers the end of a code expression by using a
fairly sophisticated parsing engine.

Modifying the Interpretation of Code and Content

Sometimes, you may need to modify the logic that Razor uses to interpret code
expressions. For example, if you want to display an @ symbol in the browser,
you use @@. Razor interprets this as an escape sequence and renders a single @
symbol. This technique is useful for rendering email addresses.

Razor has sophisticated logic to distinguish code from content and often the @
symbol is all that is required. However, occasionally, you may find that an error
occurs because Razor misinterprets content as code. To fix such errors, you can
use the @: delimiter, which explicitly declares a line as content and not code.

If you want to declare several lines as content, use the <text> tag instead of the
@: delimiter. Razor removes the <text> and </text> tags before returning the
content to the browser.

In the following code example, Razor interprets the @: delimiter to display plain
text.

Using the @: Delimiter

@(

@: This text is in a code block but the delimiter declares it as content.

)
HTML Encoding

For security reasons, when Razor runs any server-side code that returns a string,
it encodes the string as HTML before rendering it to the browser. For example,
you may have a Comment model class with the following properties:

Subject. This property contains a subject for the comment as a simple string
o
with no formatting information.
HtmlComment. This property contains the comment text itself. More important,
o it includes the formatting information as HTML tags. For example, it might
include <i> tags to italicize a word.

If you have used the normal @Model.HtmlComment syntax to return the


formatted comment text, Razor encodes “<” as “&lt” and “>” as “&gt” in the
HTML source. This results in the user seeing “<i>” on the webpage. This is not
the behavior you intend because you want the users to see italicized text.

To render text without HTML encoding, use the Html.Raw() helper. For
example, use @Html.Raw(Model.HtmlComment).

Note: Razor encodes text as HTML for a specific security reason—to stop
malicious users from injecting malicious code into your web application. If such
attacks are successful, injected code may circumvent security restrictions in your
web application and deny service to users, or it may access sensitive information.
Therefore, you should only use the Html.Raw() helper when it is absolutely
necessary. Also, if you must use the Html.Raw() helper, you must ensure that it
does not operate on unchecked strings entered by users.

Features of Razor Syntax


Razor includes many useful features that you can use to control the manner in
which ASP.NET MVC renders your view as HTML. These features include the
following:

Razor Comments

You may want to include comments in your Razor code to describe it to other
developers in your team. This is an important technique that improves developer
productivity by making it easier to understand code.

You can declare a Razor comment by using the

@* delimiter, as shown in the following code example.

A Razor Comment

@* This text will not be rendered by the Razor view engine, because this

is a comment. *@

Implicit Code Expressions and Parentheses

Razor uses implicit code expressions to determine parts of a line that are server-
side code. Usually, implicit code expressions render the HTML you want, but
occasionally, you might find that Razor interprets an expression as HTML when
it should be run as server-side code.
For example, if the Product.Price property contains the value 2.00, the
following code renders “Price Including Sales Tax: 2.00 * 1.2”.

An Implicit Code Expression

<span>Price Including Sales Tax: @Model.Price * 1.2</span>

You can control and alter this behavior by using parentheses to enclose the
expression for Razor to evaluate.

For example, if the Product.Price property contains the value 2.00, the
following code renders “Price Including Sales Tax: 2.40”.

Using Parentheses to Explicitly Delimit Expressions

<span>Price Including Sales Tax: @(Model.Price * 1.2)</span>

Razor Code Blocks, Loops, and Conditions

If you want to write multiple lines of server-side code, you can do it without
prefacing every line with the @ symbol by using a Razor code block.

A Razor Code Block

@ {

//Razor interprets all text within these curly braces as server-side

code.

Razor also includes code blocks that run conditional statements or loop through
collections.

For example, Razor runs the following code only if the Product.InStock
Boolean property returns true.
A Razor If Code Block

@if (Model.InStock)

Html.ActionLink("Buy This Product", "AddToCart")

Razor loops are useful for creating index views, which display many objects of a
particular model class. A product catalog page, which displays many products
from the database, is a good example of an index view. To implement an index
view, a controller action passes an enumerable collection of objects to the view.

You can loop through all the objects in an enumerable collection by using the
foreach code block:

A Razor Foreach Code Block

@foreach (var item in Model)

<div>@item.ProductName</div>

Question: You want to describe a code block to developers in your view file.
You do not want your description to be passed to the browser. What syntax
should you use?

Binding Views to Model Classes and Displaying


Properties
Many Razor views are designed to display properties from a specific model class.
If you bind such views to the class they display, you get extra help such as
IntelliSense feedback as you write the Razor code. Other views may display
properties from different model classes in different cases, or may not use a model
class at all. These views cannot be bound to a model class and are called dynamic
views. You must understand how to write Razor code for both these situations.

Strongly-Typed Views

In many cases, when you create a view, you know that the controller action will
always pass an object of a specific model class. For example, if you are writing
the Display view for the Display action in the Product controller, you know
from the action code that the action will always pass a Product object to the
view.

In such cases, you can create a strongly-typed view. A strongly-typed view is a


view that includes a declaration of the model class. When you declare the model
class in the view, Visual Studio helps you with additional IntelliSense feedback
and error-checking as you write the code. This is possible because Visual Studio
can check the properties that the model class includes. Troubleshooting run-time
errors is also easy. You should create strongly-typed views whenever you can so
that you benefit from this extra IntelliSense and error-checking. If you follow this
as a best practice, you will make fewer coding errors. A strongly-typed view only
works with an object of the model class in the declaration.
To create a strongly-typed view in Visual Studio, select Create a strongly typed
view in the Add View dialog box, and then choose the model class to bind to the
view.

You can choose the Product model class so that Visual Studio can bind the view
to the class you specify, by adding the following line of code at the top of the
view file.

The Model Declaration

@model MyWebSite.Models.Product

Later in the view file, you can access properties of the model object by using the
Model helper. For example, you might access a product catalog number in this
manner: @Model.CatalogNumber.

Binding to an Enumerable List

Some views display many instances of a model class. For example, a product
catalog page displays many instances of the Product model class. In such cases,
the controller action passes a list of model objects to the view, instead of a single
model object. You can still create a strongly-typed view in this situation, but you
must use a different model declaration. You usually loop through the items in the
list by using a Razor foreach loop.

The following code example shows a multiple-item view with the model
declaration and the loop that enumerates all the Product objects passed by the
action.

A View of a List of Objects

@model IEnumerable<MyWebSite.Models.Product>

<h1>Product Catalog</h1>

@foreach (var Product in Model)


{

<div>Name: @Product.Name</div>

Using Dynamic Views

Sometimes, you might want to create a view that can display more than one
model class. For example, you might want to create a view that can display your
own products and products from a different supplier, together. These model
classes might be named Product and ThirdPartyProduct. Some properties can
be similar while others differ. For example, both Product and
ThirdPartyProduct might include the Price property while only the
ThirdPartyProduct model class includes the Supplier property.

Furthermore, sometimes, the controller action does not pass any model class to
the view. The most common example of such a classless view is the site home
page.

In such cases, you can create a dynamic view. A dynamic view does not include
the @model declaration at the top of the page. You can choose to add the
@model declaration to change the view into a strongly-typed view, later.

When you create dynamic views, you receive less helpful IntelliSense feedback
and error checking because Visual Studio cannot check the model class
properties to verify the code. In such scenarios, you have to ensure that you
access only the properties that exist. To access a property that may or may not
exist, such as the ThirdPartyProduct.Supplier property in the preceding
example, check the property for null before you use it.

Question: You want to write a view that displays ten objects of the Photo model
class. What model declaration should you use?
Rendering Accessible HTML

The Internet is for everyone, regardless of any disabilities an individual user may
have.

Furthermore, if users with disabilities cannot easily browse your website, they
may visit your competitors’ websites and your company may lose business. You
should therefore ensure that people with disabilities—such as those who have
low vision or are hard-of-hearing—can use your web application, and that their
web browsers can parse the HTML content that your site presents. Because MVC
views are responsible for rendering HTML in an MVC web application, you
render accessible

HTML by writing views that follow accessibility guidelines. When you write
views, keep the following challenges and best practices in mind.

Users have different requirements depending on their abilities and disabilities.


For example, consider the following factors:

Users with low vision may use a standard browser, but they may increase text
o
size with a screen magnifier so that they can read the content.
Profoundly blind users may use a browser with text-to-speech software or text-
o
to-Braille hardware.
Color-blind users may have difficulty if a color difference is used to highlight
o
text.
o Deaf users may not be able to access audio content.
o Users with limited dexterity may find it difficult to click small targets.
o User with epilepsy may have seizures if presented with flashing content.

You can ensure that your content is accessible to the broadest range of users by
adhering to the following guidelines:

Do not rely on color differences to highlight text or other content. For example,
o links should be underlined or formatted in bold font to emphasize them to
color-blind users.
Always provide equivalent alternative content for visual and auditory content.
For example, always complete the alt attribute for images. Use this attribute to
o
describe the image so that text-to-speech software or text-to-Braille hardware
can render meaningful words to the user.
Use markup and style sheets to separate content from structure and presentation
code. This helps text interpretation software to render content to users without
being confused by structural and presentation code. For example, you should
apply the following best practices to display content on your webpage:

Avoid using tables to display the content. You should use tables only to
present tabulated content. Tables can be used to render graphics and branding

on a webpage, but in an accessible site, use positional style sheets to display
content. Text readers do not read style sheets.
o Avoid using nested tables. In a nested table, a table cell contains another
table. These are particularly confusing to text readers because they read each

table cell in a sequential order. The user is likely to become disoriented and
unable to determine which cell is being read and what it means.
Avoid using images that include important text. Text readers cannot render

text from within an image file. Instead, use markup to render this text.

Additional Reading: The World Wide Web Consortium (W3C) has a project
called the Web Accessibility Initiative (WAI) that promotes accessible web
content. This project has published the Web Content Accessibility Guidelines
(WCAG). These guidelines are accepted by the web publishing industry as
definitive. To read the full guidelines, go to:
http://go.microsoft.com/fwlink/?LinkID=288955&clcid=0x409

Note: In ASP.NET MVC, the developer has complete control over the HTML
that the web server sends to the web browser. However, you must understand
accessibility principles to write accessible MVC views. Ensure that your entire
development team is familiar with the requirements of accessibility and the
related best practices.

Question: You want to present your company logo at the uppermost part of the
page. The logo is a .gif file that includes the name of the company in an unusual
font. How can you ensure that the logo is accessible?

Alternative View Engines

A view engine is a component of the MVC framework that is responsible for


locating view files, running the server-side code they contain, and rendering
HTML that the browser can display to the user. Many views work with the Razor
view engine. Razor is the default view engine in MVC 4 and is a highly flexible
and efficient view engine.

However, some developers may prefer to use a different view engine for the
following reasons:

View Location Logic. Razor assumes that all views are located in the Views
o top-
level folder. Within this, Razor assumes

that each controller has a separate folder. For example, views for the
ProductController are located in the Product folder within Views. Razor also
looks for some views in the Shared subfolder. These views can be used by
more than one controller. If you do not like this view location logic, you can
use an alternate view engine, or create a custom view engine.
View Syntax. Each view engine uses a different syntax in view files. For
example, in Razor, the @ symbol delimits server-side code. By contrast, in the
ASPX view engine, <% %> delimiters are used. This is familiar to developers
who have worked with Web Forms. You may prefer one syntax over another
for the following reasons:

o ▪ Experience. The technologies that you or your team have previously worked
with may make it easier for you to learn the syntax of a specific view engine.
Readability. Some view engines work with view files that are easily readable
▪ for anyone who knows HTML. Web designers, who do not know C# or other
programming languages, may be able to learn readable syntaxes.
Succinctness. Some view engines work with view files that are terse and

generate HTML with relatively small amounts of code.

Common View Engines

The following table describes and compares four popular view engines.

View Description Code Example


Engin
e

Razor This is the @model IEnumerable<MyWebSite.Models.Product>


default view
engine for
MVC 4. It is
View Description Code Example
Engin
e

easy to learn <ul>


for anyone
who has @foreach (var p in Model)

experience in
{
HTML and
C# or Visual
<li>Name: @p.Name</li>
Basic. Visual
Studio }
provides
good
IntelliSense
feedback for
Razor code
and it is
compatible
with unit
testing.

ASPX This was the <%@ Control Inherits=


default view
engine for "System.Web.Mvc.ViewPage<IEnumerable<Product>

MVC 1 and >"


2. It is easy
to learn for %>

developers
<ul>
with
experience in
<% foreach(var p in model){%>
ASP.NET
View Description Code Example
Engin
e

Web Forms <li><%=p.Name%></li>


and it is also
known as the <%}%>

Web Forms
View
Engine. It
includes
good
IntelliSense
feedback.

</ul>

NHam NHaml is a @type=IEnumerable<Product>


l .NET
Framework %ul

version of
the Haml - foreach (var p in model)

view engine
%li= p.Name
used with
Ruby on
Rails, a
competitor to
ASP.NET
MVC.
Developers
who have
developed
View Description Code Example
Engin
e

websites with
Ruby on
Rails may
prefer this
view engine.
Visual Studio
does not
provide
IntelliSense
feedback for
this view
engine.
NHaml
syntax is
terse and
efficient, but
often less
intelligible to
inexperience
d developers.

Spark This view <viewdata products="IEnumerable[[Product]]"/>


engine uses
view files <ul if="products.Any()">

that are
<li each="var p in
easily
readable and products">${p.Name}</li>

similar to
</ul>
View Description Code Example
Engin
e

static HTML
files. This
design results
in view files
that are
readable for
anyone who
knows
HTML. You
can obtain
IntelliSense
support for
Spark in
Visual
Studio.

Additional Reading: For more information about alternative view engines, go


to: http://go.microsoft.com/fwlink/?LinkID=288956&clcid=0x409
http://go.microsoft.com/fwlink/?LinkID=288957&clcid=0x409

Creating Custom View Engines

You can also create your own view engine to implement custom logic for
locating views or to implement custom syntax for view files. Custom view
engines are rarely created because the existing view engines are powerful,
flexible, and easy to learn. The default logic for finding view files is also simple
and rarely needs modification. To create a custom view engine, you must take the
following steps:
Create a View Class. This class must implement the IView interface and have a
Render() method. You need to write the custom logic in the Render() method
o
for interpreting custom syntax. This code is likely to include regular
expressions and other sophisticated string-parsing code.
Create a View Engine. This class should inherit the
VirtualPathProviderViewEngine class and include the CreateView() and
o CreatePartialView() methods. By inheriting from the
ViewPathProviderViewEngine class, you can modify the
ViewLocationFormat property to implement custom logic for locating views.
Register the Custom View Engine. To register your custom view engine with
MVC, call ViewEngines.Engines.Add() in the Global.asax file.
o
Additional Reading: For more information about creating custom view
engines in ASP.NET MVC page, see:
http://go.microsoft.com/fwlink/?LinkID=288958&clcid=0x409

Question: Is there any HTML markup that the Razor view engine cannot render?

Lesson 2: Using HTML Helpers


The ASP.NET MVC 4 Framework includes many HTML helper functions that
you can use in views. HTML helpers are C# methods that you can call to render
values, labels, and input controls such as text boxes. Helpers include common
logic that makes it easier for you to render HTML for MVC model class
properties and other tasks. Some HTML helpers examine the definition of a
property in a model class and then render appropriate HTML. Some HTML
helpers call controller actions and others validate user input data. You can also
create custom HTML helpers. You need to know the appropriate HTML helper
to use in any scenario and how to pass the correct parameters to relevant HTML
helpers.

Lesson Objectives
After completing this lesson, you will be able to :
o Use the Html.ActionLink and Url.Action helpers to call a controller action.
Use the Html.DisplayNameFor and HtmlDisplayFor helpers to display the
o
value of a model class property.
Use the Html.LabelFor and HTML.EditorFor helpers to render an editor
o
control for a model class property.
o Use the Html.BeginForm helper to render a form for a controller action.
o Use HTML helpers to validate data typed by users.
o Use various HTML helpers to build a user interface for a web application.

Using Action Helpers

HTML helpers are simple methods that in most cases return a string. This string
is a small section of HTML that the view engine can insert into the view file to
generate the completed webpage. You can write views that render any type of
HTML content without using a single helper if you prefer not to use HTML
helpers. However, HTML helpers make the task of managing HTML content
easier by rendering common HTML strings for often-used scenarios.

The Html.ActionLink() and Url.Action() helpers enable you to render HTML


that calls controller

actions.

The Html.ActionLink() Helper


When the user makes a request to an MVC web application, the ASP.NET MVC
4 framework forwards the request to the correct controller and action, thereby
passing the correct parameters. It is possible for users to make such requests by
typing a URL into the Address bar of a web browser, but they rarely know the
name of the controller, action, or parameters. Instead, they usually click a link.
The Html.ActionLink() helper can be used to render links to actions for you.
The helper returns an <a> element with the correct href parameter value when
users click a link in a webpage.

In the following code example, the Html.Actionlink() helper renders an <a>


element that calls the Display action in the Photo controller, and passes an
integer for the photo ID.

Using the Html.ActionLink() Helper

@Html.ActionLink("Click here to view photo 1", "Display", new { id = 1 })

By default, the example renders the following HTML:

<a href="/photo/display/1">Click here to view photo 1</a>

Notice that you pass parameters to the helper by using an anonymous object. In
this manner, you can pass multiple parameters.

Note: The Html.ActionLink() helper works with the routing engine to formulate
the correct URL for the link. The helper will render the href value above,
assuming it is called from a PhotoController view. There are several overloads of
the ActionLink helper, however, if you wish to use it to call actions in other
controllers.

The Url.Action Helper

The Url.Action() helper renders a URL by using the routing engine without
rendering the enclosing <a> element.
You can use the Url.Action() helper to populate the src attribute of an <img>
element or <script> element. This helper is useful whenever you want to
formulate a URL to a controller action without rendering a hyperlink.

The following code example shows how to render an image by calling the
Url.Action helper within the src attribute of an img element:

Rendering an Image from an Action

<img alt="This image came from an action" src="@Url.Action("GetImage",

new { id = 1 })"

/>

Additional Reading: For more information about the Html.ActionLink() and


Url.Action() helpers, see:

http://go.microsoft.com/fwlink/?LinkID=288959&clcid=0x409
http://go.microsoft.com/fwlink/?LinkID=288960&clcid=0x409

Question: You want to render an HTML5 <audio> tag to play a sound file from
an action. Would you use the Html.ActionLink() helper or the Url.Action()
helper?

Using Display Helpers


MVC includes several helpers that display properties from model classes. You
can use these helpers to build views that display product details, comment details,
user details, and so on.

Html.DisplayNameFor() renders the name of a model class property.


Html.DisplayFor() renders the value of a model class property. Both these
helpers examine the definition of the property in the model class, including the
data display annotations, to ensure that they render the most appropriate HTML.

The Html.DisplayNameFor() Helper

You use the Html.DisplayNameFor() helper to render the display name for a
property from the model class. If your view is strongly-typed, Visual Studio
checks whether the model class contains a property with the right name as you
type the code. Otherwise, you must ensure that you use a property that exists or
verify that it is not null before you use it. You specify the property of the model
class to the Html.DisplayNameFor() HTML helper by using a lambda
expression.

The following code example renders the display name of the CreatedDate
property by using the Html.DisplayNameFor() HTML helper .

Using the Html.DisplayNameFor() Helper

@Html.DisplayNameFor(model => model.CreatedDate)

The text rendered by the Html.DisplayNameFor() helper depends on the model


class. If you used a DisplayName annotation to give a more descriptive name to a
property, then Html.DisplayNameFor() will use that DisplayName annotation
value; otherwise, it will render the name of the property.

The Html.DisplayFor() Helper

The Html.DisplayFor() helper considers any display annotations that you


specify in the model class, and then renders the value of the property.
In the following code example, the Html.DisplayFor() helper is used to render a
date string.

Using the Html.DisplayFor() Helper

This was created on: @Html.DisplayFor(model => model.CreatedDate)

If you used the DisplayFormat annotation in the model class with


DataFormatString set to “{0:dd/MM/yy}”, then the Html.DisplayFor() helper
ensures that the date is displayed in short date format.

Question: You want to ensure that a view displays “This product was last
changed on” before the ModifiedDate property. This text is declared in the class
with the DisplayName annotation. What code would you write in the view?

The Begin Form Helper

To accept user input, you must provide a form on your webpage. A typical form
consists of a set of labels and input controls. The labels indicate to the user the
property for which they must provide a value. The input controls enable the user
to enter a value. Input controls can be text boxes, check boxes, radio buttons, file
selectors, drop-down lists, or other types of control. There is usually a submit
button and cancel button on forms.

Rendering HTML Forms


To build a form in HTML, you must start with a

<form> element in the HTML webpage. All labels and input controls must be
within the <form> element. In an MVC view, you can use the
Html.BeginForm() helper to render this element and set the controller action to
which the form sends data.

You can also specify the HTTP method that the form uses to submit data. If the
form uses the POST method, which is the default, the browser sends form values
to the web server in the body of the form. If the form uses the GET method, the
browser sends form values to the web server in the query string in the URL.

In the rendered HTML, the <form> element must be closed with a </form> tag.
In Razor views, you can ensure that the form element is closed with an @using
code block. Razor renders the </form> tag at the closing bracket of the code
block.

The following code example shows how to render a form that sends data to the
Register action in the CustomerController. The form uses the POST HTTP
verb.

Using the Html.BeginForm() Helper

@using (Html.BeginForm("Register", "Customer", FormMethod.Post))

@* Place input controls here *@

Using Forms to Post Files

In HTML, if you want to enable website users to upload files, you should use an
HTML form with special properties. Specifically, the <form> element should
include the enctype attribute set to the value multipart/form-data and the form
must use the POST HTTP verb.

You can specify additional attributes for the <form> element by passing them in
an htmlAttributes parameter as new objects. This is a good method to use to add
the enctype attribute. If the form includes any uploaded files, you must set the
enctype attribute to multipart/form-data.

The following code example shows how to render a file upload form that sends
data to the Create action in the ProductController. The form uses the POST
verb and sets the enctype attribute.

Using the Html.BeginForm() Helper

@using (Html.BeginForm("Create", "Photo", FormMethod.Post, new { enctype

"multipart/form-data" }))

@* Place input controls here *@

Question: You have created a form with a file selector control that uses the GET
method. You have set the enctype attribute to multipart/form-data, but when
you try to access the file in the action method, an exception is thrown. What have
you possibly done incorrectly?

Using Editor Helpers


Within HTML forms, there are many HTML input controls that you can use to
gather data from users. In Razor views, the Html.LabelFor() and
Html.EditorFor() helpers make it easy to render the most appropriate input
controls for the properties of a model class. To understand how these helpers
render HTML, you must first understand the HTML input controls. Some
common HTML controls are described in the following table.

Contro Example Descriptio n

Text <input A single- line text box in which the user


box can enter a string. The name attribute is
type="text" used to identify the entered value in the
query string or to send form data by using
name="Title"> the POST method.

Multi- <textarea A multi- line text box in which the user can
line text enter longer strings.
box name="Description

"

rows="20"
Contro Example Descriptio n

cols="80">

Check <input A check box submits a Boolean value.


box
type="checkbox"

name="ContactMe">

Please send me

new offer

details

Additional Reading: For more information about all HTML form elements, go
to: http://go.microsoft.com/fwlink/?LinkID=288961&clcid=0x409

The Html.LabelFor() Helper

The Html.LabelFor() helper is similar to the Html.DisplayNameFor() helper


because it renders the name of the property that you specify, taking into account
the DisplayName annotation if it is specified in the model class. However, unlike
the Html.DisplayNameFor() helper, the Html.LabelFor() helper renders a
<label> element.

The following code example renders a label for the CreatedDate property.
Using the Html.LabelFor() Helper

@Html.LabelFor(model => model.CreatedDate)

The Html.EditorFor() Helper

The Html.EditorFor() helper renders HTML <input> elements and other form
controls for properties from an model class. This helper renders the most
appropriate element for each property data type. For example, the
Html.EditorFor() helper renders <input type="text"> for a string property. If
the string property is annotated with [DataType(DataType.MultilineText)], the
Html.EditorFor() helper renders a <textarea> element instead. The following
table describes the HTML that Html.EditorFor() renders for different model
classes.

Control Model Class Property HTML Rendered by


EditorFor()

Text box public string Title { get; set; } <input type="text"

name="Title">

Multi-line [DataType(DataType.MultilineText)] <textarea


text box name="Description"
public string Description { get;

rows="20"
set;}
cols="80">

Check [Display(Name = "Please send me <input


box type="checkbox"
new offer details")]

name="ContactMe">
public bool ContactMe { get; set;

}
Control Model Class Property HTML Rendered by
EditorFor()

Please send me new

offer

details.

If the action passes an existing model object to the view, the Html.EditorFor()
helper also populates each control with the current values of each property.

The following code example renders a check box for the ContactMe property.

Using the Html.EditorFor() Helper

@Html.EditorFor(model => model.ContactMe)

Question: You have a property in the Product model class named ProductID.
You want to include this in the HTML page so that client-side script can use the
ProductID value. However, you do not want the value to be displayed to users.
In the model class, you have annotated the ProductID property with the
[HiddenInput(DisplayValue=false)] attribute. How will the Html.EditorFor()
helper render this property?

Using Validation Helpers


When you request information from users, you often want the data they enter in a
certain format for further use in the web application. For example, you might
want to ensure that users enter a value for the LastName property. You might
also want to ensure that users enter a valid email address for the EmailAddress
property. You can set these requirements by using validation data annotations in
the model class. In controller actions, you can check the ModelState.IsValid
property to verify if a user has entered valid data.

When users submit a form, if they have entered

invalid data, most websites display validation messages. These messages are
often highlighted in red, but other colors or formats can be used. Often, there is a
validation summary at the top of the page such as “Please enter valid information
for the following fields: Last Name, Email Address”. The form may display
detailed validation messages next to each control in which the user entered
invalid data, or highlight the problems in user supplied data with an asterisk.

When your MVC view displays a form, you can easily show validation messages
by using the validation helpers. Validation helpers render HTML only when
users have entered invalid data.

The Html.ValidationSummary() Helper

Use the Html.ValidationSummary() helper to render a summary of all the


invalid data in the form. This helper is usually called at the top of the form. When
the user submits invalid data, the validation messages are displayed for each
invalid field in a bulleted list. You can control the validation messages in the
model class by using this syntax in the annotation:

[Required(ErrorMessage="Please enter your last name")]

The following code example renders a summary of validation messages.

Using the Html.ValidationSummary() Helper


@Html. ValidationSummary()

The Html.ValidationMessageFor() Helper

Use the Html.ValidationMessageFor() helper to render validation messages


next to each input in the form.

The following code example renders a validation message for the LastName
property of the model class.

Using the Html.ValidationMessageFor() Helper

@Html.ValidationMessageFor(model => model.LastName)

Demonstration: How to Use HTML Helpers


In this demonstration, you will see how to create a view and use HTML helpers
to render controls in it. You will also see how validation requirements, which
were set with data annotations in the model class, take effect in a view.

Demonstration Steps
In the Solution Explorer pane of the OperasWebSite - Microsoft Visual
1.
Studio window, expand Controllers, and then click OperaController.cs.
On the BUILD menu of the OperasWebSite - Microsoft Visual Studio
2.
window, click Build Solution.
In the OperaController.cs code window, locate the following code, right-
click the code, and then click Add View.
3.
public ActionResult Create ()

In the View Name box of the Add View dialog box, ensure that the name
4.
displayed is Create.
In the Add View dialog box, ensure that the Create a strongly-typed view
5.
check box is selected.
In the Model class box, ensure that the value is Opera
6. (OperasWebSite.Models). If not, in the Model class box, click Opera
(OperasWebSite.Models).
7. In the Scaffold template box, ensure that the value is Empty.
In the Add View dialog box, ensure that the Use a layout or master page
8.
check box is not selected, and then click Add.
In the DIV element of the Create.cshtml code window, type the following
code.
9.
<h2>Add an Opera</h2>

Place the mouse cursor at the end of the </h2> tag, press Enter twice, and
then type the following code.

@using (Html.BeginForm(

"Create", "Opera",
10.
FormMethod.Post))

In the using code block, type the following code.

<p>

@Html.LabelFor(model =>

11.
model.Title):

@Html.EditorFor(model =>

model.Title)
@Html.ValidationMessageFor(

model => model.Title)

</p>

Place the mouse cursor at the end of the </p> tag corresponding to the
model.Title property, press Enter twice, and then type the following code.

<p>

@Html.LabelFor(model =>

model.Year):

12. @Html.EditorFor(model =>

model.Year)

@Html.ValidationMessageFor(

model => model.Year)

</p>

Place the mouse cursor at the end of the </p> tag corresponding to the
model.Year property, press Enter twice, and then type the following code.

<p>

13. @Html.LabelFor(model =>

model.Composer):

@Html.EditorFor(model =>
model.Composer)

@Html.ValidationMessageFor(

model => model.Composer)

</p>

Place the mouse cursor at the end of the </p> tag corresponding to the
model.Composer property, press Enter twice, and then type the following
code.
14.
<input type="submit"

value="Create" />

Place the mouse cursor at the end of the <input> tag, press Enter, and then
type the following code.
15.
@Html.ActionLink("Back to List", "Index")

On the DEBUG menu of the OperasWebSite - Microsoft Visual Studio


16. window, click Start Debugging.
Note: The Operas I Have Seen page is displayed.
On the Operas I Have Seen page, click operas I’ve seen.
17.
Note: On the Index page, the list of Operas is displayed.
On the Index page, click Create New.
18.
Note: The Add an Opera page is displayed.
In the Year box of the Add an Opera page, type 1597, and then click Create.

Note: Messages corresponding to the Title, Year, and Composer boxes are
19. displayed. The web application mandates you to enter values in all the boxes.
Alerts are also displayed for any inappropriate entries, with relevant
messages.
20. In the Title box of the Add an Opera page, type Rigoletto.
21. In the Year box of the Add an Opera page, type 1851.
In the Composer box of the Add an Opera page, type Verdi, and then click
22. Create.
Note: The Opera is created with the mentioned values.
23. In the Windows Internet Explorer window, click the Close button.
In the OperasWebSite - Microsoft Visual Studio window, click the Close
24.
button.

Lesson 3: Re-using Code in Views


In a web application, you frequently render similar blocks of HTML content in
different webpages. For example, in an e-commerce web application, you might
want to display the most popular products on the home page, on the front page of
the product catalog, at the top of the product search page, and perhaps in other
locations. To render such HTML content in an MVC application, you may copy
and paste code from one Razor view into others. However, to change the display
of top products later in the project, you would then have to make identical
changes in many locations. A better practice is to use a partial view. A partial
view renders a section of HTML content that can be inserted into several other
views at run time. Because the partial view is a single file that is re-used in
several locations, when you implement a change in a single location, the changes
are updated in other locations in the web application. Partial views increase the
manageability of MVC web applications and facilitate a consistent presentation
of content throughout a web application.

Lesson Objectives
After completing this lesson, you will be able to:

o Describe how partial views enable you to re-use Razor code.


o Create partial views in an MVC 4 web application.
o Use partial views in an MVC 4 web application.
o Determine when to use partial views.

Creating Partial Views

You can use partial views to render identical HTML or similar HTML in
different locations in your web application. Consider a web application in which
users can comment on articles. In the article view, you want to display the
comments for that specific article at the end of the page. You want a similar
display on the home page, but you want to display the most popular comments on
any article. You can build a single comments partial view for this scenario as
follows:

First, create a partial view that displays a collection of comments in the


required
o
format.
Next, create a controller action that retrieves the most popular comments, and
o
then passes them to the partial view.
Then, create another controller action that uses the article ID to find comments
o specific to that article. The controller action then passes this collection of
comments to the partial view.
o Finally, call the appropriate actions from the home page and the article view.

Because the partial view renders a collection of comments, you can re-use it for
various situations by passing different collections to it from controller actions.
Creating and Naming Partial Views

In Visual Studio, you can create a partial view by using the Add View dialog, in
the same manner as creating any other view. Ensure that you select the Create as
a Partial View check box. Because partial views render a small section of
HTML rather than a complete webpage, Visual Studio does not add <head>,
<body>, and other tags to the partial view. By convention, partial views are
named prefixed with an underscore character, for example,
_CommentsList.cshtml. This convention is optional but is often helpful to
distinguish partial views in Solution Explorer.

Partial views are often created inside the /Views/Shared folder in your site.
Views in the Shared folder are accessible to many controllers, whereas views in
the /Views/Comment folder are accessible only from the CommentController.

Strongly-typed and dynamic partial views

Similar to other views, you can create strongly-typed partial views if you are
certain that the partial view will always display the same model class. Visual
Studio can provide the most informative IntelliSense feedback and error-
checking for strongly-typed partial views, when compared with other types of
views. A strongly-typed view has the declaration of the @model directive at the
top of the file. Alternatively, you can create a dynamic partial view if you are not
certain that the partial view will always display the same model class. You can
create dynamic partial views by omitting the @model directive declaration.

In the following example of a partial view, you can see the @model declaration
that makes the partial view strongly-typed. You can also see that the partial view
renders only an unordered list and not a complete HTML webpage as the
following lines of code indicate.

A Strongly-Typed Partial View

@model IEnumerable<Adworks.Models.Comment>
<ul>

@foreach (var item in Model) {

<li>

Subject: @Html.DisplayFor(modelItem => item.Subject)

</li>

</ul>

Question: You want to create a partial view that displays a list of comments. The
comments partial view will be called by actions in the PhotoController and the
HomeController. In which folder should you create the partial view file?

Using Partial Views

Besides knowing how to create partial views, you need to know how to use them
within multiple other views in your site. You can re-use partial views by using
the Html.Partial() and Html.Action() HTML helpers.

The Html.Partial() Helper


You can use the Html.Partial() helper to render a partial view within another
view file. MVC inserts the HTML that the partial view renders into the parent
view and returns the complete webpage to the browser. The first parameter is the
name of

the partial view file without its file extension. The

second optional parameter is a model object for the partial view to render. This is
the same model object that the parent view uses because other model objects are
not available in this context.

The following lines of code call the _Comments.cshtml partial view without
passing a model object.

Using the Html.Partial() Helper

@Html.Partial("_Comments")

Remember that you can use the ViewBag and ViewData collections to pass data
between the action method and the view. A parent view will share the same
ViewBag or ViewData objects with the partial view. This is a good way to share
data between the controller action, view, and partial view.

The Html.Action() Helper

You can pass a model object from the parent view to a partial view when you use
Html.Partial(). However, the parent view can only pass the same model object
available in the parent view. Sometimes, you may want to use a model object
different from the parent view, often of a different model class, with the partial
view. In such cases, you can use the Html.Action() helper. This calls an action
method that returns the correct partial view. The action method can create an
instance of any model class.

Consider an Article view that displays the text and title of an Article object. You
want to display comments at the end of this view in a partial view. You can use
the Html.Action() helper to call an action in the Comments controller that
returns such a partial view. The partial view can work with a collection of
Comment objects.

In the following example, the Html.Action() helper calls an action in the


CommentController controller and passes the ID of the current article model
object.

Using the Html.Action() Helper

@Html.Action("_CommentsForArticle", "Comment", new { ArticleID = Model.ID

})

Question: You want to display user reviews of a product to each product page.
You have created a _ReviewsForProduct partial view. Would you use
Html.Partial() or Html.Action() to render this view?

Discussion: Partial View Scenarios

Consider the following scenarios when creating a web application:

You want to display the ten latest comments in the web application. When
o users click the Latest Comments link on the home page, they will see a new
webpage with the comments displayed.
You want to display the comments for an article on the Article view. You also
want to display the comments for a product on the Product view. There are
separate
o
ArticleComment and ProductComment

classes in your model, but they have similar properties.


You have a photo sharing web application and you want to display a gallery of
thumbnail images on both the AllPhotos view and the home page Index view.
o
The AllPhotos view should show every Photo object, but the home page Index
view should display only the three most recent photos uploaded.

For each scenario, discuss with the class:

o Whether you need to create a view or a partial view.


o Whether you need to create a strongly-typed view or a dynamic view.
If you decide to create a partial view, whether you need to use the
o
Html.Partial() or the Html.Action() HTML helper in the parent view.

Lab: Developing ASP.NET MVC 4 Views


Scenario

You have been asked to add the following views to the photo sharing application:

A Display view for the Photo model objects. This view will display a single
o photo in a large size, with the title, description, owner, and created date
properties.
A Create view for the Photo model objects. This view will enable users to
o
upload a new photo to the gallery and set the title and description properties.
A Photo Gallery partial view. This view will display many photos in thumbnail
sizes, with the title, owner, and created date properties. This view will be used
o on the All Photos webpage to display all the photos in the application. In
addition, this view will also be used on the home page to display the three most
recent photos.
After adding these three views to the photo sharing application, you will also test
the working of the web application.

Objectives

After completing this lab, you will be able to:

Add Razor views to an MVC application and set properties such as scaffold
o
and model binding.
o Write both HTML markup and C# code in a view by using Razor syntax.
o Create a partial view and use it to display re-usable markup.

Lab Setup

Estimated Time: 60 minutes

Virtual Machine: 20486B-SEA-DEV11

User Name: Admin

Password: Pa$$w0rd

Note: In Hyper-V Manager, start the MSL-TMG1 virtual machine if it is not


already running.

Before starting the lab, you need to enable the Allow NuGet to download
missing packages during build option, by performing the following steps:

o On the TOOLS menu of the Microsoft Visual Studio window, click Options.
o In the navigation pane of the Options dialog box, click Package Manager.
Under the Package Restore section, select the Allow NuGet to download
o
missing packages during build checkbox, and then click OK.

Exercise 1: Adding a View for Photo Display

Scenario
In this exercise, you will:

Create a new view in the Photo Sharing web application to display single
o
photos in large size.
o Display the properties of a photo such as title, description, and created date.

The main tasks for this exercise are as follows:

1. Add a new display view.


2. Complete the photo display view.

Task 1: Add a new display view.

Start the virtual machine, and log on with the following credentials:

1. o Virtual Machine: 20486B-SEA-DEV11


o User name: Admin
o Password: Pa$$w0rd
Open the Photo Sharing Application solution from the following location:

2.
File location: Allfiles
o
(D):\Labfiles\Mod05\Starter\PhotoSharingApplication
3. Open the PhotoController.cs code window.
4. Build the solution
Add a new view to the Display action in the PhotoController by using the
following information:

o Name: Display
5. o View engine: Razor (CSHTML)
o View type: Strongly typed
o Model class: Photo
o Scaffold template: Empty
o Layout or master page: None
Task 2: Complete the photo display view.

1. Add a title to the display view by using the Title property of the Model object.
Add an H2 element to the body page to display the photo title on the page by
2.
using the Title property of the Model object.
Add an <img> tag to display the photo on the page by using the following
information:
3.
o Width: 800
o src: Empty
Add the URL.Action helper to the src attribute of the <img> tag by using the
following information:

4. o Method: Url.Action()
o Action name: GetImage
o Controller name: Photo
o Route values: new { id=Model.PhotoID }
Add a P element to display the Description property from the model by using
the following information:

5. o Helper: Html.DisplayFor
Lamda expression: model =>
o
model.Description
Add a P element to display the UserName property from the model by using
the following information:

Helpers:
6.
o ▪ Html.DisplayNameFor

▪ HtmlDisplayFor
o Lamda expression: model => model.UserName
Add a P element to display the CreatedDate property from the model by using
the following information:

Helpers:
7.
o ▪ Html.DisplayNameFor

▪ Html.DisplayFor
o Lamda expression: model => model.CreatedDate
Add a P element to display a link to the Index controller action by using the
following information:

o Helper: HTML.ActionLink
8.
Content: Back to List
o
Note: You will create the Index action and view for the PhotoController
later in this lab.
9. Save the Display.cshtml file.

Results: After completing this exercise, you will be able to add a single display
view to the Photo Sharing web application and display the properties of a photo.

Exercise 2: Adding a View for New Photos

Scenario

In this exercise, you will

Create a view to upload new photos for display in the Photo Sharing
o
application.
o Display the properties of a photo, such as title, description, and created date.

The main tasks for this exercise are as follows:

1. Add a new create view.


2. Complete the photo create view.
Task 1: Add a new create view.

Create a new view for the Create action of the PhotoController class by
using the following information:

o Name: Create
o View: Razor (CSHTML)
1. o View type: Strongly Typed
o Model class: Photo
o Scaffold template: Empty
o Partial view: None
o Layout or master page: None

Task 2: Complete the photo create view.

Add the following title to the Create view:


1.
o Title: Create New Photo
Add an H2 element to the body page to display the heading as Create New
2.
Photo.
Create a form on the page by using the following information within an
@using statement:

o Helper: Html.BeginForm
3. o Action: Create
o Controller name: Photo
o Form method: FormMethod.Post
o Parameter: Pass the HTML attribute enctype = "multipart/form-data"
In the form, use the Html.ValidationSummary helper to render validation
4.
messages.
After the ValidationSummary, add a P element to display controls for the
5. Title property of the model by using the following information:
Helpers:

o ▪ LabelFor
▪ EditorFor
▪ ValidationMessageFor
After the controls for the Title property, add a P element to display a label for
the PhotoFile property, and an <input> tag by using the following
information:
6.
o Helper: LabelFor
o Input type: file
o Name: Image
After the PhotoFile controls, add a P element to display controls for the
Description property of the model by using the following information:

Helpers:
7.
o ▪ LabelFor
▪ EditorFor
▪ ValidationMessageFor
After the Description controls, add a P element to display read-only controls
for the UserName property of the model by using the following information:

8. Helpers:

o ▪ LabelFor

▪ DisplayFor
After the UserName controls, add a P element to display read-only controls
for the CreatedDate property of the model by using the following
information:
9.
Helpers:
o
▪ LabelFor
▪ DisplayFor
After the CreatedDate controls, add a P element that contains an <input>
tag by using the following information:

10. o Input type: submit


o Value: Create
o Add an action link to the Index action with the text Back to List.
11. Save the Create.cshtml file.

Results: After completing this exercise, you will be able to create a web
application with a Razor view to display new photos.

Exercise 3: Creating and Using a Partial View

Scenario

In this exercise, you will:

o Add a gallery action to the Photo Controller.


o Add a photo gallery partial view.
o Complete the photo gallery partial view.
o Use the photo gallery partial view.

The main tasks for this exercise are as follows:

1. Add a gallery action to the Photo Controller.


2. Add a photo gallery partial view.
3. Complete the photo gallery partial view.
4. Use the photo gallery partial view.

Task 1: Add a gallery action to the Photo Controller.


Add a new action to the PhotoController.cs file by using the following
information:

o Annotation: ChildActionOnly
1. o Scope: public
o Return Type: ActionResult
o Name: _PhotoGallery
o Parameter: an Integer called number with a default value of 0
Create a new List of Photo objects named photos. Add an if statement, to set
2. photos to include all the Photos in the context object, if the number
parameter is zero.
If the number parameter is not zero, set photos to list the most recent Photo
3. objects. The number of Photo objects in the list should be the number
attribute.
4. Pass the photos object to the partial view _PhotoGallery and return the view.
5. Save the PhotoController.cs file.

Task 2: Add a photo gallery partial view.


Create a new partial view for the _PhotoGallery action in the
PhotoController.cs file by using the following information:

o Name: _PhotoGallery
1. o View type: Strongly Typed
o Model class: Photo
o Scaffold template: Empty
o Layout or master page: None
Create a new folder in the PhotoSharingApplication project by using the
following information:
2.
o Parent folder: Views
o Folder name: Shared
Move the _PhotoGallery.cshtml view file from the Photo folder to the Shared
3.
folder.
Task 3: Complete the photo gallery partial view.

In the _PhotoGallery.cshtml partial view file, bind the view to an enumerable


1.
list of Photo model objects.
In the _PhotoGallery.cshtml partial view file, add a For Each statement that
2.
loops through all the items in the Model.
In the For Each statement, add an H3 element that renders the item.Title
3.
property.
After the H3 element, add an if statement that checks that the item.PhotoFile
4.
value is not null.
If the item.PhotoFile value is not null, render an <img> tag with width 200.
Call the UrlAction helper to set the src attribute by using the following
information:
5.
o Action: GetImage
o Controller: Photo
o Parameters: for the id parameter, pass item.PhotoID
After the if statement, add a P element, and call the @Html.DisplayFor helper
6. to render the words Created By: followed by the value of the item.UserName
property.
After the UserName display controls, add a P element, and call the
7. @Html.DisplayFor helper to render the words Created On: followed by the
value of the item.CreatedDate property.
After the CreatedDate display controls, call the Html.ActionLink helper to
render a link by using the following information:

8. o Link text: Display


o View name: Display
o Parameters: pass the item.PhotoID value as the id parameter
9. Save the _PhotoGallery.cshtml file.

Task 4: Use the photo gallery partial view.


Modify the Index action in the PhotoController.cs so that no model class is
1.
passed to the Index view.
Create a view for the Index action in the PhotoController.cs file by using the
following information:

2. o Name: Index
o View type: Not strongly typed
o Layout or master page: None
3. In the Index.cshtml file, change the title to All Photos.
4. Add an H2 element to the page body to display the heading as All Photos
Add a P element to add a link to the Create action in the Photo controller by
using the following information:

5. o Helper: Html.ActionLink
o Link text: Add a Photo
o Action name: Create
o Controller name: Photo
Insert the _PhotoGallery partial view by using the following information:

6. o Helper: Html.Action
o Action name: _PhotoGallery
o Controller name: Photo
7. Save the Index.cshtml file.

Results: After completing this exercise, you will be able to create a web
application with a partial view to display multiple photos.

Exercise 4: Adding a Home View and Testing the Views

Scenario

In this exercise, you will create a home page that re-uses the photo gallery object,
but displays only the three most recent photos.
The main tasks for this exercise are as follows:

1. Add a Controller and View for the home page.


2. Use the web application.

Task 1: Add a Controller and View for the home page.

Add a new Controller to the home page by using the following information:

1. o Controller name: HomeController

o Template: Empty MVC Controller


Add a new view to the Index action in HomeController by using the
following information:

2. o View name: Index


o View type: Not strongly typed
o Layout or master page: None
Change the title of the page to Welcome to Adventure Works Photo
3.
Sharing.
Add the following text to the home page:

4.
Welcome to Adventure Works Photo Sharing! Use this site to share your
o
adventures.
5. Add an H2 element to display the heading as Latest Photos.
Insert the _PhotoGallery partial view by using the following information:

o Helper: Html.Action
6. o Action name: _PhotoGallery

o Controller name: Photo


o Parameters: for the number parameter, pass the value 3
7. Save the Index.cshtml file.

Task 2: Use the web application.


1. Start the Photo Sharing web application with debugging.
2. Verify the number of photos displayed on the home page.
Display a photo of your choice to verify whether the display shows the
3.
required information.
4. Verify the number of photos displayed on the All Photos page.
Add a new photo of your choice to the application by using the following
information:

5. o Title: My First Photo


o Description: This is the first test of the Create photo view.
o File path: Allfiles (D):\Labfiles\Mod05\SamplePhotos
6. Close Internet Explorer and Microsoft Visual Studio.

Results: After completing this exercise, you will be able to create a web
application in which users can upload and view the photos.

Question: How can you improve the accessibility of the HTML that your photo
views render?

Question: In the lab, how did you ensure that the Create view for Photo model
objects could upload photo files when the user clicked the Create button?

Module Review and Takeaways


In this module, you saw how to build the user interface for your web application
by creating views with the Razor view engine. Views can display properties from
a model class and enable users to create, read, update, and delete objects of that
model class. Some views display many objects by looping through a collection of
model objects. The HTML Helper methods that are built into ASP.NET MVC 4
facilitate the rendering of displays, controls, and forms, and return validation
messages to users. Partial views can be re-used several times in your web
application to render similar sections of HTML on multiple pages.
Best Practice: Use Razor comments, declared with the @**@ delimiters,
throughout your Razor views to help explain the view code to other developers in
your team.

Best Practice: Only use @: and <text> tags when Razor misinterprets content as
code. Razor has sophisticated logic for distinguishing content from code, so this
is rarely necessary.

Best Practice: Use strongly-typed views wherever possible because Visual


Studio helps you to write correct code by displaying IntelliSense feedback.

Common Issues and Troubleshooting Tips

Common Issue Troubleshooting


Tip

When a controller tries to access a partial view, an


exception is thrown.

Review Question(s)

Question: You want to display the name of the Comment.Subject property in


an MVC view that renders an Edit form for comments. You want the label Edit
Subject to appear to the left of a text box so that a user can edit the Subject
value. Which HTML helper should you use to render the field name?

Verify the correctness of the statement by placing a mark in the column to the
right.
Statement Answer

If your Razor generates errors by wrongly interpreting content as


server-side code, this indicates that you have explicitly declared
the content by using the @**@ delimiters.

Module 06: Testing and Debugging ASP.NET


MVC 4 Web Applications
Contents:
Module Overview

Lesson Unit Testing MVC Components


1:

Lesson Implementing an Exception Handling Strategy


2:

Lab: Testing and Debugging ASP.NET MVC 4 Web Applications

Module Review and Takeaways


Module Overview
Software systems such as web applications are complex and require multiple
components, often written by different developers, to work together. Incorrect
assumptions, inaccurate understanding, coding errors, and many other sources
can create bugs that result in exceptions or unexpected behavior. To improve the
quality of your web application and create a satisfying user experience, you must
identify bugs from any source and eliminate them. Traditionally, most testing has
been performed at the end of a development project. However, it has recently
become widely accepted that testing throughout the project life cycle improves
quality and ensures that there are no bugs in production software. You need to
understand how to run tests on small components of your web application to
ensure that they function as expected before you assemble them into a complete
web application. You also need to know how to use the tools available in
Microsoft Visual Studio 2012 to debug and trace exceptions when they arise.

Objectives

After completing this module, you will be able to:

Run unit tests against the Model–View–Controller (MVC) components, such as


o
model classes, and locate potential bugs.
o Build an MVC application that handles exceptions smoothly and robustly.

Lesson 1 : Unit Testing MVC Components


A unit test is a procedure that instantiates a component that you have written,
calls one aspect of the functionalities of the component, and checks that the
component responds correctly according to the design. In object-oriented
programming, unit tests usually instantiate a class and call one of its methods. In
an MVC web application, unit tests can instantiate model classes or controllers
and call their methods and actions. As a web developer, you need to know how to
create a testing project and add tests to the testing project. The tests check
individual aspects of your code without relying on database servers, network
connections, and other infrastructure. This is because unit tests focus on the code
you write.

Lesson Objectives
After completing this lesson, you will be able to:

o Describe the use of unit tests to improve the quality of code you write.
o List the principles of Test Driven Development (TDD).
Describe how loosely-coupled components increase the testability and
o
maintainability of your application.
Write unit tests against model classes, controllers, and views in an MVC web
o
application.
Describe how Inversion of Control (IoC) containers can instantiate controllers
o
and model classes.
o Run unit tests in Visual Studio 2012.
o Use a mocking tool to automate mock creation in unit tests.

Why Perform Unit Tests?

There are three types of tests you can use to identify bugs in your application:

Unit Tests: Unit tests check small aspects of functionality. For example, a unit
o
test may verify the return type of a single method. By defining many unit tests
for your project, you can ensure they cover all functional aspects of your web
application.
Integration Tests: Integration tests check how two or more components work

together. They can be used to check how


o
two or more classes interact with each other. Integration tests can also be used
to check how the entire web application, including the database and external
web services, works to deliver content.
Acceptance Tests: Acceptance tests focus on a functional or technical
requirement that must work for the stakeholders to accept the application.
Similar to integration tests, acceptance tests usually test multiple components
o working together.

Note: Unit tests are important because they can be defined early in
development. Integration and acceptance tests are usually run later, when
several components are approaching completion.

What Is a Unit Test?

A unit test is a procedure that verifies a specific aspect of functionality. Multiple


unit tests can be performed for a single class and even for a single method in a
class. For example, you can write a test that checks that the Validate method
always returns a Boolean value. You might write a second test that checks that
when you send a string to the Validate method, the method returns a true value.
You can assemble many unit tests into a single class called a test fixture. Often, a
test fixture contains all the tests for a specific class. For example,
ProductTestsFixture may include all tests that check methods in the Product
class.

A single unit test usually consists of code that runs in three phases:

Arrange. In this phase, the test creates an instance of the class that it will test.
1.
It also assigns any required properties and creates any required objects to
complete the test. Only properties and objects that are essential to the test are
created.
Act. In this phase, the test runs the functionality that it must check. Usually, in
2. the Act phase, the test calls a single procedure and stores the result in a
variable.
Assert. In this phase, the test checks the result against the expected result. If
3.
the result matches what was expected, the test passes. Otherwise, the test fails.

How Do Unit Test Help Diagnose Bugs?

Because unit tests check a small and specific aspect of code, it is easy to diagnose
the problem when the tests fail. Unit tests usually work with a single class and
isolate the class from other classes wherever possible. If other classes are
essential, the smallest number of classes are created in the Arrange phase. This
approach enables you to fix issues rapidly because the number of potential
sources of a bug is small.

Unit tests should check the code that you write and not any infrastructure that the
production system will rely on. For example, unit tests should run without
connecting to a real database or web service because network problems or service
outages may cause a failure. Using this approach, you can distinguish bugs that
arise from code, which must be fixed by altering code, from the bugs that arise
from infrastructure failures, which must be fixed by changing hardware,
reconfiguring web servers, reconfiguring connection strings, or making other
configuration changes.

Automated Unit Testing

It is important to understand that unit tests, after they are defined, can be rerun
quickly and easily throughout the rest of the project life cycle. In fact, Microsoft
Visual Studio reruns tests automatically whenever you run a project with
debugging. You can also manually initiate tests any time.

This is important because new code can cause bugs at any stage of the
development process. As an example, consider a project that proceeds through
three phases. A unit test defined for phase 1 helps highlight problems in phases 2
and 3 that might otherwise go unnoticed:

Phase 1. The ProductController class is defined and the Test_Index_Action


unit test is written. The test checks that the Index action works with an integer
1.
parameter. When you call the Index action with an integer, the action returns a
collection that includes the same number of Product objects. The test passes.
Phase 2. A developer modifies the Index action so that it returns a partial
view. The developer renames the action _Index to conform to the team’s
2. partial view naming convention. The test fails because the name has changed.
The developer modifies the test so that it calls the renamed action and the test
passes.
Phase 3. A developer modifies the Index action by writing a different
Language Integrated Query (LINQ) to implement a new functional
3. requirement. However, the developer makes a mistake in the LINQ syntax.
The Index action now returns zero products regardless of the integer that is
passed as a parameter. The test fails.

In Phase 2, the test failure arose because the action name had changed, not
because of a mistake in the action code. The solution was to change the name of
the action called in the test method, but this can remind developers to alter calls
to renamed actions throughout the solution.

In Phase 3, the test failure arose because the developer misunderstood LINQ or
made a typing error in the LINQ syntax. The unit test highlighted the error as
soon as it arose. This helps the developer focus on a solution to resolve the test
failure and ensure that new functionality does not cause failures in code written
earlier in the project.

Question: Board members want you to ensure that your web application
correctly calculates sales tax on every product in the catalog. Is this an example
of a unit test, an integration test, or an acceptance test?

Principles of Test Driven Development


You can use unit tests in any development methodology, including waterfall
projects, iterative projects, and Agile projects to spot potential bugs and improve
the quality of the final application. Any project can benefit from unit testing,
regardless of the development methodology used in the project. However, a
specific development methodology, called Test Driven Development (TDD),
places unit testing at the center of working practices. TDD is often described as a
separate development methodology. Some authors consider it to be a

core principle of the Extreme Programming methodology.

Write the Test, Pass the Test, Refactor

In TDD, developers repeat the following short cycle to implement a functional


requirement:

Write the Test. The developer starts by creating and coding the unit test. This
step requires a full understanding of the functional requirement, which can be
1.
obtained from use cases or user stories. Because the developer has not written
any code in the application, the test fails.
Pass the Test. The developer writes some quick and simple code in the
application so that it passes the test. During the first iteration, this code is
2.
frequently inelegant and may include false assumptions such as hardcoded
values.
Refactor. The developer cleans up the application code, removes duplicate
3.
code, removes hardcoded values, improves readability, and makes other
technical improvements. The developer reruns the test to ensure that
refactoring has not caused a failure.

The cycle is then repeated. In each iteration, the developer adds a small new
element of the final functionality with a corresponding test.

It is important that the code in your tests is treated as production code. It should
be well thought out and easy to read so that other developers can understand the
test and quickly diagnose any test failures.

Test Driven Development Principles

TDD is different from traditional approaches to application development. To use


TDD effectively, you must understand its fundamental principles:

Write tests before code. In the TDD development cycle, the test is created in
step one before any code in the application. This means the test must fail the
o first time it is run. You can understand the test as a specification for the
functionality you are building. By writing the test first, you ensure that you
begin with a thorough understanding of the problem you are trying to solve.
Move in small steps. By breaking a large application down into small elements
of functionality, you can improve developer productivity. You can do this by
o giving a developer a small problem to solve in each iteration. The developer
can solve the simple problem quickly and understand all the possible
circumstances in which their code runs.
Only write enough code to pass the test. In each iteration, do not be tempted to
add extra code that is not related to the test. For example, if you know that
o users will call an action with other parameters than the ones in the test, do not
write code to handle these parameters. Instead, during the next iteration, write a
second test for those parameters. Then write and refactor that code.

Developers can refer to tests as examples of how to use a class or method. This
can increase developer productivity because developers can view the code that
demonstrates the method or class.
Note: In the lab, you will use some TDD principals as you develop the solution.
However, the lab does not conform to a strict reading of the TDD methods.

Question: You have written a controller for the Comment model class. You
write a unit test that checks that the Index action returns a collection of
Comment objects. Have you conformed to TDD principles?

Writing Loosely Coupled MVC Components

A loosely coupled application is one in which each component requires few or no


details of the other components of the system. In object-oriented programming,
for example, two classes can be described as loosely-coupled if one class can call
methods on the other class without any code that is specific to the other class.
When system components are loosely-coupled in this manner, it is easy to
replace a class with another implementation of the same functionality. Loosely
coupled components are essential for thorough unit testing because classes that
deal with real

data, such as data from a database, can be easily be replaced with classes that
deal with test data.

Using Loose Coupling in Tests

A loosely-coupled application is easy to test because you can make tests simpler
by replacing a fully functional instance of a class with a simplified instance that
is specifically designed for the test. Replacing classes in tests in this manner can
only be done when components are loosely coupled. Replacement instances used
for unit tests are known as test doubles or fakes. A test double or fake includes
just enough code and properties to pass the relevant test and prove the
functionality.

Other Benefits of Loose Coupling

Loose coupling has other benefits besides testing. Loose coupling makes it easier
to replace simple components with more sophisticated ones—for example, in
version one of an application you might write a class that calculates a simple
arithmetical mean. In version two, you might replace this class with a new class
that calculates a weighted mean based on a more complex algorithm. If the
components are loosely coupled, you can perform this replacement without
modifying any code outside of the averaging classes.

Using Interfaces for Loose Coupling

In object-oriented programming, an interface defines a set of properties and


methods. Any class that implements that interface must implement all the
properties and methods it defines as a minimum. This creates loose coupling
because you need not specify a class in code. Instead, you can specify any
implementation of a particular interface.

Loose Coupling in an MVC Web Application

To show how loose coupling can be used in an MVC web application, consider
the following scenario:

You are writing an MVC web application that displays a product catalog and
enables users to click a product to view the full details. On the product details
page, users can view and add reviews of that product. You want to ensure during
testing that the Product.Reviews property, which is a collection of Review
objects, only includes reviews with the right ProductID value.
Recall that unit tests should not rely on infrastructure such as network
connections or database servers, but only on test code. By contrast, in production,
the application will obtain all product reviews from a database. To satisfy the
needs of testing and production, you can build the following components:

An IProduct interface. This includes a definition of the Reviews property,


o together with other properties and methods. This interface is known as a
repository.
A Product class. This is the implementation of the IProduct repository that the
o application uses in production. When the user calls the Reviews property, all
the reviews for the current product are obtained from the database.
A TestProduct class. This is the test double or fake implementation of the
IProduct repository that the test uses. The test sets up a TestProduct object
o and fake reviews with different ProductID values. The test calls the
TestProduct.Reviews property and checks that only the right reviews are
returned.

Notice that, in the test, the TestProduct double uses in-memory data set up
during the Arrange phase. It does not query the database. Therefore, you can test
your code without relying on the network connection to the database or the
database server itself. This approach also ensures that the test runs quickly, which
is important because slow tests discourage developers from running tests
regularly.

Question: In a test, you create a fake collection of BlogEntry objects. Is this an


example of an interface or a test double?

Writing Unit Tests for MVC Components


The Microsoft ASP.NET MVC 4 programming model is easy to integrate with
the principles of unit testing and TDD because of its separation of concerns into
model, controllers, and views.

Models are simple to test because they are independent classes that you can
instantiate and configure during the Arrange phase of a test.

Controllers are simple classes that you can test, but it is complex to test
controllers with in-memory data, rather than using a database. To test controllers
with in-memory data, you create a test double class, also known as a fake
repository.

Objects of this class can be populated with test data in memory without querying
a database. You need to understand how to write test doubles and how to write a
typical test for MVC classes.

Add and Configure a Test Project

In Microsoft Visual Studio 2012, you can test an MVC web application project
by adding a new project to the solution, based on the Unit Test Project template.
You must add references to the test project so that test code can access classes in
the MVC web application project. You will also need a reference to
System.Web.Mvc and other namespaces from the Microsoft .NET Framework.

In a Visual Studio test project, test fixtures are classes marked with the
[TestClass] annotation. Unit tests are methods marked with the [TestMethod]
annotation. Unit tests usually return void but call a method of the Assert class,
such as Assert.AreEqual() to check results in the test Assert phase.

Note: There are many other test frameworks available for MVC web applications
and you can choose the one you prefer. Many of these frameworks can be added
by using the NuGet package manager available in Visual Studio. If you use
Visual Studio Express, you cannot use the Visual Studio Unit Test Project
template, but you can add other testing frameworks by using NuGet.

Test Model Classes and Business Logic

In MVC, model classes do not depend on other components or infrastructure.


You can easily instantiate them in-memory, arrange their property values, act on
them by calling a method, and assert that the result was as expected. Sometimes,
you create business logic in the model classes, in which case the Act phase
involves calling a method on the model class itself. If, by contrast, you have
created a separate business logic layer, code in the Act phase must call a method
on the business object class and pass a model class.

The code in this test creates an instance of the Product model class and sets its
Type property. The test checks that in these circumstances, the GetAccessories()
method returns a collection of BikeAccessory objects.

Testing a Model Class

[TestMethod]

public void Test_Product_Reviews()

//Arrange phase

Product testProduct = new Product();

testProduct.Type = "CompleteBike";
//Act phase

var result = testProduct.GetAccessories();

//Assert phase

Assert.AreEqual(typeof(IEnumerable(BikeAccessory)), result.GetType());

Create Repository Interfaces

A repository is an interface that defines properties and methods that MVC can
use to store data in a web application. It is common to create a single repository
interface for your entire web application.

In the following code example, the IWebStoreContext interface is a repository


that defines methods such as Add() and Delete(), and properties such as
Products.

A Repository Interface

public interface IWebStoreContext

IQueryable<Product> Products { get; }

T Add<T>(T entity) where T : class;

Product FindProductById(int ID);

T Delete<T>(T entity) where T : class;

}
Implement and Use a Repository in the Application

The repository interface defines methods for interacting with data but does not
fix how that data will be set and stored. You must provide two implementations
of the repository:

An implementation of the repository for use in production and development.


o This implementation will use data from the database or some other storage
mechanism.
An implementation of the repository for use in tests. This implementation will
o
use data from the memory set during the Arrange phase of each test.

The following code example shows how to implement the repository interface in
your MVC project for use in production and development.

Implementing a Repository in the MVC Project

public class WebStoreContext : DbContext, IWebStoreContext

public DbSet<Product> Products { get; set; }

IQueryable<Product> IWebStoreContext.Products { get { return Photos; }

T IWebStoreContext.Add<T>(T entity)

return Set<T>().Add(entity);

Product IWebStoreContext.FindProductById(int ID)


{

return Set<Product>().Find(ID);

T IWebStoreContext.Delete<T>(T entity)

return Set<T>().Remove(entity);

Note that the WebStoreContext class still inherits from the Entity Framework
DbContext class but also implements the IWebStoreContext interface that you
just created. In fact, the interface methods such as Add(), Delete(), and
FindProductById() just wrap methods from the DbContext class such as
Remove().

Implement a Repository Test Double

The second implementation of the repository interface is the implementation that


you will use in unit tests. This implementation uses in-memory data and a keyed
collection of objects to function just like an Entity Framework context, but
avoids working with a database.

The following code example shows how to implement a repository class for tests.

Implementing a Fake Repository

class FakeWebStoreContext : IWebStoreContext

{
//This object is a keyed collection we use to mock an

//entity framework context in memory

SetMap _map = new SetMap();

public IQueryable<Product> Products

get { return _map.Get<Product>().AsQueryable(); }

set { _map.Use<Product>(value); }

public T Add<T>(T entity) where T : class

_map.Get<T>().Add(entity);

return entity;

public Product FindProductById(int ID)

Product item = (from p in this.Products

where p.ProductID == ID

select p).First();

return item;
}

public T Delete<T>(T entity) where T : class

_map.Get<T>().Remove(entity);

return entity;

class SetMap : KeyedCollection<Type, object>

public HashSet<T> Use<T>(IEnumerable<T> sourceData)

var set = new HashSet<T>(sourceData);

if (Contains(typeof(T)))

Remove(typeof(T));

Add(set);

return set;

}
public HashSet<T> Get<T>() { return (HashSet<T>) this[typeof(T)];

protected override Type GetKeyForItem(object item)

return item.GetType().GetGenericArguments().Single();

Using the Test Double to Test a Controller

After you have implemented a test double class for the repository, you can use it
to test a controller in a unit test. In the Arrange phase of the test, create a new
object from the test double class and pass it to the controller constructor. The
controller uses this object for its Entity Framework context during the test Act
phase. This enables you to check results.

The following code example shows how to test a controller action by using a test
double for the Entity Framework context.

Using a Test Double to Test a Controller

[TestMethod]

public void Test_Index_Model_Type()

var context = new FakeWebStoreContext();


context.Products = new[] {

new Product(),

new Product (),

new Product ()

}.AsQueryable();

var controller = new ProductController(context);

var result = controller.Index() as ViewResult;

Assert.AreEqual(typeof(List<Product>), result.Model.GetType());

Note that the test creates a new instance of the FakeWebStoreContext class and
adds three Product objects to it. In this case, you can run the test without setting
any properties on the Product objects. This context is passed to the
ProductController constructor and the test proceeds to the Act and Assert
phases.

Question: For what purpose would you use a fake repository when you write
unit tests against an MVC controller?

Specifying the Correct Context


When you use test doubles for unit testing MVC controllers, you must ensure that
the controller uses the correct context in two different scenarios: unit tests, and at
all other times. If you use the test double production code, for example, no data
will be stored in the database. If you use the actual Entity Framework context for
unit testing, all the tests will fail. The following table gives further details.

Scenario Context

In unit In a unit test, you should test code without relying on


tests underlying infrastructure such as databases. You can use a test
double class that behaves like an Entity Framework context, but
uses in-memory data.

At other When you are not unit testing the code, you use an actual Entity
times Framework context in your controller code, which interacts with
a database.

Using Constructors to Specify a Repository

You can specify the correct repository to use in a test by using controller
constructors. During a unit test, call a controller constructor that takes an instance
of the repository interface as a parameter. At other times, the MVC controller
factory will call the controller constructor without any parameters.

The following code example shows the constructors in an MVC controller that
you can use for production and unit testing.

Using Constructors to Specify Repositories

public class ProductController : Controller

private IWebStoreContext context;

//The parameterless version of the constructor is used by the MVC

controller factory

public ProductController()

//Instantiate an actual Entity Framework context

context = new WebStoreContext();

//This constructor is used by unit tests. They pass a test double

context

public ProductController(IWebStoreContext Context)

//Use the context passed to the constructor


context = Context;

//Add action methods here

Using Inversion of Control Containers

You can also ensure that the correct repository class is used in each context by
using an Inversion of Control (IoC) container. An IoC container is a framework
that you can add to your application that instantiates classes. You must configure
the IoC container so that it can identify the kind of object to create when the
application expects a specific interface. For example, when code is used to create
a new instance of the IWebStoreContext interface, the IoC container checks its
configuration and finds that it should instantiate the WebStoreContext class,
which is an Entity Framework context that implements the IWebStoreContext
interface.

Note: IoC frameworks are also known as Dependency Injection (DI) frameworks
because they inject classes that implement the correct interfaces into class
constructors.

By using an IoC container, you avoid the need to create two constructors for
controller classes. During tests, you can instantiate the test double and pass it to
the controller constructor. At other times, the IoC container instantiates the actual
Entity Framework context and passes it to the controller constructor.

Note: There are many IoC containers designed for use with ASP.NET MVC web
applications. These replace certain components of the MVC framework to
support IoC. For example, they replace the default controller factory with a
factory that instantiates controllers with the right context class. Many IoC
containers are available in the NuGet package library, such as NinJect and
StructureMap.
Question: Which approach is more loosely-coupled: using constructors to
specify the context, or using IoC containers to specify the context?

Demonstration: How to Run Unit Tests


In this demonstration, you will see how to add a new test project to your
ASP.NET MVC 4 solution, and how to create and run a simple unit test against
the home page controller.

Demonstration Steps
In the Solution Explorer pane of the OperasWebSite - Microsoft Visual
1. Studio window, right-click Solution ‘OperasWebSite’ (1 project), point to
Add, and then click New Project.
In the navigation pane of the Add New Project dialog box, under Installed,
2.
expand Visual C#, and then click Test.
In the result pane of the Add New Project dialog box, click Unit Test
3.
Project, in the Name box, type OperasWebSiteTests, and then click OK.
In the Solution Explorer pane, under OperasWebSiteTests, right-click
4.
References, and then click Add Reference.
In the navigation pane of the Reference Manager - OperasWebSiteTests
5.
dialog box, click Solution.
In the Name column of the result pane, click OperasWebSite, select the
6.
check box corresponding to OperasWebSite, and then click OK.
In the Solution Explorer pane, under OperasWebSiteTests, right-click
7.
References, and then click Add Reference.
In the navigation pane of the Reference Manager - OperasWebSiteTests
8.
dialog box, click Assemblies, and then click Extensions.
In the Name column of the result pane, click System.Web.Mvc with version
9.
number 4.0.0.0, select the corresponding check box, and then click OK.
In the Solution Explorer pane, under OperasWebSiteTests, right-click
10.
UnitTest1.cs, and then click Rename.
In the Solution Explorer pane, replace UnitTest1 with
11.
HomeControllerTests.cs, and then press Enter.
12. In the Microsoft Visual Studio dialog box, click Yes.
In the HomeControllerTests.cs code window, locate the following code.
13.
public void TestMethod1()

Replace the code with the following code.


14.
public void Test_Index_Return_View()

Place the mouse cursor at the end of the


Microsoft.VisualStudio.TestTools.UnitTesting namespace, press Enter, and
then type the following code.

15. using System.Web.Mvc;

using OperasWebSite.Controllers;

using OperasWebSite.Models;

In the Test_Index_Return_View code block, press Enter, and then type the
16.
following code.
HomeController controller =

new HomeController();

var result = controller.Index()

as ViewResult;

Assert.AreEqual("WrongName",

result.ViewName);

Note: This test is created to show the students a failing test.


On the TEST menu of the OperasWebSite - Microsoft Visual Studio
17.
window, point to Run, and then click All Tests.
In the Failed Tests (1) section of the Test Explorer pane, note that
18.
Test_Index_Return_View is listed.
19. In the Test Explorer pane, click Test_Index_Return_View.
At the lower part of the Test Explorer pane, drag the separator upward, and
20.
then view the test results.
21. In the Test Explorer pane, click the Close button.
In the Solution Explorer pane, under OperasWebSiteTests, click
22.
HomeControllerTests.cs.
In the HomeControllerTests.cs code window, locate the following code.

23. Assert.AreEqual("WrongName",

result.ViewName);

Replace the code with the following code.

24. Assert.AreEqual("Index",

result.ViewName);.

On the TEST menu of the OperasWebSite - Microsoft Visual Studio


25.
window, point to Run, and then click All Tests.
In the Passed Tests (1) section of the Test Explorer pane, note that
26.
Test_Index_Return_View is listed.
In the Test Explorer pane, click Test_Index_Return_View, and then, in the
27.
lower part of the Test Explorer pane, view the test results.
28. In the Test Explorer pane, click the Close button.
In the OperasWebSite - Microsoft Visual Studio window, click the Close
29.
button.

Using Mocking Frameworks


When you write a unit test, you must, during the Arrange phase, create test data
on which the test will run. By using a test double or mock object to supply test
data, you can test your code in isolation from other classes and from the
infrastructure elements such as databases and network connections on which the
application will rely. You can create test doubles by manually coding their
instantiation, setting their properties, and populating collections. Such test
doubles are known as manual mock objects.

Alternatively, instead of creating mock objects

manually with your own code, you can use a mocking framework to automate
this work. A mocking framework automatically creates mock object by using the
interfaces that you specify. In the case of IoC containers, there are many mocking
frameworks that can be used in testing MVC web applications. You can find
many mocking frameworks by using the NuGet package manager.

Note: Mocking frameworks for ASP.NET MVC 4 include Moq, RhinoMocks,


and NSubstitute. All these frameworks are available in NuGet and there are
alternatives. Choose the framework that best suits your testing needs.

Why Use a Mocking Framework?

There are many situations in which mocking frameworks can significantly ease
unit testing. Even for simple tests, mocking frameworks reduce the amount of
setup code that you have to develop. After you become familiar with the mocking
framework that you choose, and have learned how to write arrangement code for
it, you will begin to save time. In more complex situations, such as the following,
mocking frameworks have great advantages:

Creating multiple mock objects of a single type. You should try to keep each
unit test as simple as possible, but inevitably, some tests require many mock
objects to work with. For example, if you are testing a method that underlies
o
paging functionality in your web application, you must create enough mock
objects to populate multiple pages. Mocking frameworks can automate the
creation of multiple mock objects of the same type.
Mocking objects with multiple interfaces. In some tests, where there are several
dependencies between classes of different types, you must create many mock
o objects of different classes. In such situations, it is tedious to manually code
many mock objects. Mocking frameworks can help by automatically generating
the objects from the interfaces that you specify.

In each unit test, you are interested in a small and specific area of functionality.
Some properties and methods of an interface will be crucial to your test, while
others will be irrelevant. A mocking framework enables you to specify irrelevant
properties and methods in a given test. When the framework creates a mock
object for your test, it creates stubs for the irrelevant properties and methods. A
stub is a simple implementation with little code. In this way, the mocking
framework frees you from having to implement all the requirements of the
interface laboriously.

Question: What is the difference between an IoC container and a mocking


framework?

Lesson 2: Implementing an Exception Handling


Strategy
Unexpected events are likely to occur from time to time in any complex system,
including MVC web applications. Occasionally, such unexpected run-time events
cause an error. When this happens, ASP.NET or the .NET Framework generates
an exception, which is an object that you can use to diagnose and resolve the
error. The exception contains information that you can use to diagnose the
problem. Exceptions that are not handled in your code will cause the web
application to halt and an error message to be displayed to the user. As a web
developer, you need to know how to detect, handle, and raise exceptions, and
identify the cause of the problem. Visual Studio provides a broad range of tools
for debugging exceptions and improving the robustness of your code. You can
also log exceptions to databases and other stores, and use the .NET Framework
code contracts to reduce the frequency of exceptions.

Lesson Objectives
After completing this lesson, you will be able to:

o Explain how to raise and catch exceptions.


o Explain how to configure exception handling by using Web.config.
o Explain how to trace exceptions by using the IntelliTrace tool.
o Describe how to log exceptions.
o Describe the health monitoring options for an MVC 4 web application.

Raising and Catching Exceptions

An error is an unexpected run-time event that prevents an application from


completing an operation. When a line of code causes an error, ASP.NET or the
common language runtime creates an exception. This exception is an object of a
class that inherits from the System.Exception base class. There are many
exception classes.

Often the object class identifies what went wrong.

For example, if there is an

ArgumentNullException, it indicates that a null value was sent to a method that


does not accept a null value as an argument.

Unhandled Exceptions

When an exception is not explicitly handled by an application, the application


stops and the user sees an error message. In ASP.NET MVC applications, this
error message is in the form of a webpage. You can override ASP.NET default
error pages to display your own error information to users.

If an unhandled exception arises while you are debugging the application in


Visual Studio, execution breaks on the line that generated the exception. You can
use the Visual Studio debugging tools to investigate what went wrong, isolate the
problem, and debug your code.

Sometimes, you may also want to raise your own exceptions as a form of
communication between parts of your application. For example, consider an
application that displays products on a website. In the repository, you implement
a FindProduct method that returns the product with a name that matches the
search string that is passed as an attribute. If the FindProduct method does not
locate a product with the specified name, you may wish to raise an exception.
This approach enables code in the controller, which calls the FindProduct
method, to handle the event that no products are found. You can use the throw
keyword to raise errors in C# code.

Catching Errors with Try/Catch Blocks

The most familiar way to catch an exception, which works in any .NET
Framework code, is to use the try/catch block. Code in the try block is run. If
any of that code generates an exception, the type of exception is checked against
the type declared in the catch block. If the type matches, or is of a type derived
from the type declared in the catch block, the code in the catch block runs. You
can use the code in the catch block to obtain information about what went wrong
and resolve the error condition.

The following code example catches any ArgumentNullException objects.

A Simple Try/Catch Block

try

Product product = FindProductFromComment(comment);

catch (ArgumentNullException ex)

Console.WriteLine("The comment object was null. Error message: " +

ex.Message);

In MVC controllers, there are two methods to catch exceptions—the


OnException method and the [HandleError] annotation.

Catching Controller Exceptions in OnException

The OnException method is defined on the base Controller class, so you can
override it in any MVC controller. When you override the OnException method
in a custom controller, MVC runs the method whenever an exception arises and
is not handled in a try/catch block. Using this approach, you can handle errors
anywhere in your controller without adding many try/catch blocks throughout
the code.

In the OnException method, you can catch specific types of exceptions by


checking the ExceptionContext.Exception property. Your code must set the
context.Result property to display a view to the user. If you do not set this
property, the browser displays a blank webpage to the user.

In the following code example, the OnException method is used to catch


InvalidOperationException objects.

Using OnException to Catch Controller Errors

protected override void OnException(ExceptionContext context)

// Catch invalid operation exception

if (filterContext.Exception is InvalidOperationException)

var model = new HandleErrorInfo(context.Exception, controllerName,

actionName);

var result = new ViewResult

ViewName = "Error",

ViewData = new ViewDataDictionary<HandleErrorInfo>(model),

//Save pass the current Temp Data to the Error view, because

it often
contains

//diagnostic information

TempData = context.Controller.TempData

};

context.Result = result;

Catching Controller Exceptions with HandleError

Using the [HandleError] annotation, you can use an attribute on individual


action methods or on the controller class itself, in which case, the [HandleError]
annotation catches errors in any action. When you use the [HandleError]
annotation without properties, all exceptions are caught and sent to an MVC view
called Error.cshtml. This default error view should be created in the
/View/Shared folder.

You can use two properties to control the behavior of [HandleError]:

ExceptionType. By default, the [HandleError] annotation catches all


o exceptions. If you set a more specific type with the ExceptionType property,
only exceptions of that specific type will be caught.
View. By default, the [HandleError] annotation forwards users to the
Error.cshtml view. You can specify another view file by using the View
o property. By setting both the ExceptionType and View properties, you can
divert exceptions of specific types to views designed specifically to display
them.
In the code example, the first [HandleError] annotation forwards
NotImplementedException errors to the NotImplemented view. All other
errors are forwarded to the default error view.

Using the HandleError Annotation

[HandleError(ExceptionType=typeof(NotImplementedException),

View="NotImplemented")]

[HandleError]

public ActionResult Index()

//Place action code here

Question: You are using the [HandleError] annotation to catch exceptions in


your web application. However, you realize that [HandleError] catches all
exceptions, making it difficult for you to isolate a specific issue. What can you do
to narrow down the exceptions that the [HandleError] annotation is catching?

Configuring Exception Handling


ASP.NET applications display a default error page to users when an unhandled
exception occurs in your MVC web application. There are two reasons why you
may want to change the default error page:

You want to display a branded and styled error page that has the same layout as
o
other pages in the application and includes the company logo.
You want to avoid drawing attention to the technology that powers the site. By

letting malicious users know that your


o
site runs ASP.NET MVC, you may encourage them to attack it by using
methods that have worked in the past.

To configure a custom error page for your application, use the top-level
Web.config file. The custom error page will be displayed when an exception in
not handled by any try/catch block or [HandleError] attribute.

Custom Error Modes

To configure custom errors, add the <customErrors> element to the Web.config


file. This element must be a child of the <system.web> element. Use the
following attributes:

mode: The mode attribute can be set to one of three values:

▪ Off: Unhandled errors are displayed on the default ASP.NET error page.
On: Unhandled errors are displayed in the page you specify in the

defaultRedirect attribute.
o RemoteOnly: In this mode, unhandled errors are displayed differently for
browsers on remote computers and browsers on the web server. In a
production site, all browsers are remote and errors are displayed on the page

that you specify in the defaultRedirect attribute. In development situations,
the developer often browses to the site on the local computer. When an error
occurs, the developer is directed to the default ASP.NET error page, which
includes debugging information such as the stack trace. Use the RemoteOnly
mode on development computers.
defaultRedirect: This attribute sets the name of the view that will be used to
o display unhandled exceptions. When you create this view, place it in the
Views/Shared folder.

The code in the following example enables custom errors and specifies that
unhandled exceptions are forwarded to the customError view.

Configuring Custom Errors

<system.web>

<customErrors mode="On" defaultRedirect="CustomError" />

</system.web>

HTTP error pages

Some Hypertext Transfer Protocol-level (HTTP) errors cannot be caught by


custom MVC error views as specified in Web.config or the [HandleError]
annotation. For such errors, you can use the <error> element in Web.config, as a
child element of the <customErrors> element.

In the following example, the <error> element is used for specific HTML files
to respond to HTTP 500 errors.

Catching HTTP Error Codes

<customErrors mode="On" defaultRedirect="CustomError" >

<error statusCode="500" redirect="~/Error/Error500.html" />

</customErrors>
Question: You have switched off custom errors in the Web.config file. When
you run your application without debugging, an exception is thrown in a
try/catch block. What page displays the exception to the user?

Using Visual Studio IntelliTrace in MVC

When something goes wrong in your web application, whether it happens during
development or in production, you need information about the state of the
application, to diagnose the problem. Sometimes, a small amount of information
is sufficient. For example, you may be able to see from the URL query string that
a link was formulated wrongly. Often, however, problems arise in more obscure
places and you need as much information as possible to perform a diagnosis.
IntelliTrace is a feature of Visual Studio that assists debugging by presenting

as much information as possible. IntelliTrace was introduced with Microsoft


Visual Studio 2010 Ultimate.

The Traditional Debugging Workflow

When developers debug malfunctioning code, they run the application in Visual
Studio debugging mode. If an unhandled exception occurs, Visual Studio breaks
execution and displays details such as the exception class and the exception
message. You can use the Locals, Call Stack, and Error List windows to
determine the values of variables and properties that may have caused the
exception. All these pieces of information are presented as they were when the
error occurred.
If a problem originated before the error occurred, you must halt debugging, set a
break point, and then restart debugging. Again, Visual Studio halts execution, but
this time, it is at the break point. You can use the same windows to gain
information and step through code, line by line, to see how values change, and
diagnose the error.

Two problems can occur in this workflow:

If you set the break point too late, you will miss the origin of the error. You
o
must set another break point and restart debugging.
If you are stepping through many lines of code, you can miss the error by
o selecting Debug|StepInto or pressing the F11 shortcut too many times. This is
easy to do when there are hundreds of lines of code to step through.

Debugging With IntelliTrace

IntelliTrace improves this workflow and addresses the two problems that arise
during the traditional debugging workflow by recording a timeline of code
execution. When you run an application in the debug mode, IntelliTrace records
all the events that occur in the background. This can include exceptions,
debugging events such as break points, and other events that you can configure.

As before, when the debugger encounters an unhandled exception or a break


point, Visual Studio halts execution and displays the details of any exception.
However, the developer can now see all the recorded events in the IntelliTrace
pane. The current event appears at the end of the list and is named Live Event.
You can see all the previous events in the list and can click them for more details.
In this way, you can investigate what happened before the exception or the break
point.

When you click an earlier event in the IntelliTrace pane, the Locals, Call Stack,
and Error List windows display the state of the application at the moment of the
earlier event. The line of code that corresponds to the selected event is
highlighted in orange color. Because of this highlighting, two problems that arise
during the traditional debugging workflow are eased, namely, missing the origin
of error and stepping too far through the code. Because the relevant code is
highlighted, if you miss the origin of the error or step too far through the code,
you can get back to earlier events and investigate values.

To help you locate the correct event in the IntelliTrace window, you can filter by
event category or execution thread, or use the search option.

IntelliTrace Configuration Options

To configure IntelliTrace, click DEBUG, click IntelliTrace, and then click


Open IntelliTrace Settings. You can enable or disable IntelliTrace event
recording and specify a location and maximum size for the IntelliTrace files.

Most of the configuration options concern the amount of data to record in


IntelliTrace files. The default settings have a mimimal affect on performance, but
if those are insufficient to diagnose a problem, you can choose to log more
information to target the problem. This may compromise performance, but
remember that IntelliTrace information is only recorded during debugging. Your
settings will not degrade performance after the application is deployed to a web
server. Under General, you can set IntelliTrace to record IntelliTrace events
only, or both IntelliTrace events and call information, which includes all calls to
methods and classes. You can configure what is included in IntelliTrace events
by using the IntelliTrace Events list. For example, by default, ASP.NET events
such as error pages, page post backs, and redirects are included for MVC
applications.

Saving and Opening IntelliTrace Files

IntelliTrace automatically saves events in an IntelliTrace file when you enter


debug mode. The file is automatically deleted when you close Visual Studio, to
ensure that IntelliTrace files do not over-use disk space. Note that this means that
the IntelliTrace pane includes events from the current debugging session and any
previous debugging sessions run since you started Visual Studio. However, these
files are temporary.
You can avoid losing an IntelliTrace file when you close Visual Studio by saving
it for later analysis. To do this, click DEBUG, click IntelliTrace, and then click
Save IntelliTrace Session. The file is saved with an .iTrace extension. If you
double-click an .iTrace file, Visual Studio displays the threads, exceptions,
modules, and other information that the file contains.

Additional Reading: For more information about IntelliTrace and how to use it,
see http://go.microsoft.com/fwlink/?LinkID=288962&clcid=0x409

Question: You are looking at IntelliTrace events and suspect that the error
originated in a class written by a colleague who works in another country. How
can you help the colleague to see the events that you can see in IntelliTrace after
you close Visual Studio?

Logging Exceptions

Exceptions that you face during development can be investigated and debugged
by using the Visual Studio debugging tools, including IntelliTrace. In an ideal
situation, no exceptions would arise when your web application is complete and
deployed for users over the Internet. However, in the real world, unforeseen
circumstances arise resulting in exceptions. For example, database failures,
network issues, and configuration errors in any part of the system can cause
exceptions.

You have already seen how to present a branded and informative custom error
page to users when
exceptions occur. It is also appropriate to log the exceptions in a production web
application, so the administrators and developers can assess the extent of the
problem, remove the cause, and improve the robustness of the code.

Writing Error Logging Code

Before you write code to log exceptions in your web application, consider where
exceptions should be recorded. Generally, web applications log exceptions to an
Extensible Markup Language (XML) file. This approach can be efficient,
especially if the text file is kept on a separate drive from the database of the web
application and other critical, commonly accessed files. However, the file size of
the XML files can grow large, making them difficult to analyze.

A common approach is to log errors to tables in a database. These tables can be a


part of a single web application database, or you can place them in a dedicated
database away from product catalogs, user profiles, and other information. By
logging exceptions to a database, you create a list of exceptions that can be easily
searched and analyzed. You can also build a webpage to present these logged
exceptions to administrators so that they can access the details from a browser.

You should also consider sending email messages or other types of messages to
administrators and developers when exceptions occur. This approach ensures that
administrators and developers hear of an error very quickly. It does not require
them to review the exceptions logged in the database. Frequently, error handling
code in live applications both logs to a database and send email messages to
administrators and developers.

Where to Write Error Logging Code

When you decide where to write code that logs errors, you should consider that
errors might arise in almost any part of your application. You should choose an
approach that enables you to write error logging code once that will run for any
exception anywhere in your application.
For example, it is not appropriate to write error logging code in individual
try/catch blocks. If you do this, you will have to create a try/catch block for
every procedure in your application, and write duplicate logging code in the
catch block.

A more effective approach is as follows:

Create a custom base controller class for your web application. This class
o
inherits from the System.Web.Mvc.Controller base class.
In your custom base controller class, override the OnException() method.
o
Place you error logging code in this method.
When you create controllers, inherit from your custom base controller class,
o
instead of System.Web.Mvc.Controller.

In this way, you can write error logging code only once in the overridden
OnExcpetion() method. This catches exceptions from any of the inheriting
controllers.

Using Third-Party Logging Tools

Because exception logging is a very common functional requirement for web


applications, there are many third-party solutions that you can choose if you do
not want to write your own logging code. Many of these are available within
Visual Studio from the NuGet package manager.

Perhaps, the most commonly used and widely supported error logging package is
Error Logging Modules and Handlers (ELMAH). ELMAH can be used with any
ASP.NET web application and can log exceptions to XML files or a wide variety
of databases, including Microsoft SQL Server, Oracle, Microsoft SQL Server
Compact, MySQL, and others. In addition, ELMAH includes webpages that you
can use to remotely view exception lists and details, and ELMAH can send alert
email messages to the address that you configure.

Question: You want to ensure that developers can review exception details that
arise during debugging. How should you approach error logging code?
Health Monitoring

Since ASP.NET version 2.0, you can use health monitoring to record what
happens in a web application. Health monitoring can record exceptions through
error logging techniques.

However, health monitoring can also record a wide range of other events such as
application starts and stops, failed logon attempts, membership events, and user
input validation errors. Some pieces of these information are difficult to access
from any other source.

Health Monitoring Features

You can customize the category of events that

health monitoring records. Each event is within one of the five following
categories.

Event Category Description

Application Application lifetime events include application starts and


Lifetime Events stops.

Audit Events Audit events include logons, logoffs, and logon failures.
Event Category Description

Error Events Error events incude .NET Framework exceptions and


HTTP errors such as 404 errors.

Request Request processing events include events that occur as


Processing ASP.NET controllers, models, and views receive and
Events respond to webpage requests.

Heartbeats Heartbeats are periodic events that health monitoring can


raise and record to confirm that the application is
running.

You can also customize the location where health monitoring stores event details
by configuring health monitoring providers. You can choose from the following
providers.

Health Monitoring Provider Description

EventLogWebEventProvider EventLogWebEventProvider sends


events to the Windows Event Log.
These events appear in the Windows
log.

SqlWebEventProvider SqlWebEventProvider sends events to a


SQL Server database.

WmiWebEventProvider WmiWebEventProvider sends events to


Windows Management Infrastructure
client.
Health Monitoring Provider Description

SimpleMailWebEventProvider SimpleMailWebEventProvider sends


events in an email message sent to an
address you specify.

TemplatedMailWebEventProvider TemplatedMailWebEventProvider also


sends events in an email message, but
you can use a template email to format
the information.

TraceWebEventProvider TraceWebEventProvider sends events to


the ASP.NET tracing system.

Configuring Health Monitoring

You configure health monitoring by using the <healthMonitoring> element


within the <system.web> element in Web.config. You can use elements within
<healthMonitoring> to add and configure providers and define rules that govern
how events of different types are recorded.

The following code example shows how to configure health monitoring to record
application life cycle events to a SQL Server database.

Configuring Health Monitoring

<system.web>

<connectionStrings>

<add name="HealthDB" connectionString="your connection string here"

/>
</connectionStrings>

<healthMonitoring enabled="true">

<providers>

<add name="sqlProvider"

type="System.Web.Management.SqlWebEventProvider"

connectionStringName="HealthDB"

buffer="false"

bufferMode="Notification" />

</providers>

<rules>

<add name="LifeCycle"

provider="sqlProvider"

eventName="Application Lifetime Events" />

</rules>

</healthMonitoring>

<system.web>

Additional Reading:

For full details of all the options that you can configure in Web.config for health
monitoring, see http://go.microsoft.com/fwlink/?LinkID=293685&clcid=0x409
If you configure health monitoring to use the SqlWebEventProvider, ASP.NET
will, by default, create a database file called, ASPNETDB.MDF, in the
App_Data folder of the web application. You can alter this location by using the
connection string in Web.config. However, health monitoring will only work if
certain data tables are present in the database that you connect to. You can
prepare the database with the correct tables by using the aspnet_regsql.exe tool.
This tool is found in the %WINDOWS%\Microsoft.NET\Framework\version
directory.

The following command prepares a SQL Server database for health monitoring,
authenticating as the current user.

aspnet_regsql.exe –E –S HealthDatabaseServer –d HealthDatabase –A w

Question: After using your recently-developed web application, several users are
facing failed logon attempts. As a result, to track these exceptions, you have
decided to set up a monitoring system that will send an email message to a
specified email address. Which health monitoring provider will you use to fix
this?

Lab: Testing and Debugging ASP.NET MVC 4 Web


Applications
Scenario

The Photo Sharing application is in the early stages of development. However,


frequent errors are hindering the productivity of the development team. The
senior developer advises that you intercept exceptions and other flaws as early as
possible. You have been asked to perform unit tests of the PhotoController to
ensure that all scenarios work as expected and to avoid problems later in the web
application development life cycle. You have also been asked to ensure that
when critical errors occur, developers can obtain helpful technical information.

Objectives
After completing this lab, you will be able to:

o Perform unit tests of the components of an MVC web application.


o Configure an exception handling strategy for an MVC web application.
o Use Visual Studio debugging tools against a web application.

Lab Setup

Estimated Time: 90 minutes

Virtual Machine: 20486B-SEA-DEV11

User name: Admin

Password: Pa$$w0rd

Note: In Hyper-V Manager, start the MSL-TMG1 virtual machine if it is not


already running.

Before starting the lab, you need to enable the Allow NuGet to download
missing packages during build option, by performing the following steps:

o On the TOOLS menu of the Microsoft Visual Studio window, click Options.
o In the navigation pane of the Options dialog box, click Package Manager.
Under the Package Restore section, select the Allow NuGet to download
o
missing packages during build checkbox, and then click OK.

Exercise 1: Performing Unit Tests

Scenario

In this exercise, you will:

Create a test project and write the following tests.


o
Test_Index_Return_View: This test checks that the Index action returns a

view named Index.
Test_PhotoGallery_Model_Type: This test checks that the _PhotoGallery
▪ action passes an enumerable list of Photo objects to the _PhotoGallery partial
view.
Test_GetImage_Return_Type: This test checks that the GetImage action

returns a file and not a view.
Test_PhotoGallery_No_Parameter: This test checks that when you call the
▪ _PhotoGallery action without any parameters, the action passes all the photos
in the context to the _PhotoGallery partial view.
Test_PhotoGallery_Int_Parameter: This test checks that when you call the
▪ _PhotoGallery action with an integer parameter, the action passes the
corresponding number of photos to the _PhotoGallery action.
o Implement a repository.
o Refactor the PhotoController to use a repository.
Refactor tests to use a mock repository.

Note: The tests you add to the solution in this exercise will improve the quality
o of code and prevent bugs as development proceeds. However, this exercise
does not conform to the principles of TDD because the PhotoController class
already exists. In TDD, you would create these and other tests first, and then
create a PhotoController class that passes the tests.

The main tasks for this exercise are as follows:

1. Create a test project.


2. Write the tests.
3. Implement a repository.
4. Refactor the photo controller to use the repository.
5. Refactor the tests to use a mock repository.
6. Add further tests.

Task 1: Create a test project.


Start the virtual machine and log on with the following credentials:

1. o Virtual Machine: 20486B-SEA-DEV11


o User name: Admin
o Password: Pa$$w0rd
Open the PhotoSharingApplication solution from the following location:

2.
File location: Allfiles
o
(D):\Labfiles\Mod06\Starter\PhotoSharingApplication
Add a new project to the solution for unit tests by using the following
information:
3.
o Template: Unit Test Project
o Name: PhotoSharingTests
Add a reference to the PhotoSharingApplication project in the
4.
PhotoSharingTests project.
Add a reference to the System.Web.Mvc assembly in the PhotoSharingTests
project by using the following information:
5.
o MVC version: 4.0.0.0

Task 2: Write the tests.

1. Rename the UnitTest1 class as PhotoControllerTests.


2. Rename the TestMethod1 method as Test_Index_Return_View.
Add using statements for the following namespaces:

o System.Collections.Generic
3. o System.Web.Mvc

o PhotoSharingApplication.Models
o PhotoSharingApplication.Controllers
In the Test_Index_Return_View test, create a new PhotoController, call the
4.
Index action, and assert that the name of the result view is Index.
Add a new test method by using the following information:

o Annotation: [TestMethod]
5. o Scope: public
o Return type: void
o Name: Test_PhotoGallery_Model_Type
o Parameters: None
In the Test_PhotoGallery_Model_Type test, create a new PhotoController,
6. call the _PhotoGallery action, and assert that the type of the result model is
List<Photo>.
Add a new test method by using the following information:

o Annotation: [TestMethod]
7. o Scope: public
o Return type: void
o Name: Test_GetImage_Return_Type
o Parameters: None
In the Test_GetImage_Return_Type test, create a new PhotoController, call
8.
the GetImage action, and assert that the result type is FileContentResult.
9. Run all the tests in the PhotoSharingTests project and examine the results.

Task 3: Implement a repository.

Add a new interface called IPhotoSharingContext to the Models folder in


1.
the PhotoSharingApplication project.
2. Set public scope to the new interface.
Add the Photos property to the IPhotoSharingContext interface by using
the following information:

3. o Type: IQueryable<Photo>
o Name: Photos
o Access: Read only
Add the Comments property to the IPhotoSharingContext interface by
using the following information:

4. o Type: IQueryable<Comment>
o Name: Comments
o Access: Read only
Add the SaveChanges method to the IPhotoSharingContext interface by
using the following information:
5.
o Return type: Integer
o Name: SaveChanges
Add the Add method to the IPhotoSharingContext interface by using the
following information:
6.
o Return type: T, where T is any class
o Parameter: an instance of T named entity
Add the FindPhotoById method to the IPhotoSharingContext interface by
using the following information:
7.
o Return type: Photo.
o Parameter: an integer named ID
Add the FindCommentById method to the IPhotoSharingContext interface
by using the following information:
8.
o Return type: Comment
o Parameter: an integer named ID
Add the Delete method to the IPhotoSharingContext interface by using the
following information:
9.
o Return type: T, where T is any class.
o Parameter: An instance of T named entity.
Ensure that the PhotoSharingContext class implements the
10.
IPhotoSharingContent interface.
In the PhotoSharingContext class, implement the Photos property from the
11. IPhotoSharingContext interface and return the Photos collection for the get
method.
In the PhotoSharingContext class, implement the Comments property from
12. the IPhotoSharingContext interface and return the Comments collection for
the get method.
In the PhotoSharingContext class, implement the SaveChanges method
13. from the IPhotoSharingContext interface and return the results of the
SaveChanges method.
In the PhotoSharingContext class, implement the Add method from the
14. IPhotoSharingContext interface and return a Set<T> collection with entity
added.
In the PhotoSharingContext class, implement the FindPhotoById method
15. from the IPhotoSharingContext interface and return the Photo object with
requested ID.
In the PhotoSharingContext class, implement the FindCommentById
16. method from the IPhotoSharingContext interface and return the Comment
object with requested ID.
In the PhotoSharingContext class, implement the Delete method from the
17. IPhotoSharingContext interface and return a Set<T> collection with entity
removed.
18. Save all the changes and build the project.

Task 4: Refactor the photo controller to use the repository.

In the PhotoController class, change the declaration of the context object so


1. it is an instance of the IPhotoSharingContext. Do not instantiate the context
object.
Add a new constructor to the PhotoController class. In the controller,
2.
instantiate context to be a new PhotoSharingContext object.
Add a second constructor to the PhotoController class that accepts an
3. IPhotoSharingContext implementation named Context as a parameter. In
the constructor, instantiate context to be the Context object.
In the PhotoController Display action, replace the call to
4.
context.Photos.Find() with a similar call to context.FindPhotoById().
In the PhotoController Create action for the POST verb, replace the call to
5.
context.Photos.Add() with a similar call to context.Add<Photo>.
In the PhotoController Delete action, replace the call to
6.
context.Photos.Find() with a similar call to context.FindPhotoById().
In the PhotoController DeleteConfirmed action, replace the call to
7.
context.Photos.Find() with a similar call to context.FindPhotoById().
In the PhotoController DeleteConfirmed action, replace the call to
8.
context.Photos.Remove() with a similar call to context.Delete<Photo>.
In the PhotoController GetImage action, replace the call to
9.
context.Photos.Find() with a similar call to context.FindPhotoById()
10. Run the application with debugging to ensure that the changes are consistent.

Task 5: Refactor the tests to use a mock repository.

1. Add a new folder called Doubles to the PhotoSharingTests project.


Add the FakePhotoSharingContext.cs existing file to the Doubles folder from
the following location:

2. Allfiles (D):\Labfiles\Mod06\Fake Repository\


FakePhotoSharingContext.cs
o
Note: This class will be used as a test double for the Entity Framework
context.
In the PhotoControllerTests.cs file, add using statements for the following
namespaces:
3.
o System.Linq
o PhotoSharingTests.Doubles
In the Test_Index_Return_View method, create a new instance of the
4. FakePhotoSharingContext class and pass it to the PhotoController
constructor.
In the Test_PhotoGallery_Model_Type method, create a new instance of the
5. FakePhotoSharingContext class, add four new Photo objects to the class,
and then pass them to the PhotoController constructor.
In the Test_GetImage_Return_Type method, create a new instance of the
6.
FakePhotoSharingContext class.
Add four new Photo objects to the context.Photos collection. Use the
following information to add each new Photo object:

7. o PhotoID: a unique integer value


o PhotoFile: a new byte array of length 1
o ImageMimeType: image/jpeg
Ensure that the new FakePhotoSharingContext object is passed to the
8.
PhotoController constructor.
Run all the tests in the PhotoSharingTests project and verify the status of all
9.
the tests.

Task 6: Add further tests.

In PhotoControllerTests.cs, add a new test method by using the following


information:

o Annotation: [TestMethod]
1. o Scope: public
o Return type: void
o Name: Test_PhotoGallery_No_Parameter
o Parameters: None
In the Test_PhotoGallery_No_Parameter method, create a new instance of
2. the FakePhotoSharingContext class, add four new Photo objects to the class,
and then pass them to the PhotoController constructor.
Call the _PhotoGallery action and store the PartialViewResult in a variable
3.
named result.
Cast the result.Model property as an IEnumerable<Photo> collection and
4. then check that the number of Photos in the collection is 4, which is the same
as the number of photos you added to the fake context.
In the PhotoControllerTests.cs code window, copy and paste the entire
5. Test_PhotoGallery_No_Parameter method. Rename the pasted test method
as Test_PhotoGallery_Int_Parameter.
In the Test_Photo_Gallery_Int_Parameter method, ensure that the call to the
6.
_PhotoGallery action passes the integer 3.
Assert that the number of Photo objects in the modelPhotos collection is 3,
7.
which is the integer you passed to the _PhotoGallery action.
Run all the tests in this PhotoSharingTests project and verify the status of all
8.
tests.

Results: After completing this exercise, you will be able to add a set of
PhotoController tests defined in the PhotoSharingTests project of the Photo
Sharing application.

Exercise 2: Optional—Configuring Exception Handling

Scenario

Now that you have developed unit tests for the Photo Sharing application, you
need to configure an exception handling strategy for the MVC web application.
This would ensure that when exceptions occur in the development phase of the
PhotoSharingApplication project, the controller, action, and exception messages
are displayed in a custom MVC error view. You also need to implement a
placeholder action for the SlideShow action in the PhotoController view. This
action will be completed during a later iteration of the project.

Complete this exercise if time permits.

The main tasks for this exercise are as follows:


1. Edit Web.config for exception handling.
2. Create a custom error view.
3. Configure errors in the PhotoController class.
4. Raise errors.

Task 1: Edit Web.config for exception handling.

Open the Web.config file in the root level folder of the


1.
PhotoSharingApplication project.
Add the <customErrors> element to the <system.web> element by using the
following information:

2. o Parent element: <system.web>


o Element: <customErrors>
o Mode: On
o defaultRedirect: ErrorPage
Add the <error> element to the <customErrors> element by using the
following information:

3. o Parent element: <customErrors>


o Element: <error>
o statusCode: 500
o redirect: Error.html
Add a new HTML page to the PhotoSharingApplication project by using the
following information:
4.
o Template: HTML Page
o Name: Error.html
5. In the Error.html file, set the contents of the TITLE element to Error.
6. Add content to the Error.html file to explain the error to users.

Task 2: Create a custom error view.


Add a new view to the Shared folder by using the following information:

1. o Name of the view: Error


o View type: Not strongly typed
o Layout or master page: None
In the Error.cshtml file, set the content of the TITLE element to Custom
2.
Error.
Set the @model for the Error.cshtml to
3.
System.Web.Mvc.HandleErrorInfo.
4. In the DIV element, render an H1 element by using the following information:
5. Content: MVC Error
6. In the DIV element, render the ControllerName property of the Model object.
7. In the DIV element, render the ActionName property of the Model object.
In the DIV element, render the Exception.Message property of the Model
8.
object.
9. Save all the changes made to the Error.cshtml file.

Task 3: Configure errors in the PhotoController class.

Modify the PhotoController class to send errors to the Error.cshtml view by


using the following information:

1. o Class: PhotoController
o Annotation: HandleError
o View: Error
Add a new action to the PhotoController class by using the following
information:

2. o Scope: public
o Return type: ActionResult
o Name: SlideShow
o Parameters: None
In the new action, throw an exception by using the following information:

3. o Type: NotImplmentedException

o Message: The SlideShow action is not yet ready

Task 4: Raise errors.

4. Start debugging and display Sample Photo 5.


In the Internet Explorer window, request the relative URL and view the error
details.
1.
o URL: /Photo/Display/malformedID
In the Internet Explorer window, request the relative URL.
2.
o URL: /Photo/SlideShow
3. Use the IntelliTrace pane to investigate the exception.
4. Stop debugging and close Visual Studio.

Results: After completing this exercise, you will be able to:

Configure a custom error handling strategy for an MVC application.

Question: When you ran the tests for the first time in Exercise 1, why did
Test_Index_Return_View pass, while Test_GetImage_Return_Type and
Test_PhotoGallery_Model_Type failed?

Question: In Exercise 1, why did all the tests pass during the second run?

Module Review and Takeaways


In this module, you became familiar with various techniques that you can use to
eliminate bugs from your ASP.NET MVC 4 web application. This begins early in
the development phase of the project, when you define unit tests that ensure that
each method and class in your application behaves precisely as designed. Unit
tests are automatically rerun as you build the application so you can be sure that
methods and classes that did work are not broken by later coding errors.
Exceptions arise in even the most well-tested applications because of unforeseen
circumstances. You also saw how to ensure that exceptions are handled
smoothly, and how error logs are optionally stored for later analysis.

Best Practice: If you are using TDD or Extreme Programming, define each test
before you write the code that implements a requirement. Use the test as a full
specification that your code must satisfy. This requires a full understanding of the
design.

Best Practice: Investigate and choose a mocking framework to help you create
test double objects for use in unit tests. Though it may take time to select the best
framework and to learn how to code mock objects, your time investment will be
worth it over the life of the project.

Best Practice: Do not be tempted to skip unit tests when under time pressure.
Doing so can introduce bugs and errors into your system and result in more time
being spent debugging.

Common Issues and Troubleshooting Tips

Common Issue Troubleshooting Tip

No information appears in the IntelliTrace window.

Review Question(s)

Question: You want to ensure that the PhotoController object passes a single
Photo object to the Display view, when a user calls the Search action for an
existing photo title. What unit tests should you create to check this functionality?

Tools
NinJect, StructureMap. These are Inversion of Control (IoC) containers, also
known as Dependency Injection (DI) frameworks. They create non-test
implementations of interfaces in your web application.

Moq, RhinoMocks, NSubstitute. These are mocking frameworks. They automate


the creation of test doubles for unit tests.

IntelliTrace. This is a part of Visual Studio that displays application state at the
point of an exception or break, and at earlier times.

Health Monitoring. This part of ASP.NET can store health events in a database,
log, or other locations for later analysis.

ELMAH. This exception logging tool can store exceptions in database tables,
XML files, and elsewhere, and enable administrators to view exception details on
a webpage.

 Module 07:
Aspecto destacadoNotaExpandir aspecto destacadoExpandir nota

Structuring ASP.NET MVC 4 Web Applications


Contents:
Module Overview

Lesson Analyzing Information Architecture


1:

Lesson Configuring Routes


2:
Lesson Creating a Navigation Structure
3:

Lab: Structuring ASP.NET MVC 4 Web Applications

Module Review and Takeaways

Module Overview
An MVC web application can grow large and complex and the application can
contain many types of information that relate to each other in complicated ways.
A key challenge for such web applications is to ensure that users can easily locate
the information that interests them. Although a search tool is helpful, you should
design your web application in such a way that users can navigate to the page
they need through a short sequence of links. At each level, users must know what
link to click next. The URLs that users see in the Address bar must be readable
and understandable. You need to understand how to present the model classes
you have designed in a way that is logical to the user. You also need to ensure
that Internet search engines can crawl and analyze your web application
structure, so that your application content appears close to the top of the search
engine results. You can achieve these goals by learning about ASP.NET routing
and navigation.

Objectives

After completing this module, you will be able to:

Plan suitable information architecture for a given set of functional


o
requirements.
Add routes to the ASP.NET routing engine and ensure that URLs are user-
o
friendly throughout an MVC web application.
o Add navigation controls to an application to enable users to locate data rapidly.

Lesson 1 : Analyzing Information Architecture


When you analyze use cases and user stories to plan a model for your web
application, you must determine the kinds of objects that your web application
will manage. For example, if your web application provides technical
documentation for a product, you can plan model classes such as installation
guides, user guides, frequently asked questions (FAQs), FAQ answers,
categories, comments, and other model classes. The model imposes a logical
structure of objects on the web application. However, you must also consider
how users expect information to be structured. Users may expect a hierarchical
structure, in which FAQs, FAQ answers, and comments are presented under the
product they relate to. When you create a complex MVC web application, you
need to know how to present model classes in a logical manner, so that your web
application is user-friendly.

Lesson Objectives
After completing this lesson, you will be able to:

o Describe information architecture.


o Describe search engine optimization and its importance for web developers.

What Is Information Architecture?


When the information your web application manages is complex and multi-
faceted, it is easy to present objects in a confusing way. Unless you think
carefully about the way users expect information to be structured and how they
expect to navigate to useful content, you may unintentionally create an unusable
web application. During development, when you work with a limited amount of
data, this confusion may not become apparent. Then, when real-world data is
added to your database at production deployment time, it becomes clear that the
web

application is confusing. You can avoid this eventuality by planning the


information architecture.

Information architecture is a logical structure for the objects your web


application manages. You should design such architecture in a way that users can
find content quickly without understanding any technical aspects of your web
application. For example, users should be able to locate a technical answer about
their product without understanding the database structure or the classes that
constitute the model.

Example Scenario: A Technical Documentation Website

To understand the need for information architecture, consider a web application


that presents technical information about a company’s products for customers
and engineers. In this example, the company manufactures domestic heating
furnaces, which are installed in homes by qualified heating engineers. The web
application is intended to enable customers to locate instructions, hints, and tips.
This web application is also intended to enable engineers to obtain the technical
documentation on installing and servicing furnaces.

The development team has identified the following simple user stories:

Customers have a certain problem with their boilers. They want to find a
specific FAQ answer that solves the problem. They know the boiler product
o name and the fuel, but not the product number. They visit the web application
and navigate to the boiler name. They click the FAQ for their boiler name and
locate the answer that they need.
Engineers need the latest installation manual for a boiler. They know the boiler
product number, product name, and fuel type. They visit the site and navigate
o
to the boiler name. They click the Manuals link and locate the installation
manual.
Engineers have web applications, which they want to link to a specific boiler
o name. You want to ensure that the URL is simple and readable for customers
and engineers.

You have already planned the following model classes:

Furnace. Each furnace object is a product manufactured and sold by the


o
company.
Category. Categories organize the furnaces by type. For example, you can have
o
categories such as oil-fired, gas-fired, and solid fuel.
FAQ. Each FAQ relates to a single furnace. Each furnace can have many
o
questions. The class includes both Question and Answer properties.
Installation Manual. Each furnace has a single installation manual in the form
o
of a PDF document.
User Manual. Each furnace has a single user manual in the form of a PDF
o
document.

Planning a Logical Hierarchy


You can see from the user stories that FAQ and manuals are both accessed by
navigating to the relevant product first. You can also see that the company has
different products, and both customers and engineers know the fuel type for a
particular furnace. Therefore, you can organize furnaces in categories by fuel
type. The following list shows a logical hierarchy of objects, which helps both
the customers and engineers find the information they need by clicking through
each level:

Category

▪ Furnace
o ▪ FAQ

▪ User Manual
▪ Installation Manual

Presenting a Hierarchy in Navigation Controls

The information architecture you design should be presented on webpages in the


form of navigation controls. Common approaches to such controls include:

Site Menus. Most websites have a main menu that presents the main areas of
content. For simple web applications, the main menu may include a small
o
number of static links. For larger web applications, when users click a site
menu link, a submenu appears.
Tree Views. A tree view is a menu that shows several levels of information
hierarchy. Usually, users can expand or collapse objects at each level, to locate
o
the content they require. Tree views are useful for presenting complex
hierarchies in navigable structures.
Breadcrumb Trails. A breadcrumb trail is a navigation control that shows the
user where they are in the web application. Usually a breadcrumb trail shows
o the current pages and all the parent pages in the hierarchy, with the home page
as the top level. Breadcrumb trails enable you to understand how a page fits in
with the information architecture shown in menus and tree views.
The types of navigation controls you build in your web application depend on
how you expect users to find information.

Presenting a Hierarchy in URLs

You can increase the usability of your web application by reflecting the
information architecture in the URLs, which the users see in the Address bar of
the web browser. In many web applications, URLs often include long and
inscrutable information such as Globally Unique Identifiers (GUIDs) and long
query strings with many parameters. Such URLs prevent users from manually
formulating the address to an item, and these URLs are difficult to link to a page
on your web application. Instead, URLs can be plain and comprehensible, to help
users browse through your content.

In MVC web applications, the default configuration is simple, but it is based on


controllers, actions, and parameters. The following are some example URLs that
follow this default pattern:

http://site/Furnace/Details/23: This URL links to the Furnace controller and


o
the Details action, and it displays the furnace with the ID 23.
http://site/FAQQuestion/Details/234: This URL links to the FAQQuestion
o
controller and the Details action, and it displays the FAQ with the ID 234.
http://site/InstallationManual/Details/3654: This URL links to the
o InstallationManual controller and the Details action, and it displays the manual
with the ID 3654.

As you can see, the web application user is required to understand how
controllers, actions, and action parameters work, to formulate URLs themselves.
Instead, users can use URLs that are easier to understand, such as the following,
because they reflect the information hierarchy:

http://site/OilFired/HotBurner2000: This URL links to a Furnace by specifying


o the fuel category and the product name. Customers and engineers can
understand these values.
http://site/OilFired/HotBurner2000/HowToRestartMyFurnace: This URL links
o
to an FAQ by specifying the furnace name the question relates to.
http://site/OilFired/HotBurner2000/: This URL links to the Installation Manual
o
by specifying the furnace name the manual relates to.

As you can see, these URLs are easy for customers and engineers to understand,
because the URLs are based on a logical hierarchy and the information that the
users already have. You can control the URLs that your ASP.NET web
application uses, by configuring the ASP.NET routing engine.

Question: Why may it be difficult for users to understand URLs based on


controllers, actions, and parameters?

What Is Search Engine Optimization?

Most users find web applications by using search engines. Users tend to visit the
links that appear at the top of search engine results more frequently than those
lower down and those on the second page of results. For this reason, website
administrators and developers try to ensure their web application appears high in
search engine results, by using a process known as Search Engine Optimization
(SEO). SEO ensures that more people visit your web application.

Search engines examine the content of your web application, by crawling it with
a program called a
web bot. If you understand the priorities that web bots and search engine indexes
use to order search results, you can create a web application that conforms to
those priorities and thereby appears high in search engine results.

SEO Best Practices

Various search engines have different web bots with different algorithms to
prioritize results. The complete details of these algorithms are not usually
published. However, if you adopt the following best practices, your site has a
good chance of appearing high in search results:

Ensure that each webpage in your web application has a meaningful <title>
o
element in the <head> section of the HTML.
Ensure that you include a <meta name="keywords"> tag in the <head> element
o of each page. The content attribute of this element should include keywords
that describe the content of the page accurately.
Ensure that you include a <meta name="description"> tag in the <head>
o element of each page. The content attribute of this element should include a
sentence that describes the content of the page accurately.
Ensure that the <title> element and the <meta> elements are different for each
o
page in your web application.
Choose a domain name that includes one or more of your most important
o
keywords.
Ensure that keywords appear in the <h1>, <h2>, or <h3> elements of your
o
webpage.
Ensure that navigation controls enable web bots to crawl your entire web
application. For example, you may have content in your site that users can only
o
find with the search tool, not by clicking through links. As web bots cannot use
search tools, this content will not be indexed.
o Ensure that URLs do not include GUIDs or long query text.

SEO and Web Application Structure


Information architecture is a subject that is closely related to SEO. This is
because both information architecture and SEO are relevant to the structure,
hierarchy, and accessibility of the objects in your web application. Users click
links on menus to navigate to the pages that interest them. Web bots use the same
links to navigate the web application and crawl its content. Users prefer URLs
without GUIDs and long query text because they are meaningful. Web bots often
ignore links with GUIDs and long query text in them. In addition, when
keywords appear in URLs, web bots prioritize a webpage in search results.

As an ASP.NET MVC developer, you must understand SEO principles and use
them whenever you write code, to ensure that you do not damage the search
engine positioning of your web application. Views are critical to SEO because
they render <meta> tags, and <title> elements. Routes and the configuration of
the routing engine are also critical, because, by using routes, you can control the
URLs that your web application generates.

Question: A developer creates a partial view that contains <meta> tags and
<title> tags. The developer uses this partial view on every page in the web
application. Do these actions conform to SEO best practices?

Lesson 2: Configuring Routes


ASP.NET enables developers to control the URLs that a web application uses, to
link the URLs and the content by configuring routes. A route is an object that
parses a requested URL, and it determines the controller and action to which the
request must be forwarded. Such routes are called incoming routes. HTML
helpers also use routes when they formulate links to controllers and actions. Such
routes are called outgoing routes. You need to know how to write code that adds
a new route to your application. You also need to know how the routing engine
interprets a route so that requests go to the appropriate controllers, and users see
meaningful URLs.

Lesson Objectives
After completing this module, you will be able to:

o Describe the features of the ASP.NET routing engine.


o Describe the benefits of adding routes to an ASP.NET MVC web application.
o Explain how to add and configure routes.
o Explain how to use routes to pass parameters.
o Add routes to manage URL formulation.

The ASP.NET Routing Engine

Routing governs the way URLs are formulated and how they correspond to
controllers and actions.

Routing does not operate on the protocol, server, domain, or port number of a
URL, but only on the directories and file name in the relative URL. For example,
in the URL, http://www.advworks.com/photo/display/1, routing operates on the
relative path /photo/display/1.

In ASP.NET, routes are used for two purposes:

To parse the URLs requested by browsers.

o This analysis ensures that requests are

forwarded to the right controllers and actions. These are called incoming URLs.
To formulate URLs in webpage links and other elements. When you use
helpers such as Html.ActionLink() and Url.Action() in MVC views, the
o
helpers construct URLs according to the routes in the routing table. These are
called outgoing URLs.

When you create an MVC web application in Visual Studio by using a project
template, the application has a default route. You must understand this default
route before you consider adding extra routes to manipulate URLs in the
application.

Note: You can use routes and the routing engine to govern relative URLs in any
ASP.NET 4.5 application and not just in those that use the MVC programming
model.

The Default Route

The default route is simple but logical and works well in many web applications.
The default route examines the first three segments of the URL. Each segment is
delimited by a forward slash:

The first segment is interpreted as the name of the controller. The routing
o engine forwards the request to this controller. If a first segment is not specified,
the default route forwards the request to a controller called Home.
The second segment is interpreted as the name of the action. The routing engine
o forwards the request to this action. If a second segment is not specified, the
default route forwards the request to a controller called Index.
The third segment is interpreted as an ID value, which is passed to the action as
o a parameter. The parameter is optional, so if a third segment is not specified, no
default value is passed to the action.

You can see that when the user requests the URL,
http://www.advworks.com/photo/display/1, the default route passes the ID
parameter 1 to the Display action of the Photo controller.
The following code shows how the default route is implemented in new
ASP.NET MVC 4 applications.

The Default Route

routes.MapRoute(

name: "Default",

url: "{controller}/{action}/{id}",

defaults: new {

controller = "Home",

action = "Index",

id = UrlParameter.Optional

);

Custom Routes

Developers add their own custom routes to a web application for two main
reasons:

To make URLs easier for site visitors to understand. A URL such as


http://www.advworks.com/photo/display/1 is logical to the visitor, but it
requires some knowledge to formulate such URLs. In this case, to type the right
URL in the Address bar of the web browser, the user must know some
o
information. This information includes the controller name, Photo, the action
name, Display, and the ID of the photo of interest. If you use Globally Unique
Identifiers (GUIDs) in the database, the ID segment of the URL can be long
and difficult to remember. Ideally, you should consider what users know and
create routes that accept that information. In this example, users may know the
title of a photo that they had seen earlier in your application. You should create
a route that can interpret a URL such as
http://www.advworks.com/photo/title/My%20Photo%20Title, and forward the
URL to an appropriate action to display the right photo. Although users usually
click links to make requests, friendly URLs like these make a site easier to use
and link to from other sites.
To improve search engine rankings. Search engines do not prioritize webpages
that have GUIDs or long query text in the URL. Some web bots do not even
o crawl such links. In addition, some search engines boost a page’s ranking when
one or more of its keywords appear in the URL. User-friendly URLs are
therefore a critical tool in SEO.

Controller Factories and Routes

MVC uses controller factories that help create an instance of a controller class to
handle a request. MVC uses action invokers to call the right action and pass
parameters to that action method. Both controller factories and action invokers
refer to the routing table to complete their tasks. The following are steps that
MVC conducts when a request is received from a web browser:

An MvcHandler object creates a controller factory. The controller factory is


1.
the object that instantiates a controller to respond to the request.
The controller factory consults the routing table to determine the right
2.
Controller class to use.
The controller factory creates a Controller object, and the MvcHandler calls
3.
the Execute method in that controller.
The ControllerActionInvoker examines the request URL and consults the
4.
routing table to determine the action in the Controller object to call.
The ControllerActionInvoker uses a model binder to determine the values
5. that should be passed to the action as parameters. The model binder consults
the routing table to determine if any segments of the URL should be passed as
parameters. The model binder can also pass parameters from a posted form,
from the URL query text, or from uploaded files.
The ControllerActionInvoker runs the action. Often, the action creates a new
instance of a model class, perhaps by querying the database with the
6.
parameters that the invoker passed to it. This model object is passed to a view,
to display results to the user.

As you can see, you can use routes to manage the behavior of controller factories,
action invokers, and model binders, because all these objects refer to the routing
table. MVC is highly extensible; therefore, developers can create custom
implementations of controller factories, action invokers, and model binders.
However, by using routes, you can usually implement the URL functionality that
you need with the default implementations of these classes. You should ensure
that routes cannot implement your required functionality before you plan to
customize controller factories, action invokers, or model binders.

Question: A user wants to edit a comment that the user created in your MVC
application. You have not created any custom routes. What URL do you think the
user must request, to see the edit view with the right comment?

Adding and Configuring Routes

Every MVC web application has a RouteTable object in which routes are stored,
in the Routes properties. You can add routes to the Routes property by calling
the MapRoute() method.
In the Visual Studio project templates for MVC 4, a dedicated RouteConfig.cs
code file exists in the App_Start folder. This file includes the
RouteConfig.RegisterRoutes() static method where the default route is added to
the RouteTable object. You can add custom routes in this method. The
Global.asax.cs file includes a call to RouteConfig.RegisterRoutes() in the

Application_Start() method, which means that routes are added to the routing
table whenever the MVC application starts.

Properties of a Route

Before you can add a route, you must understand the properties of a route. This is
to ensure that these properties match the URL segments correctly and pass
requests and parameters to the right location. The properties of a route include
the following:

Name. This string property assigns a name to a route. It is not involved in


o
matching or request forwarding.
URL. This string property is a URL pattern that is compared to a request, to
determine if the route should be used. You can use segment variables to match
a part of the URL. You can specify a segment variable by using braces. For
o
example, if you specify the URL, “photo/{title}”, the route matches any request
where the relative URL starts with the string, “photo/”, and includes one more
segment. The segment variable is “title” and can be used elsewhere in the route.
Constraints. Sometimes you must place extra constraints on the route to ensure
that it matches only with the appropriate requests. For example, if you want
relative URLs in the form, “photo/34”, to specify a photo with the ID “34”, you
must use a URL property like “photo/{id}”. However, observe that this URL
pattern also matches the relative URL, “photo/create”, because it has one extra
o
segment. For IDs, you must constrain the URL to match only segments
comprising digits. You can do this by adding a constraint to the route. The
Constraints property enables you to specify a regular expression for each
segment variable. The route will match a request only if all the segment
variables match the regular expressions that you specify.
Defaults. This string property can assign default values to the segment variables
o in the URL pattern. Default values are used for segment variables when the
request does not specify them.

The Default Route Code

The default route specifies the Name, URL, and Defaults properties to obtain
controller and action names, and ID values, from the requested relative URL. By
examining these properties, you can understand how to construct your own
routes.

The following code shows the default route in the Visual Studio MVC project
templates.

The Default Route in RouteConfig.cs

routes.MapRoute(

name: "Default",

url: "{controller}/{action}/{id}",

defaults: new { controller = "Home", action = "Index", id =

UrlParameter.Optional }

);

Observe that the URL pattern specifies three segments: {controller}, {action},
and {id}. This means that a relative URL in the form, “photo/display/23”, will be
sent to the Display action of the PhotoController class. The third segment will
be passed as a parameter to the action method. Therefore, if the Display action
accepts a parameter named id, the value, 23, will be passed by MVC.

In the defaults property, the {id} segment is marked as optional. This means that
the route still matches a relative URL, even if no third segment is specified. For
example, the route matches the relative URL, “photo/create”, and passes the URL
to the Create action of the PhotoController class.

The defaults property specifies a default value of “Index” for the {action}
segment. This means that the route still matches a relative URL, even if no
second segment is specified. For example, the route matches the relative URL,
“photo”, and passes the URL to the Index action of the PhotoController class.

Finally, the defaults property specifies a default value of “Home” for the
{controller} segment. This means that the route still matches a relative URL,
even if no segments are specified, that is, if there is no relative URL. For
example, the absolute URL, “http://www.advworks.com”, matches this route, and
the URL is passed to the Index action of the HomeController class.

As you can see, with the default route in place, developers build the web
application’s home page by creating a controller named, HomeController, with
an action named, Index. This action usually returns a view called, Index, from
the Views/Home folder.

Creating Custom Routes

You can add custom routes by calling the routes.MapHttpRoute() method, just
like the default route.

In the following code example, a constraint is used to ensure that only digits
match the {id} segment variable.

A Custom Route

routes.MapRoute(

name: "PhotoRoute",

url: "photo/{id}",

defaults: new { controller = "Photo", action = "Details" },


constraints: new { id = "[0-9]+" }

);

Observe that the URL pattern in the route matches any relative URL that starts
with “photo/” and has one or more segments. However, in the constraints
property, the route specifies a regular expression for the {id} segment variable.
This regular expression matches only if the segment is composed of digits that
range from 1 through 9. If the user requests the relative URL, “photo/234”, then
this route matches, and the routing engine forwards the request to the Details
action of the PhotoController class. If the user requests the relative URL,
“photo/create”, then this route does not match and a subsequent route must be
used to forward the request.

Precedence of Routes

Routes are evaluated by the routing engine in the order with which they are
added to the RouteTable.Routes collection. If a route matches, the routing
engine uses it and does not evaluate any later route in the collection. If a route
does not match, the routing engine ignores it and evaluates the next route in the
collection. For this reason, you must add routes to the RouteTable.Routes
collection in the appropriate order. You can add the most specific routes first,
such as routes that have no segment variables and no default values. Routes with
constraints should be added before routes without constraints.

The route named "Default" matches any request, including those with no relative
URL. This default route should be the last that you add to the
RouteTable.Routes collection. If the routing engine evaluates this route, the
route is always used. Any routes added after the “Default” route are never used.

Question: A developer has removed all code from the Application_Start()


method in Global.asax.cs. When the developer runs the application, he or she
receives 404 errors for any request, regardless of the relative URL. Why does this
occur?
Using Routes to Pass Parameters

The routing engine separates the relative URL in a request into one or more
segments. Each forward slash delimits one segment from the next. If you want
one of the segments to specify the controller name, you can use the {controller}
segment variable. The controller factory always interprets this variable as the
controller to instantiate.

Alternatively, to fix a route to a single controller, you can specify a value for the
controller variable in the defaults property. In a similar manner, if you want one
of the segments to specify the action method, you can use the {action} segment

variable. The action invoker always interprets this variable as the action to call.
Alternatively, to fix a route to a single action, you can specify a value for the
action variable in the defaults property.

Segment variables or default values with other names have no special meaning to
MVC and are passed to actions. You can access the values of these variables by
using one of two methods: the RouteData.Values collection or by using model
binding to pass values to action parameters.

The RouteData.Values Collection

In the action method, you can access the values of any segment variable by using
the RouteData.Values collection. Consider the following example:
In RouteConfig.cs, you have defined a route with the URL pattern
o
“{controller}/{action}/{title}”.
o The user requests the relative URL, “photo/edit/my%20photo”.

The RouteData.Values collection contains the following values, which you can
use in the action method:

o RouteData.Value["controller"]: This value has the value, “photo”.


o RouteData.Value["action"]: This value has the value, “edit”.
o RouteData.Value["title"]: This value has the value, “my%20photo”.

Using Model Binding to Obtain Parameters

Consider the following action method.

public void ActionMethod Display (int PhotoID)

return View(PhotoID);

The default MVC action invoker is a class named, ControllerActionInvoker.


This invoker uses a class named, DefaultModelBinder, to pass the appropriate
parameters to actions. This model binder uses the following logic to pass
parameters:

The binder examines the definition of the action to which it must pass
1. parameters. In the example, the binder determines that the action requires an
integer parameter called, PhotoID.
The binder searches for values in the request, which can be passed as
2.
parameters by name. In the example, the binder searches for integers because
the action requires integers. The binder searches for values in the following
locations in sequential order:

Form Values. If the user fills out a form and clicks the Submit button, the
a.
binder can find parameters in the Request.Form collection.
Route Values. If the matched route includes the segment variable {photoid},
b. the binder can find the value for the PhotoID parameter in the
RouteData.Values collection. This match is case-insensitive.
Query Strings. If the user request includes named parameters after a
c. question mark, the binder can find these parameters in the
Request.QueryString collection.
Files: If the user request includes uploaded files, these files can be used as
d. parameters in an action. File parameters in actions must use the
HttpPostedFileBase type.

Therefore, you can use the default model binder to pass parameters to action
strings. If the name of an action method parameter matches the name of a route
segment variable, the model binder passes the parameter automatically.

Optional Parameters

Sometimes, you want requests to match a route, regardless of whether parameter


values are supplied. For example, you might want to enable users to specify a
color for a product.

In the following example, the route added includes an optional color parameter.

A Route with an Optional Parameter

routes.MapRoute(

name: "ProductRoute",

url: "product/{id}/{color}",
defaults: new { color = UrlParameter.Optional }

);

The default values specify that {color} is optional. If the relative URL has three
segments, the route matches, and the third segment is passed to the
RouteData.Values["color"] value. If the relative URL has only two segments,
the route matches, because the {color} is optional. In this case, the
RouteData.Values["color"] value does not exist. If the relative URL has only
one segment, the route does not match.

Question: A developer has replaced the default model binder with a custom
model binder. Now, several action methods are throwing exceptions on lines that
use action parameters. How can you fix this bug?

Demonstration: How to Add Routes


In this demonstration, you will see how to create URLs by adding routes to the
MVC web application. You will also see how to enable visitors to the Operas
web application to browse the operas by title.

Demonstration Steps
On the DEBUG menu of the OperasWebSite - Microsoft Visual Studio
1.
window, click Start Debugging.
2. On the Operas I Have Seen page, click the operas I’ve seen link.
3. On the Index page, click the Details link corresponding to Cosi Fan Tutte.
In the Address bar of the Windows Internet Explorer window, note that the
URL is http://localhost:<portnumber>/Opera/Details/1.
4.
Note: This URL indicates that the controller is Opera, the action is Details,
and the ID is 1.
5. In the Windows Internet Explorer window, click the Close button.
In the Solution Explorer pane, expand OperasWebSite, expand Controllers,
6.
and then click OperaController.cs.
In the OperaController.cs code window, place the mouse cursor at the end of
the Details action code block, press Enter twice, and then type the following
code.

7. public ActionResult DetailsByTitle(string title)

In the DetailsByTitle action code block, type the following code, and then
press Enter.

Opera opera = (Opera)(from o in contextDB.Operas

8.
where o.Title == title

select o).FirstOrDefault();
In the DetailsByTitle action code block, after the code that you just entered,
type the following code.

if (opera == null)

{
9.
return HttpNotFound();

return View("Details", opera);

In the Solution Explorer pane, under OperasWebSite, expand App_Start, and


10.
then click RouteConfig.cs.
In the RouteConfig.cs code window, locate the following code.
11.
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

Place the mouse cursor at the end of the call to the IgnoreRoute() method,
press Enter twice, and then type the following code.

routes.MapRoute(

name: "OperaTitleRoute",
12.
url: "opera/title/{title}",

defaults: new { controller = "Opera", action = "DetailsByTitle" }

);

On the FILE menu of the OperasWebSite - Microsoft Visual Studio


13.
window, click Save All.
On the DEBUG menu of OperasWebSite - Microsoft Visual Studio
14.
window, click Start Debugging.
15. On the Operas I Have Seen page, click the operas I’ve seen link.
In the Address bar of the Windows Internet Explorer window, append the
16. existing URL with /title/rigoletto, and then click the Go button.
Note: The details of the Rigoletto opera are displayed.
17. In the Windows Internet Explorer window, click the Close button.
In the OperasWebSite - Microsoft Visual Studio window, click the Close
18.
button.

Unit Tests and Routes


Unit tests are small, isolated methods that check a specific aspect of your code.
As your project grows in complexity, you can rerun all unit tests to ensure that
the verified functionality remains in a working state. If your team uses Test
Driven Development (TDD), you can define tests to specify a functional
requirement and then write code that passes your test. Such approaches
significantly increase the quality of your code, by highlighting bugs as soon as
they arise.

You can use unit tests to ensure that routes in your MVC web application behave
as designed. If

you do such tests, you can prevent many 404 HTTP errors and internal server
errors from reaching web application users. Users generally have a low tolerance
for such errors, and if errors arise too often, they will browse to the websites of
your competitors.

Creating a HTTP Context Test Double

In a webpage request, ASP.NET stores details of the request in an HTTP Context


object. These details include the URL that was requested, details of the browser,
and other information. To write a unit test for routes, you must simulate the
HTTP Context object by creating a test double class.

The following code shows how to create a fake HTTP context object to use as a
test double.
An HTTP Context Test Double

public class FakeHttpContextForRouting : HttpContextBase

FakeHttpRequestForRouting _request;

FakeHttpResponseForRouting _response;

//The constructor enables you to specify a request URL and an

Application path in

the test

public FakeHttpContextForRouting(string appPath = "/", string

requestUrl = "~/")

//Create new fake request and response objects

_request = new FakeHttpRequestForRouting(appPath,

requestUrl);

_response = new FakeHttpResponseForRouting();

//This property returns the fake request

public override HttpRequestBase Request

get { return _request; }


}

//This property returns the fake response

public override HttpResponseBase Response

get { return _response; }

//This is the fake request class

public class FakeHttpRequestForRouting : HttpRequestBase

string _appPath;

string _requestUrl;

public FakeHttpRequestForRouting(string appPath, string

requestUrl)

_appPath = appPath;

_requestUrl = requestUrl;

public override string ApplicationPath


{

get { return _appPath; }

public override string AppRelativeCurrentExecutionFilePath

get { return _requestUrl; }

public override string PathInfo

get { return ""; }

public override NameValueCollection ServerVariables

get { return new NameValueCollection(); }

//This is the fake response class

public class FakeHttpResponseForRouting : HttpResponseBase

{
public override string ApplyAppPathModifier(string virtualPath)

return virtualPath;

Writing Routing Tests

After creating an HTTP context test double, you can write unit tests for each
route in the routing table. These unit tests adopt the following general phases:

Arrange. In the Arrange phase of the test, you can create a new HTTP context
from your test double class. You can set the request URL for this object to be
o
the URL you want to test. You can then create a new route collection and call
the RouteConfig.RegisterRoutes() method in your web application.
Act. In the Act phase, you can test the routes by calling the GetRouteData()
o method of the route collection. You can then pass the fake HTTP context to this
method.
Assert. In the Assert phase, you can use the RouteData.Values collection to
o
check that the controller, action and other values are assigned correctly.

In the following example unit test, the default route is checked. The request URL
has only a single segment and the test asserts that this segment is passed as the
controller name.

A Routing Unit Test

[TestMethod]

public void Test_Default_Route_ControllerOnly()

{
//This test checks the default route when only the controller is

specified

//Arrange

var context = new FakeHttpContextForRouting(requestUrl:

"~/ControllerName");

var routes = new RouteCollection();

MyMVCApplication.RouteConfig.RegisterRoutes(routes);

// Act

RouteData routeData = routes.GetRouteData(context);

// Assert

Assert.AreEqual("ControllerName", routeData.Values["controller"]);

Assert.AreEqual("Index", routeData.Values["action"]);

Assert.AreEqual(UrlParameter.Optional, routeData.Values["id"]);

Question: You are writing a unit test to check your web application’s routing
table. You want to ensure that the request is passed to an action method called,
“Edit”. What line of code would you use in the Assert phase of the test to check
this fact?

Lesson 3: Creating a Navigation Structure


A navigation structure is a logical hierarchy of webpages, which enables users to
browse to the information that interests them. In simple web applications, the
design of the navigation structure is also usually simple. As your web application
grows, it becomes difficult to present menus and navigation controls that show
the users clearly what their next click should be, at every step. You need to
understand how to build menus, which help users understand where they are in
your site and where to go next. You can do this by building menus and
breadcrumb controls.

Lesson Objectives
After completing this lesson, you will be able to:

o Describe the importance of well-designed navigation.


o Build clear menus in a web application.
o Add breadcrumb controls to a web application.
o Build site navigation in a web application.

The Importance of Well-Designed Navigation

The information architecture you design for your web application is a logical
hierarchy of objects.

This hierarchy should be clear and understandable to the audience of your web
application. If your web application is designed for people with specialist
knowledge, you can implement information architecture that requires specialist
knowledge. For example, in an engineering web application, you could base your
information architecture on specialist technologies and solutions that engineers
understand. However, such information architecture would not be
helpful to the general public.

After designing the information architecture, you must present it in your web
application. You can add routes to ensure that URLs reflect your information
architecture. Similarly, you must add navigation controls to present the
information architecture in the body of each webpage. The navigation controls
you build are the primary means by which users browse your web application
and locate content. You should ensure two things with these navigation controls:

An obvious next step. You should ensure that users can easily decide what link
to click, on each page. To achieve this aim, you can consider use cases. For
each use case, you can list what the user knows when they arrive at your web
o
application. The user should be able to choose the right link without any
specialist or technical knowledge. For example, avoid basing your links on any
kind of technical jargon, unless you know that your audience understands it.
A clear context. In a simple web application with only one or two levels in the
information architecture, users can easily keep track of where they are. In larger
web applications with many levels, you must provide navigation controls,
which show users where they are and how to navigate back up the hierarchy.
Tree views and breadcrumb controls perform this function well.
o
Best Practice: Base your navigation controls on the information hierarchy,
rather than on the model and model classes, database tables, or other technical
structures in your web application. Users will probably not understand the
model classes, controllers, views, and data storage mechanisms that underlie
your web application.

Common Types of Navigation Controls

Remember that most web application visitors have browsed thousands of Internet
applications before they visit your home page. Visitors are usually familiar with
common types of menus used on many web applications, and you can make use
of this knowledge by using the same types of menus in your web application.
Common menu types include the following:
Top menus. Often placed at the top of the page or immediately beneath the
application branding, top menus link to the main areas of your web application.
o
In some applications, each item in the top menu has a submenu with links to
lower level items and pages.
Tree views. A tree view is a hierarchical menu that can display many items in
multiple levels in your web application. By default, a tree view often displays
only one or two levels of the information architecture. Users can expand lower
o
levels to find the content they need. Tree views enable users to explore multiple
levels on a single page. Tree views can also show clearly the position of the
current page, in the hierarchy.
Breadcrumb trails. Often presented as a horizontal sequence of links across the
top of a webpage, a breadcrumb trail shows the current page and its parents in
o all the higher levels of the hierarchy. Breadcrumb trails show the current
position of the user, in the context of the web application and enable users to
navigate to higher, less specific pages.
Footer menus. The page footer is often not visible when a user arrives on a
page. The user must scroll to the end of the page to see the footer. The footer is
o often used as a location for important, but not business-critical, links. For
example, links to copyright and other legal information, links to parent
companies, and links to site maps are often placed in the footer menu.

The MVC Site Map Provider

In ASP.NET, one way to rapidly build information architecture and navigation


controls to present that architecture is to use a site map provider. A site map
provider is an ASP.NET component that stores the logical hierarchy of your web
application. Navigation controls such as top menus, tree views, and breadcrumb
trails can take their links from this single hierarchy.

The MVC Site Map Provider is a provider designed to work with MVC
controllers and actions. It presents the information architecture that you can
configure in a simple XML file. This hierarchy is completely independent of the
model, controllers, and actions in your applications, although you can build links
to them. The provider also includes HTML helpers, which you can use in views
to render menus, tree views, and breadcrumb trails.

Note: The MVC Site Map Provider is a component by Maarten Balliauw that is
not included in MVC web applications, by default. You can find it in the NuGet
package manager by searching for “MvcSiteMapProvider”.

Question: Analysis of web logs has shown that visitors to your web application
can navigate to low-level pages in your information architecture, quickly and
easily. However, they subsequently find other pages by returning to the home
page and navigating the entire hierarchy again from the top, or else they use the
search tool. How can you enable users to navigate to higher levels without
starting from the home page again?

Configuring the MVC Site Map Provider

After installing the MVC Site Map Provider from the NuGet package manager,
you must configure the provider and set up the logical hierarchy it should
present, before you can render any menus.

Configuring the MVC Site Map Provider in Web.Config

You should configure the MVC Site Map Provider, by adding elements to the
Web.config file in the root folder of your MVC web application. When you
install the site map provider, the NuGet

package adds a <siteMap> element to the <system.web> section of this file.


The following code example shows how to configure the site map provider.

The <siteMap> Element in Web.config

<siteMap defaultProvider="MvcSiteMapProvider" enabled="true">

<providers>

<clear />

<add name="MvcSiteMapProvider"

type="MvcSiteMapProvider.DefaultSiteMapProvider,

MvcSiteMapProvider"

siteMapFile="~/Mvc.Sitemap"

securityTrimmingEnabled="false"

cacheDuration="5"

enableLocalization="false"

scanAssembliesForSiteMapNodes="false"

includeAssembliesForScan=""

excludeAssembliesForScan=""

attributesToIgnore=""

nodeKeyGenerator="MvcSiteMapProvider.DefaultNodeKeyGenerator,

MvcSiteMapProvider"
controllerTypeResolver="MvcSiteMapProvider.DefaultControllerTypeResolver,

MvcSiteMapProvider"

actionMethodParameterResolver="MvcSiteMapProvider.DefaultActionMethodPara

meterResolver,

MvcSiteMapProvider"

aclModule="MvcSiteMapProvider.DefaultAclModule,

MvcSiteMapProvider"

siteMapNodeUrlResolver="MvcSiteMapProvider.DefaultSiteMapNodeUrlResolver,

MvcSiteMapProvider"

siteMapNodeVisibilityProvider="MvcSiteMapProvider.DefaultSiteMapNodeVisib

ilityProvider,

MvcSiteMapProvider"

siteMapProviderEventHandler="MvcSiteMapProvider.DefaultSiteMapProviderEve

ntHandler,

MvcSiteMapProvider"

/>
</providers>

</siteMap>

Note that you can configure the name of the XML file where the site map is
stored, enable security trimming, and configure caching.

Additional Reading: For complete details of the configuration values you can
use with the MVC Site Map Provider, together with other documentation, go to
http://go.microsoft.com/fwlink/?LinkID=288963&clcid=0x409

Creating the Site Map File

The MVC Site Map Provider is the only site map provider that enables you to
specify a controller and action for every item in the site map. You do this by
completing a site map file. By default, the site map file is named Mvc.sitemap
and is stored in the highest level of your web application. The hierarchy consists
of nested <mvcSiteMapNode> elements. This is the hierarchy that the helpers
will display in navigation controls.

The following example shows simple information architecture as described in an


MVC site map provider site map file.

An MVC Site Map File

<?xml version="1.0" encoding="utf-8" ?>

<mvcSiteMap xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns="http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-3.0"

xsi:schemaLocation=

"http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-3.0

MvcSiteMapSchema.xsd"

enableLocalization="true">
<mvcSiteMapNode title="Home" controller="Home" action="Index">

<mvcSiteMapNode title="Products" controller="Product"

action="Index"

key="AllProducts">

<mvcSiteMapNode title="Bikes" controller="Category"

action="Display">

</mvcSiteMapNode>

</mvcSiteMapNode>

<mvcSiteMapNode title="Latest News" controller="Article"

action="DisplayLatest" >

<mvcSiteMapNode title="About Us" controller="Home" action="About"

/>

</mvcSiteMapNode>

</mvcSiteMap>

Question: You use the MVC Site Map Provider. Your boss notices that an
incorrect link appears in the highest menu and the tree view on every page in
your web application. Your boss asks you to fix every page in the web
application. What steps should you take?

Adding Menu Controls


After configuring the site map provider and creating a site map file, you can add
menus, tree views, and other navigation controls to your views.

The MVC site map provider includes some HTML helpers to make this easy.

The following example code shows how to render a main menu in an MVC view,
by using the HTML.MvcSiteMap() helper.

Rendering a Menu Control

@Html.MvcSiteMap().Menu(false, false,

true)

In this example, the first parameter specifies that the menu does not start from the
current node. The menu starts from the top-level node, which is usually the home
page of the web application. The second parameter specifies that the starting
node does not display as a child node at the same level as second-level nodes.
The third parameter specifies that the starting node displays in the menu.

You can also use the Html.MvcSiteMap() helper to render a breadcrumb


control, as displayed in the following code.

Rendering a Breadcrumb Trail

@Html.MvcSiteMap().SiteMapPath()
The Html.MvcSiteMap() helper also includes functions that you can use to
render node titles and complete site maps.

Additional Reading:

For complete reference documentation that details the Html.MvcSiteMap()


helper and its functions, go to
http://go.microsoft.com/fwlink/?LinkID=288964&clcid=0x409

Question: What are some of the benefits of using the Html.MvcSiteMap()


helper?

Demonstration: How to Build Site Navigation


In this demonstration, you will see how to create menus and breadcrumb trails by
using the MVC site map provider and its HTML helpers.

Demonstration Steps
On the PROJECT menu of the OperasWebSite - Microsoft Visual Studio
1.
window, click Manage NuGet Packages.
2. In the OperasWebSite - Manage NuGet Packages dialog box, click Online.
In the Search Online (Ctrl+E) box of the OperasWebSite - Manage NuGet
3. Packages dialog box, type mvcsitemapprovider, and then click the Search
button.
In the OperasWebSite - Manage NuGet Packages dialog box, click Install
4.
corresponding to MvcSiteMapProvider.
In the OperasWebSite - Manage NuGet Packages dialog box, ensure that
5.
the MvcSiteMapProvider package is installed, and then click Close.
In the Solution Explorer pane of the OperasWebSite - Microsoft Visual
6. Studio window, expand OperasWebSite, collapse App_Start, collapse
Controllers, and then collapse Views.
7. In the Solution Explorer pane, under Global.asax, click Mvc.sitemap.
In the Mvc.sitemap code window, locate the following code.
8.
<mvcSiteMapNode title="Home" controller="Home" action="Index">

Place the mouse cursor at the end of the located code, press Enter, and then
type the following code.

<mvcSiteMapNode title="All Operas" controller="Opera" action="Index"


9.
key="AllOperas"

/>

On the BUILD menu of the OperasWebSite - Microsoft Visual Studio


10.
window, click Build Solution.
In the Solution Explorer pane, expand Views, expand Home, and then click
11.
Index.cshtml.
In the Index.cshtml code window, place the mouse cursor after the <div> tag,
press Enter, and then type the following code.
12.

Menu: @Html.MvcSiteMap().Menu(false, false, true)


Place the mouse cursor at the end of the site map menu code block, press
Enter, and then type the following code.
13.

Breadcrumb Trail: @Html.MvcSiteMap().SiteMapPath()


In the Solution Explorer pane, under Views, expand Opera, and then click
14.
Index.cshtml.
In the Index.cshtml code window, place the mouse cursor at the end of the
<body> tag, press Enter, and then type the following code.
15.
Menu: @Html.MvcSiteMap().Menu(false, false, true)

Place the mouse cursor at the end of the site map menu code block, press
Enter, and then type the following code.
16.

Breadcrumb Trail: @Html.MvcSiteMap().SiteMapPath()


On the DEBUG menu of the OperasWebSite - Microsoft Visual Studio
17. window, click Start Debugging.
Note: On the Operas I Have Seen page, ensure that a menu is added.
18. On the Operas I Have Seen page, under Menu, click the All Operas link.
On the Index page, note that the Main Opera List is displayed.
19.
Note: On the Index page, you can also view the menu.
In the Breadcrumb Trail section of the Index page, click the Home link.
20.
Note: The Operas I Have Seen page is displayed.
On the Operas I Have Seen page, under Menu, click the About link.
21.
Note: The About page of the web application is displayed.
22. In the Windows Internet Explorer window, click the Close button.
In the OperasWebSite - Microsoft Visual Studio window, click the Close
23.
button.

Lab: Structuring ASP.NET MVC 4 Web


Applications
Scenario

An important design priority for the Photo Sharing application is that the visitors
should be able to easily and logically locate photographs. Additionally, photo
galleries and photos need to appear high in search engine results. To implement
these priorities, you have been asked to configure routes that enable the entry of
user-friendly URLs to access photos.

You have been asked to ensure that the URLs of the following forms work to
display a photo:

~/photo/display/PhotoId. In this form of URL, PhotoId is the database ID of the


o photo object. This form of URL already works because it matches the default
route.
~/photo/PhotoId. In this form of URL, PhotoId is the database ID of the photo
o object. This is the logical URL to enter when you know the ID of the photo that
you want to access.
~/photo/title/PhotoTitle. In this form of URL, PhotoTitle is the title of the photo
o object. This is the logical URL to enter when you know the title of the photo
that you want to access.

You have also been asked to implement the following navigation controls in the
Photo Sharing application:

o A menu with links to the main site areas


o A breadcrumb control

These navigation controls will be added to the menu after the completion of the
main site areas.

Objectives

After completing this lab, you will be able to:

o Add routes to the ASP.NET Routing Engine in an ASP.NET MVC application.


o Build navigation controls within ASP.NET views.

Lab Setup

Estimated Time: 40 minutes

Virtual Machine: 20486B-SEA-DEV11

Username: Admin

Password: Pa$$w0rd

Note: In Hyper-V Manager, start the MSL-TMG1 virtual machine if it is not


already running.
Before starting the lab, you need to enable the Allow NuGet to download
missing packages during build option, by performing the following steps:

o On the TOOLS menu of the Microsoft Visual Studio window, click Options.
o In the navigation pane of the Options dialog box, click Package Manager.
Under the Package Restore section, select the Allow NuGet to download
o
missing packages during build checkbox, and then click OK.

Exercise 1: Using the Routing Engine

Scenario

In this exercise, you will:

o Create unit tests for the routes you wish to create.


o Add routes to the application that satisfy your tests.
o Try out routes by typing URLs in the Internet Explorer Address bar.

This approach conforms to the principles of Test Driven Development (TDD).

The main tasks for this exercise are as follows:

1. Test the routing configuration.


2. Add and test the Photo ID route.
3. Add and test the Photo Title route.
4. Try out the new routes.

Task 1: Test the routing configuration.

Start the virtual machine, and log on with the following credentials:

1. o Virtual Machine: 20486B-SEA-DEV11


o User name: Admin
o Password: Pa$$w0rd
Open the PhotoSharingApplication solution from the following location:

2.
File location: Allfiles
o
(D):\Labfiles\Mod07\Starter\PhotoSharingApplication
Add an existing code file to the Photo Sharing Tests project, which contains
test doubles for HTTP objects, by using the following information:

3. o Destination folder: Doubles


o Source folder: Allfiles (D):\Labfiles\Mod07\Fake Http Classes
o Code file: FakeHttpClasses.cs
Add a reference from the Photo Sharing Tests project to the System.Web
4.
assembly.
Add a new Unit Test item to the PhotoSharingTests project. Name the file,
5.
RoutingTests.cs.
Add using statements to the RoutingTests.cs file for the following
namespaces:

6. o System.Web.Routing
o System.Web.Mvc
o PhotoSharingTests.Doubles
o PhotoSharingApplication
7. Rename the TestMethod1 test to Test_Default_Route_ControllerOnly.
In the Test_Default_Route_ControllerOnly test, create a new var by using
the following information:

8. o Name: context
o Type: FakeHttpContextForRouting
o Request URL: ~/ControllerName
Create a new RouteCollection object named routes and pass it to the
9.
RouteConfig.RegisterRoutes() method.
Call the routes.GetRouteData() method to run the test by using the
10. following information:
o Return type: RouteData
o Return object name: routeData
o Method: routes.GetRouteData
o HTTP context object: context
Assert the following facts:

11. o That routeData is not null


o That the controller value in routeData is “ControllerName”
o That the action value in routeData is “Index”
Add a new test to the RoutingTests class named,
12.
Test_Photo_Route_With_PhotoID.
In the Test_Photo_Route_With_PhotoID() test method, create a new var by
using the following information:

13. o Name: context


o Type: FakeHttpContextForRouting
o Request URL: ~/photo/2
Create a new RouteCollection object named routes and pass it to the
14.
RouteConfig.RegisterRoutes() method.
Call the routes.GetRouteData() method to run the test by using the
following information:

15. o Return type: RouteData


o Return object name: routeData
o Method: routes.GetRouteData
o Http context object: context
Assert the following facts:

o That routeData is not null


16. o That the controller value in routeData is “Photo”

o That the action value in routeData is “Display”


o That the id value in routeData is “2”
17. Add a new test to the RoutingTests class named Test_Photo_Title_Route
In the Test_Photo_Title_Route test method, create a new var by using the
following information:

18. o Name: context


o Type: FakeHttpContextForRouting
o Request URL: ~/photo/title/my%20title
Create a new RouteCollection object named routes and pass it to the
19.
RouteConfig.RegisterRoutes() method.
Call the routes.GetRouteData() method to run the test by using the
following information:

20. o Return type: RouteData


o Return object name: routeData
o Method: routes.GetRouteData
o HTTP context object: context
Assert the following facts:

o That routeData is not null


21. o That the controller value in routeData is “Photo”

o That the action value in routeData is “DisplayByTitle”


o That the title value in routeData is “my%20title”
Run all the tests in the Photo Sharing Tests project to verify the test results.
22.
Note: Two of the tests should fail because the routes that they test do not yet
exist.

Task 2: Add and test the Photo ID route.

1. Open the RouteConfig.cs file in the PhotoSharingApplication project.


Add a new route to the Photo Sharing application by using the following
2. information. Add the new route before the default route:
o Name: PhotoRoute
o URL: photo/{id}
o Default controller: Photo
o Default action: Display
o Constraints: id = "[0-9]+"
3. Run all the tests in the Photo Sharing Tests project to verify the test results.

Task 3: Add and test the Photo Title route.

Add a new route to the Photo Sharing application by using the following
information. Add the new route after the PhotoRoute route but before the
default route:

1. o Name: PhotoTitleRoute
o URL: photo/title/{title}
o Default controller: Photo
o Default action: DisplayByTitle
Add a new action method to PhotoController.cs by using the following
information:

2. o Scope: public
o Return type: ActionResult
o Name: DisplayByTitle
o Parameter: a string named title
In the DisplayByTitle action method, use the context.FindPhotoByTitle()
3. method to locate a photo. If the context.FindPhotoByTitle() method returns
null, return HttpNotFound(). Otherwise, pass the photo to the Display view.
4. Run all the tests in the Photo Sharing Tests project to verify the test results.

Task 4: Try out the new routes.

1. Start the PhotoSharingApplication project with debugging.


View properties of the Display link of any image on the home page, and note
2.
the route that has been used to formulate the link.
3. Display any image to verify the URL.
Access the following relative URL:
4.
o /photo/title/sample photo 3
5. Stop debugging.

Results: After completing this exercise, you will be able to create a Photo
Sharing application with three configured routes that enable visitors to easily
locate photos by using logical URLs.

Exercise 2: Optional—Building Navigation Controls

Scenario

In this exercise, you will:

o Add the MVC site map provider to your Photo Sharing application.
o Use the MVC site map provider to create a menu and a breadcrumb control.

At this stage of development, most of the main areas in the Photo Sharing
Application are not yet built; therefore, the menu will show only the home page
and the All Photos gallery. Your team will add new nodes to the site map as areas
of the site are completed.

Complete this exercise if time permits

The main tasks for this exercise are as follows:

1. Install the MVC site map provider.


2. Configure the MVC site map provider.
3. Render menus and breadcrumb trails.
4. Try out the menus.

Task 1: Install the MVC site map provider.


Start the NuGet Packages manager and locate the MvcSiteMapProvider
1.
package.
2. Install the MvcSiteMapProvider package.

Task 2: Configure the MVC site map provider.

1. Open the Web.config file in the PhotoSharingApplication project.


2. Configure the MvcSiteMapProvider to disable localization.
3. Save the changes made to the Web.config file.
Open the Mvc.sitemap file and remove the <mvcSiteMapNode> element with
4.
the title, About.
Add an <mvcSiteMapNode> element within the Home node by using the
following information:

5. o Title: All Photos


o Controller: Photo
o Action: Index
o Key: AllPhotos
6. Save the changes made to the Mvc.sitemap file.
7. Build the solution.

Task 3: Render menus and breadcrumb trails.

Render a site menu on the Home Index view by using the following
information:

o Helper: Html.MvcSiteMap()
1. o Method: Menu
o Start From Current Note: False
o Starting Node in Child Level: False
o Show Starting Node: True
Render a breadcrumb trail on the Home view by using the following
information:
2.
o Helper: Html.MvcSiteMap()
o Method: SiteMapPath
Render a site menu on the Photo Index view by using the following
information:

o Helper: Html.MvcSiteMap()
3. o Method: Menu
o Start From Current Note: False
o Starting Node in Child Level: False
o Show Starting Node: True
Render a breadcrumb trail on the Photo Index view by using the following
information:
4.
o Helper: Html.MvcSiteMap()
o Method: SiteMapPath

Task 4: Try out the menus.

1. Start debugging the PhotoSharingApplication project.


2. Use the menu option to browse to All Photos.
3. Use the breadcrumb trail to browse to the Home page.
4. Stop debugging and close the Visual Studio application.

Results: After completing this exercise, you will be able to create a Photo
Sharing application with a simple site map, menu, and breadcrumb control.

Question: In Exercise 1, when you ran the tests for the first time, why did
Test_Default_Route_Controller_Only pass when
Test_Photo_Route_With_PhotoID and Test_Photo_Title_Route fail?

Question: Why is the constraint necessary in the PhotoRoute route?


Module Review and Takeaways
To create a compelling web application that is easy to navigate, you must
consider carefully the architecture of the information you present. You should try
to ensure that the hierarchy of objects you present in URLs and navigation
controls matches user expectations. You should also ensure that users can
understand this hierarchy of objects without specialist technical knowledge. By
using routes and site map providers, you can present logical information
architecture to application visitors.

Best Practice: The default route is logical. However, it requires knowledge of


controllers and actions for users to understand URLs. You can consider creating
custom routes that can be understood with information that users already have.

Best Practice: You can use breadcrumb trails and tree view navigation controls
to present the current location of a user, in the context of the logical hierarchy of
the web application.

Best Practice: You can use unit tests to check routes in the routing table, similar
to the manner with which you use tests to check controllers, actions, and model
classes. It is easy for a small mistake to completely change the way URLs are
handled in your web application. This is because new routes, if poorly coded, can
override other routes. Unit tests highlight such bugs as soon as they arise.

Common Issues and Troubleshooting Tips

Common Issue Troubleshooting Tip

A route never takes effect.

Review Question(s)

Verify the correctness of the statement by placing a mark in the column to the
right.
Statement Answer

You have implemented the MVC Site Map Provider in your web
application and used it to build menus and breadcrumb trails with
which users can navigate the logical hierarchy. MVC
automatically takes routes from the MVC Site Map Provider so the
same hierarchy is used in URLs.

Question: You want to ensure that when the user specifies a relative URL in the
form, “customer/3546”, the request is forwarded to the DisplayByID() action in
the CustomerController. You also want to ensure that when the user specifies a
relative URL in the form, “customer/fullname”, the request is forwarded to the
DisplayByName() action in the CustomerController. What routes should you
add?

Module 08: Applying Styles to ASP.NET MVC 4


Web Applications
Contents:
Module Overview

Lesson Using Layouts


1:
Lesson Applying CSS Styles to an MVC Application
2:

Lesson Creating an Adaptive User Interface


3:

Lab: Applying Styles to MVC 4 Web Applications

Module Review and Takeaways

Module Overview
While building web applications, you should apply a consistent look and feel to
the application. You should include consistent header and footer sections in all
the views. ASP.NET MVC 4 includes features such as cascading style sheets
(CSS) styles and layouts that enhance the appearance and usability of your web
application. ASP.NET MVC 4 also includes features such as mobile-specific
views that allow you to build applications for different browsers or mobile
devices.

Objectives

After completing this module, you will be able to:

Apply a consistent layout to ASP.NET MVC 4 applications by using CSS and


o
layout.
o Develop device-specific views to support various browsers.
o Build adaptive user interface for mobile devices.

Lesson 1 : Using Layouts


You need to build multiple views to support the operations of the application,
such as creating an order and querying order history. However, several
maintenance issues arise while changing the common part of the application
layout, because of which you need to update each view. To resolve these
maintenance issues, you can build a common module or a shared view. A shared
view that helps to store the application logic is called a layout. ASP.NET MVC 4
includes features that help simplify the process of creating and using layouts.
You can further simplify the application management process by using the
_ViewStart file, to apply the layout to each view, instead of individually editing
each view.

Lesson Objectives
After completing this lesson, you will be able to:

o Describe layouts.
o Describe how to use layouts.
o Describe the _ViewStart file.

What Are Layouts?


The ASP.NET MVC 4 Razor engine includes a feature called layouts. Layouts
are also called template views. Layouts enable you to define a common style
template, and then apply it to all the views in a web application. The functionality
of layouts is similar to that of the master page in a traditional ASP.NET web
application. You can use layouts to define the content layout or logic that is
shared across views.

You can define multiple layouts in an ASP.NET MVC 4 application, and each
layout can have multiple sections. You can define these sections

anywhere in the layout file, even in the <head> section of the HTML. Sections
enable you to output dynamic content to multiple, non-contiguous, regions of the
final response.

Question: What are some common scenarios when you would use layouts?

Creating a Layout

While creating layouts, you need to store the layout files in the \Views\Shared
folder of the project. The \Views\Shared folder is the default location, where you
can store common view files or templates.

The following example illustrates a layout.

A Layout View

<!DOCTYPE html>
<html>

<head>

<meta name="viewport"

content="width=device-width" />

<title>@ViewBag.Title</title>

</head>

<body>

<div>

@RenderBody()

</div>

</body>

</html

In the preceding example, the @RenderBody() method indicates to the rendering


engine where the content of the view goes.

ViewBag is an object that the layout and view shares. You can use the ViewBag
object to pass information between a view and a layout. To pass information, you
need to add a property to the ViewBag object, in the ViewPage of the
ViewController or View file, and use the same property in the layout file.
Properties help you control the content in the layout, to dynamically render
webpages from the code in the view file. For example, consider that the template
uses the ViewBag.Title property to render the <title> content in the view. This
property helps define the Title property of the ViewBag object in the view and
retrieve the property in the layout. This retrieval is possible because the code in
the view file runs before the layout runs.

The following example illustrates a layout that contains a section.

Using Sections in Layouts

<!DOCTYPE html>

<html>

<head>

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

<title>@ViewBag.Title</title>

</head>

<body>

<div id="menu">

@RenderSection("MenuBar",required:false)

</div>

<div>

@RenderBody()

</div>

</body>

</html>
The MenuBar parameter in the RenderSection() helper method specifies the
name of the section that you want to render in the layout. The required
parameter is optional; it allows you to determine if the section you render is
required. Consider that a section is required, and you do not implement the
section in the layout file. In this case, ASP.NET MVC 4.0 displays the Section
not defined exception at runtime.

Implementing sections in a layout file makes it easier to track content errors. If a


section is not required, you can choose to not include it in the layout.

Additional Reading: For more information about layouts and sections, you can
see: http://go.microsoft.com/fwlink/?LinkID=288965&clcid=0x409

Question: Why do you have multiple sections in a layout?

Linking Views and Layouts

After defining the layout, you should link the layout to the view files. You should
first remove the content that is not required anymore in the view. Then, you need
to create the link between the view and the layout, so that the content removed
from the view is not reflected in the layout.

To link a layout to a view, you need to add the Layout directive at the top of the
view file. The following code shows how to add a layout in a view file.

Linking to a View
@{

ViewBag.Title = "Details";

Layout = "~/Views/Shared/SiteLayout.cshtml";

<h2>Details</h2>

You can use the ViewBag.Title property to pass page title information from the
view to the layout. You can define other properties along with the ViewBag
object, such as <meta> elements in the <head> section, and enable them to pass
information to the layout.

If you have multiple sections in the layout file, you define the content of the
sections by using the @section directive. The following code illustrates how to
use the @section directive.

Using the @section Directive

@{

ViewBag.Title = "Details";

Layout = "~/Views/Shared/SiteLayout.cshtml";

<h2>Details</h2>

@section MenuBar {

<p> this is menu</p>

}
In the preceding example, you set the layout file to display sections at the top of
each view file. Usually, you have the same layout across the entire web
application or section. You can define the layout for an application or section, by
using the _ViewStart file. During runtime, the code in the _ViewStart file runs
before all the other views in the web application. Therefore, you can place all
common application logics in the _ViewStart file.

To use the _ViewStart file, you need to add the _ViewStart.cshtml file in the
\Views folder of your project. The following code illustrates the contents of the
_ViewStart file.

The _ViewStart File

@{

Layout = "~/Views/Shared/SiteLayout.cshtml";

Question: When should you use the _Viewstart file?

Lesson 2: Applying CSS Styles to an MVC


Application
Cascading Style Sheets (CSS) is an industry standard for applying styles to
HTML pages. Different methods of applying CSS to a webpage are available.
These methods include external CSS file, inline CSS, and CSS code block in
HTML. Developers usually use an external CSS file, because this file is shared
across multiple pages and it helps apply a consistent style across the application.
You need to know how to import styles into a web application, to ensure
consistency in the appearance of the application. You also need to know how to
use Expression Blend to create rich and interactive user interfaces.

Lesson Objectives
After completing this lesson, you will be able to:

Describe the user experience that can be accomplished by using Expression


o
Blend.
o Import styles into an ASP.NET MVC 4 web application.
o Apply a consistent look and feel to an MVC 4 web application.

Overview of User Interface Design with Expression


Blend

Expression Blend is a visual authoring tool that helps developers and designers to
create user interfaces for Windows 8 HTML5 applications and other web
applications. Expression Blend for HTML includes a visual designer, which
serves as a good complement to Visual Studio. Visual Studio is developer-
centric, whereas Expression Blend for HTML is designer-centric. The functions
in Expression Blend facilitate developing HTML styles and CSS.

Expression Blend for HTML includes the interactive mode that enables
developers to visualize the

result of the design, HTML, CSS, and JavaScript, by displaying results on the
screen while they edit the code. Expression Blend for HTML also includes CSS
tools that enable you to generate and edit CSS styles on the graphical user
interface.
Question: What are the key benefits of using Expression Blend for HTML to edit
CSS?

Importing Styles into an MVC Web Application

After creating CSS styles, you should import these styles into the web
application. After importing the CSS file into the web application, you need to
modify the layout of the web application, so that you can use the CSS styles that
you imported. You can modify the layout of a web application, by using the
<link> element.

The following example shows how to use the <link> element.

Linking to a Style Sheet

<!DOCTYPE html>

<html>

<head>

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

<title>@ViewBag.Title</title>

<link href="~/Views/Shared/StyleSheet1.css" rel="stylesheet"

type="text/css" />
</head>

<body>

<div id="menu">

@RenderSection("MenuBar",required:false)

</div>

<div>

@RenderBody()

</div>

</body>

</html>

CSS selectors help browsers to determine how the CSS styles should be applied.
You can use various selectors, such as class and id selectors, to apply styles to
HTML elements.

CSS class Selector

You can define a CSS class selector to specify a style for a group of elements. To
apply the class selector to an HTML element, you need to add the class attribute
to the HTML element. You can use the .<class> syntax to add the style in the
CSS file.

The following example shows how to add the class selector in a view.

Using a Class

@{
ViewBag.Title = "Details";

Layout = "~/Views/Shared/SiteLayout.cshtml";

<h2>Details</h2>

@section MenuBar {

<p class=”menu”> this is menu</p>

The following CSS snippet shows how to create the class selector.

Applying a Style to a Class

.menu

font-weight:bold;

CSS id Selector

You can use the CSS id selector to specify a style for any unique element in your
HTML code. To apply the id selector to an HTML element, you need to add the
id attribute and a unique name to the HTML element. You can use the #<id>
syntax to add the style in the CSS file.

The following example shows how to use the id attribute in a view.

Using The id Selector


@{

ViewBag.Title = "Details";

Layout = "~/Views/Shared/SiteLayout.cshtml";

<h2>Details</h2>

@section MenuBar {

<p id="leftmenu"> this is menu</p>

The following CSS snippet shows how to create the CSS id selector.

Creating an ID Style

#leftmenu

font-size:16px;

Question: What are some common scenarios when you would use the class
selector? What are some common scenarios when you would use the id selector?

Demonstration: How to Apply a Consistent Look and


Feel
In this demonstration, you will see how to:

o Create a layout.
o Apply the layout to an MVC view.

Demonstration Steps
On the DEBUG menu of the OperasWebSite - Microsoft Visual Studio
window, click Start Debugging.
1.
Note: On the Operas I Have Seen page, note that the main heading, the menu
list, and the breadcrumb control are displayed.
On the Operas I Have Seen page, click the All Operas link.
2.
Note: On the localhost page, the main heading, the menu list, and the
breadcrumb controls are not displayed.
On the localhost page, click the Details link corresponding to any image.
3.
Note: On the localhost page, the details of the opera are displayed. The main
heading, the menu list, and the breadcrumb controls are not displayed.
4. In the Windows Internet Explorer window, click the Close button.
In the Solution Explorer pane, expand OperasWebSite, and then expand
5.
Views.
In the Solution Explorer pane, under Views, right-click Shared, point to
6.
Add, and then click View.
7. In the View name box of the Add View dialog box, type SiteTemplate.
In the View engine box, ensure that the value is Razor (CSHTML), and then
8.
ensure that the Create a strongly-typed view check box is cleared.
In the Add View dialog box, clear the Use a layout or master page check
9.
box, and then click Add.
In the _SiteTemplate.cshtml code window, locate the following code, select
the code, and then press Delete.

@{
10.
Layout = null;

}
In the _SiteTemplate.cshtml code window, locate the following code.
11.
<title>_SiteTemplate</title>

Replace the TITLE element with the following code.


12.
<title>@ViewBag.Title</title>
In the Solution Explorer pane, under Views, expand Home, and then click
13.
Index.cshtml.
In the Index.cshtml code window, locate the following code, and then select
the code.

<h1>Operas I Have Seen</h1>

<div class="topmenu">

@Html.MvcSiteMap().Menu(false, true, true)


14.

</div>

<div class="clear-floats" />

<div class="breadcrumb">

Breadcrumb Trail: @Html.MvcSiteMap().SiteMapPath()


On the EDIT menu of the OperasWebSite - Microsoft Visual Studio
15.
window, click Cut.
16. In the Solution Explorer pane, under Shared, click _SiteTemplate.cshtml.
In the _SiteTemplate.cshtml code window, place the mouse cursor in the DIV
17.
element.
On the EDIT menu of the OperasWebSite - Microsoft Visual Studio
18.
window, click Paste
In the _SiteTemplate.cshtml code window, place the mouse cursor at the end
19. of the code you just pasted, press Enter, and then type the following code.
<div>

@RenderBody()

</div>

Place the mouse cursor after the </title> tag, press Enter, and then type the
following code.
20.
<link type="text/css" rel="stylesheet"

href="~/content/OperasStyles.css" />
21. In the Solution Explorer pane, under Home, click Index.cshtml.
In the Razor code block of the Index.cshtml code window, locate the
following code, select the code, and then press Delete.
22.
Layout = null;

In the Razor code block, type the following code.


23.
ViewBag.Title = "Operas I Have Seen";

In the Index.cshtml code window, locate the following code, select the code,
and then press Delete.

<!DOCTYPE html>

<html>

24. <head>

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

<title>Operas I Have Seen</title>

</head>
<body>

<div>

</div>

In the Index.cshtml code window, locate the following code, select the code,
and then press Delete.

</div>
25.
</body>

</html>

In the Solution Explorer pane, right-click Views, point to Add, and then click
26.
View.
In the View name box of the Add View dialog box, type _ViewStart, and
27.
then, in the View engine box, ensure that the value is Razor (CSHTML).
In the Add View dialog box, ensure that the Create a strongly-typed view
28. and the Use a layout or master page check boxes are cleared, and then click
Add.
In the _ViewStart.cshtml code window, locate the following code.
29.
Layout = null;

Replace the code with the following code.


30.
Layout = "~/Views/Shared/_SiteTemplate.cshtml";

In the _ViewStart.cshtml code window, locate the following code.


31.
<!DOCTYPE html>
In the _ViewStart.cshtml code window, select from the code located to the
32.
end tag of the HTML element, and then press Delete
On the DEBUG menu of the OperasWebSite - Microsoft Visual Studio
33.
window, click Start Debugging.
On the Operas I Have Seen page, note the main heading, the menu list, and
34.
the breadcrumb control.
On the Operas I Have Seen page, click the All Operas link, and then, on the
35. Index of Operas page, note that the main heading, the menu list, and the
breadcrumb controls are displayed.
On the Index of Operas page, click the Details link corresponding to any
36. image, and then note that the main heading, the menu list, and the
breadcrumb controls are displayed along with the opera details.
37. In the Windows Internet Explorer window, click the Close button.
In the OperasWebSite - Microsoft Visual Studio window, click the Close
38.
button.

Lesson 3: Creating an Adaptive User Interface


ASP.NET MVC 4 applications facilitate adaptive user interface to render content
on different devices. Adaptive user interface is a type of user interface that
renders content based on the capability of the target web browser or device. You
need to ensure that your application supports mobile devices, so that it reaches all
types of audience. You also need to know how to use media queries, mobile-
specific views, and jQuery Mobile to ensure that your application is effective on
mobile devices.

Lesson Objectives
After completing this lesson, you will be able to:

o Describe the HTML5 viewport attribute.


Explain how CSS media queries apply specific CSS based on the capabilities of
o
the browser.
Explain how you can use MVC 4 templates to render views based on mobile
o
device screen size.
Describe the use of jQuery Mobile for building user interfaces that work on a
o
wide variety of mobile devices.
o Use NuGet to add jQuery Mobile to your projects.

The HTML5 Viewport Attribute

Adaptive rendering allows you to customize your web application to display


differently, based on the capabilities of the web browser or device.

Additional Reading: For more information about adaptive rendering techniques,


go to:

http://go.microsoft.com/fwlink/?LinkID=288966&c lcid=0x409

Mobile browsers such as Internet Explorer use the viewport attribute to render
webpages in a

virtual window. This virtual window is usually wider than the application screen.
The viewport attribute helps eliminate the need to reduce the size of layout of
each page. Reducing the size of the layout can break or distort the display of non-
mobile-optimized web applications. Creating the application interface by using
the viewport attribute enables users to zoom into the different areas of a
webpage.
Additional Reading: For more information about the viewport attribute, visit:
http://go.microsoft.com/fwlink/?LinkID=288967&clcid=0x409

The viewport tag is a meta tag that helps to control the width and height of
webpages, while it renders to web browsers.

The following example illustrates how to use the viewport tag.

Using the Viewport Tag

<meta name="viewport" content="width=device-width, initial-scale=1,

maximum-scale=1">

The width and height properties help to specify the width and height of the
virtual viewport window. You can specify the width in pixels. You can use the
keyword device-width to enable the content to fit the native screen size of the
browser.

The initial-scale property controls the initial scale or zoom level of the webpage.
The maximum-scale, minimum-scale, and user-scalable properties control the
other scalability features of the webpage.

Question: How can you control the size of the virtual viewport window?

CSS Media Queries


You may sometimes need to apply different CSS styles in your application, to
support different browsers. HTML5 includes CSS media queries, which are
special selectors that begin with @media. Media queries allow conditional
application of CSS styles, based on the device conditions or browser capabilities.
You can apply media queries in CSS and HTML.

The following example illustrates a media query in CSS.

Using a Media Query

@media only screen and (max-width: 500px) {

header{

float: none;

You can also apply a media query in the <link> element. The following example
illustrates how to include a media query in a <link> element.

Using a Media Query in the Link Element

<link rel="stylesheet" type="text/css" href="smallscreen.css" media="only

screen and

(max-width: 500px)" />

You can use CSS media queries to apply CSS styles when the screen size is less
than 500 pixels. However, you can use CSS media queries only for the screen
layout, but not the print layout.

Additional Reading: For more information about media queries, visit


http://go.microsoft.com/fwlink/?LinkID=288968&clcid=0x409
The following table describes all properties that you can include in a media
query.

Property Description

width The width of the targeted display area, which includes the
browser window in desktop and mobile devices. In desktop
computers, when you resize the browser window, the width
of the browser changes. However, on most mobile
browsers, you cannot resize the browser window. This
implies that the width of the browser remains constant.

height The height of the targeted display area, which includes the
browser window in desktop and mobile devices.

device-width The width of the entire screen of a device. For a desktop


with a screen resolution of 1,024x768, the device-width is
usually 1,024 pixels.

device-height The height of the entire screen of a device. For a desktop


with a screen resolution of 1,024x768, the device-height is
usually 768 pixels.

orientation The orientation of the device. If the device-width is larger


than the device-
height, the orientation value is set to landscape; otherwise,
it is set to portrait.

aspect-ratio The ratio of the width and height properties.

device-aspect- The ratio of the device-width and device-height properties.


ratio The following example illustrates the device-aspect-ratio
for a device with a screen resolution of 1,280x720.
Property Description

@media screen and (device-aspect-ratio: 16/9) { }

@media screen and (device-aspect-ratio: 1280/720) { }

@media screen and (device-aspect-ratio: 2560/1440) { }

color The number of bits per color component of the device. If


the device is not a color device, the value is zero.

color-index The number of entries in the color lookup table, of the


output device.

monochrome The number of bits per pixel in a monochrome frame


buffer. For non- monochrome devices, this value is zero.

resolution The resolution of the output device, or the density of the


pixels. The common units for this property include dpi and
dpcm.

scan The scanning process of TV output devices.

grid The property that detects whether the output is in the grid or
bitmap format. Grid-based devices return a value of one; all
other devices return a value of zero.

Question: Why would you choose to use CSS media queries, instead of using C#
code, to define styles for specific browsers?

MVC 4 Templates and Mobile-Specific Views


ASP.NET MVC 4 includes two new features, mobile display mode and custom
display mode, which help you to create webpages for mobile devices and
different browsers.

Additional Reading: For more information about creating webpages for mobile
device browsers, go to

http://go.microsoft.com/fwlink/?LinkID=288966&clcid=0x409

ASP.NET MVC 4 enables you to override views for

mobile devices by using a different set of view files, rather than using a
configuration. When ASP.NET MVC 4 receives a request from a mobile
browser, it analyses the request for views with the naming convention
[view].mobile.cshtml. If ASP.NET MVC 4 detects a view with the mentioned
naming convention, ASP.NET MVC 4 will serve the request by using the mobile
version of the view; otherwise, it returns the request to the standard view.

Consider that your web application includes a layout that is specific to a browser.
In this case, you can create browser-specific views for that browser by checking
the UserAgent string of that browser. The UserAgent string helps identify a
browser.

Additional Reading: For more information about creating browser-specific


view, visit http://go.microsoft.com/fwlink/?LinkID=288969&clcid=0x409
Question: Why would you choose device-specific display modes over CSS
media queries?

jQuery Mobile

The jQuery Mobile library is a mobile version of the jQuery library, which helps
to develop applications that run on mobile devices. jQuery helps to add
responsive UI elements to a web application. jQuery also enables developers to
add interactive content to the mobile version of a web application. The library
also helps to ensure that older mobile devices see usable controls. Similar to
jQuery, jQuery Mobile library includes a set of JavaScript and CSS files that
enable you to build mobile-specific applications, without adjusting the HTML
elements.

jQuery mobile includes the following JavaScript and CSS files:

o jquery.mobile.structure-<version>.css
o jquery.mobile.structure-<version>.min.css
o jquery.mobile.theme-<version>.css
o jquery.mobile.theme-<version>.min.css
o jquery.mobile-<version>.css
o jquery.mobile-<version>.js
o jquery.mobile-<version>.min.css
o jquery.mobile-<version>.min.js
o images/ajax-loader.gif
o images/ajax-loader.png
o images/icons-18-black.png
o images/icons-18-white.png
o images/icons-36-black.png
o images/icons-36-white.png

The jQuery.Mobile.MVC NuGet package simplifies the process of adding the


jQuery Mobile library to a web application by eliminating the need to manually
install the library files. NuGet is a Visual Studio extension that enables users to
download packaged content from the Internet and directly install the content into
the project. The NuGet package contains the following items:

The App_Start\BundleMobileConfig.cs file. This file helps to reference the


o
jQuery JavaScript and CSS files.
o jQuery Mobile CSS files
o A ViewSwitcher controller widget
o jQuery Mobile JavaScript files
o A jQuery Mobile-styled layout file
A view-switcher partial view. This provides a link at the upper-end of each
o
page; this link helps switch from desktop view to mobile view, and vice versa.
o .png and .gif image files

Additional Reading: For more information about the NuGet package, visit
http://go.microsoft.com/fwlink/?LinkID=288970&clcid=0x409

Note: You can use the Microsoft Ajax Content Delivery Network (CDN) to
attend to users, by using the servers that are located geographically closer to
them. CDN helps to improve the performance of the application. After adding the
NuGet package to your ASP.NET MVC application, you can change the code in
HTML or the view, to reference the jQuery Mobile library that is hosted on
Microsoft Ajax CDN.

Additional Reading: For more information about jQuery mobile that is hosted
on Microsoft CDN, visit
http://go.microsoft.com/fwlink/?LinkID=288971&clcid=0x409
Question: What are the benefits of using Microsoft Ajax CDN?

Lab: Applying Styles to MVC 4 Web Applications


Scenario

You have created a good amount of the photo-handling functionality for the
Photo Sharing web application. However, stakeholders are concerned about the
basic black-and-white appearance of the application. In addition, titles and menus
do not appear on every page.

To resolve these issues, your manager has asked you to implement the following
user interface features:

A layout for all webpages. The layout should include common elements, such
o as the main menu and breadcrumb controls, which should appear on every page
of the application.
A style sheet and images for all webpages. The web design team has provided
an HTML mock-up application to show how the final product should look. This
o
mock-up includes a style sheet and image files. You need to import these files
and apply them to every page of the application.
A mobile-specific view. The web application should be accessible from mobile
o devices such as mobile phones and tablets. In particular, you need to ensure
that devices with narrow screens can access photos easily.

Objectives

After completing this lab, you will be able to:

o Apply a consistent look and feel to the web application.


Use layouts to ensure common interface features, such as the headers, are
o
consistent across the entire web application.
Ensure that the web application renders smoothly on screens of different sizes
o
and aspect ratios.
Lab Setup

Estimated Time: 40 minutes

Virtual Machine: 20486B-SEA-DEV11

Username: Admin

Password: Pa$$w0rd

Note: In Hyper-V Manager, start the MSL-TMG1 virtual machine if it is not


already running.

Before starting the lab, you need to enable the Allow NuGet to download
missing packages during build option, by performing the following steps:

a. On the TOOLS menu of the Microsoft Visual Studio window, click Options.
b. In the navigation pane of the Options dialog box, click Package Manager.
Under the Package Restore section, select the Allow NuGet to download
c.
missing packages during build checkbox, and then click OK.

Exercise 1: Creating and Applying Layouts

Scenario

In this exercise, you will:

o Browse through the Photo Sharing web application without a layout applied.
Create a new layout and link the application to the view by using a
o
_ViewStart.cshtml file.
o Modify the home index and photo display views to use the new layout.
o Browse through the resulting web application.

The main tasks for this exercise are as follows:

1. Open and browse through the Photo Sharing application.


2. Create a new layout.
3. Set the default layout for the application.
4. Update the views to use the layout.
5. Browse through the web application.

Task 1: Open and browse through the Photo Sharing application.

Start the virtual machine, and log on with the following credentials:

1. o Virtual Machine: 20486B-SEA-DEV11


o User name: Admin
o Password: Pa$$w0rd
Open the PhotoSharingApplication solution from the following location:

2.
File location: Allfiles
o
(D):\Labfiles\Mod08\Starter\PhotoSharingApplication
Start the web application in debugging mode and verify that the menu and the
3.
breadcrumb trail are available on the home page.
Browse to the All Photos webpage and verify that the menu and the
4.
breadcrumb trail are not available on this page.
Browse to the Sample Photo 1 webpage and verify that the menu and the
5.
breadcrumb trail are not available on this page.
6. Stop debugging.

Task 2: Create a new layout.

Add a new layout to the PhotoSharingApplication project by using the


following information:

1. o File location: /Views/Shared


o View name: _MainLayout
o View type: None
o Partial view: None
o Layout or master page: None
Change the content of the TITLE element so that the page takes its title from
2.
the ViewBag.Title property.
Add an H1 heading to the page body by using the following information:

3. o Class attribute: site-page-title


o Content: Adventure Works Photo Sharing
4. Add a DIV element to the page with the class, clear-floats.
Add a DIV element to the page with the id topmenu. Within this element,
render the main menu for the page by using the following information:

o Helper: Html.MvcSiteMap()
5. o Method: Menu()
o Start from current node: False
o Starting node in child level: True
o Show starting node: True
Add a DIV element to the page with the id breadcrumb. Within this element,
render the breadcrumb trail for the page by using the following information:
6.
o Helper: Html.MvcSiteMap()
o Method: SiteMapPath()
Add a DIV element to the page. Within this element, render the view body by
using the following information:
7.
o Helper: RenderBody()
8. Save the layout.

Task 3: Set the default layout for the application.

Add a new view to the web application by using the following information:

1. o File path: /Views


o View name: _ViewStart
o View type: None
o Partial view: None
o Layout or master page: None
In the _ViewStart.cshtml file, set the Layout to
2.
~/Views/Shared/_MainLayout.cshtml
Remove all the HTML code from the _ViewStart.cshtml file, except the
3.
layout element.
4. Save the file.

Task 4: Update the views to use the layout.

1. Open the Views/Home/Index.cshtml view file.


In the first Razor code block, remove the existing line of code, and set the
2.
ViewBag.Title property to Welcome to Adventure Works Photo Sharing.
Remove the following:

Tags along with the corresponding closing tags:

▪ <!DOCTYPE>
▪ <html>
o ▪ <head>
3. ▪ <meta>
▪ <title>
▪ <body>
▪ <div>
Content:

o ▪ Menu:
▪ Current Location:
4. Save the changes made to the Index.cshtml file.
5. Open the Views/Photo/Display.cshtml view file.
In the first Razor code block, remove the existing line of code and set the
6.
ViewBag.Title property to the Title property of the Model object.
Remove the following tags along with the corresponding closing tags:

o <!DOCTYPE>
o <html>
7. o <head>
o <meta>
o <title>
o <body>
o <div>
8. Save the changes made to the Display.cshtml file.
9. Open the Views/Shared/Error.cshtml view file.
In the Razor code block, remove the existing line of code and set the
10.
ViewBag.Title property to Custom Error.
Remove the following tags along with the corresponding closing tags:

o <!DOCTYPE>
o <html>
11. o <head>
o <meta>
o <title>
o <body>
o <div>
12. Save the changes made to the Error.cshtml file.

Task 5: Browse through the web application.

Start the web application in debugging mode and verify the menu and the
1.
breadcrumb trail on the home page.
Browse to the All Photos webpage and verify that the site title, menu, and
2.
breadcrumb trail are available on this page.
Browse to Sample Photo 1 webpage and verify that the site title, menu, and
3.
breadcrumb trail are available on this page.
4. Stop debugging.

Results: After completing this exercise, you will be able to create an ASP.NET
MVC 4 web application that uses a single layout to display every page of the
application.

Exercise 2: Applying Styles to an MVC Web Application

Scenario

In this exercise, you will

Examine a mockup web application that shows the look-and-feel the web
o
designers have created for the Photo Sharing application.
Import a style sheet, with the associated graphic files from the mockup
o application, to your web application, and then update the HTML element
classes to apply those styles to the elements in views.

Examine the changes to the user interface after the styles have been applied.

The main tasks for this exercise are as follows:

1. Examine the HTML mockup web application.


2. Import the styles and graphics.
3. Update the element classes to use the styles.
4. Browse the styled web application.

Task 1: Examine the HTML mockup web application.

Open the mockup web application and verify the layout of the home page by
1. using the following information:
File path: Allfiles (D):\Labfiles\Mod08 \Expression Web Mock
o
Up\default.html
2. Browse to the All Photos webpage and verify the layout of the page.
3. Browse to the details of any photo and verify the layout of the page.
4. Close Internet Explorer.

Task 2: Import the styles and graphics.

Add a new top-level folder to the PhotoSharingApplication project with the


following information:
1.
o Name of the folder: Content
Navigate to Allfiles (D):\Labfiles\Mod08\Expression Web Mock
Up\Content, and add the following existing files to the new folder:
2.
o PhotoSharingStyles.css
o BackgroundGradient.jpg
Add a <link> element to the _MainLayout.cshtml file to link the new style
sheet by using the following information:

3. o Type: text/css
o Relation: stylesheet
o Href: ~/content/PhotoSharingStyles.css
4. Save the _MainLayout.cshtml file.

Task 3: Update the element classes to use the styles.

1. Open the _PhotoGallery.cshtml file.


Locate the first DIV element in the file and set the class attribute to photo-
2.
index-card.
For the <img> tag, remove the width attribute and set the class attribute to
3.
photo-index-card-img.
4. For the next DIV element, set the class to photo-metadata.
For the <span>Created By:</span> element, set the class attribute to display-
5.
label.
For the <span>@Html.DisplayFor(model => item.UserName)</span>
6.
element, set the class attribute to display-field.
For the <span>Created On:</span> element, set the class attribute to display-
7.
label.
For the <span>@Html.DisplayFor(model => item.CreatedDate)</span>
8.
element, set the class attribute to display-field.

Task 4: Browse the styled web application.

Start the web application in debugging mode to examine the home page with
1.
the new style applied.
2. Browse to All Photos to examine the page with the new style applied.
3. Display a photo of your choice to examine the new style applied.
4. Stop debugging.

Results: After completing this exercise, you will be able to create a Photo
Sharing application with a consistent look and feel.

Exercise 3: Optional—Adapting Webpages for Mobile Browsers

Scenario

In this exercise, you will:

o Create a new layout for mobile devices.


Add a media query to the web application style sheet to ensure that the photo
o
index is displayed on small screens.
Test the settings applied to the application by using a small browser and
o
changing the user agent string.

Complete this exercise if time permits.


The main tasks for this exercise are as follows:

1. Test the application as a mobile device.


2. Add a new mobile layout.
3. Add a media query to the style sheet.
4. Retest the application as a mobile device.

Task 1: Test the application as a mobile device.

5. Start the web application in debugging mode.


Resize the browser window to the following dimensions:

1. o Width: 480 pixels

o Height: 700 pixels


2. Set the user agent string to IE9 for Windows Phone 7.
3. Refresh the home page and examine the mobile view of the application.
4. Stop debugging.

Task 2: Add a new mobile layout.

Create a copy of the _MainLayout.cshtml file in the Views/Shared folder


1.
and rename the file as _MainLayout.Mobile.cshtml.
In the _MainLayout.Mobile.cshtml file, in the main page heading, place a
2.
<br /> tag after the words Adventure Works.
After the H1 element, add an H2 element.
3.
o Content: Mobile Site
4. Save the _MainLayout.Mobile.cshtml mobile view.

Task 3: Add a media query to the style sheet.

1. Open the PhotoSharingStyles.css style sheet.


Add a media query to the style sheet that applies only to screen size and only
2.
when the maximum screen width is 500 pixels or less.
3. Examine the existing style of the topmenulink class.
4. Add the same style to the media query.
In the media query, set the width attribute for the topmenulink style to 100
5.
pixels.

Task 4: Retest the application as a mobile device.

1. Start the web application in a debugging mode.


2. Clear the browser cache to ensure that the style sheet is reloaded.
3. Set the user agent string to IE9 for Windows Phone 7.
Close the developer window and refresh the web application to examine
4.
whether the problem persists in the mobile view of the application.
5. Stop debugging and close Microsoft Visual Studio.

Results: After completing this exercise, you will be able to create a Photo
Sharing application that displays well on mobile devices and devices with small
screens.

Question: When you first browsed the web application in Exercise 1, why was
the menu and the breadcrumb trail visible on the home page, but not on the All
Photos page or any other page?

Question: When you first viewed the site as a mobile browser in Exercise 3,
what are the problems you came across with the display of the site heading and
menu?

Module Review and Takeaways


In this module, you learned how to apply a consistent look and feel to a web
application, and share other common components, such as headers and footers,
between all views. You also learned how to use the CSS and display modes to
adapt the web application for smaller screens and mobile devices. You also
familiarized yourself with HTML5 elements that allow you to develop web
applications that work on various browsers and devices.

Real-world Issues and Scenarios

When you develop web applications, you need to create applications that work
on different devices and browsers, such as iPhone, iPad, Windows Phone,
Google Chrome, and Internet Explorer 10. In such cases, you can use the
HTML5 elements and features in MVC 4, such as mobile-specific views, media
queries, and jQuery Mobile library, to create applications that work well in
various browsers and devices.

Review Question(s)

Question: You are building an application, which needs to work in different


mobile devices, Windows Phone, Windows, and Mac. You want to reduce the
effort for maintaining the code which is required for different devices and you
want to ensure that it would work with new browsers. What should you do?

 Module 09:
Aspecto destacadoNotaExpandir aspecto destacadoExpandir nota

Building Responsive Pages in ASP.NET MVC 4


Web Applications
Contents:
Module Overview

Lesson Using AJAX and Partial Page Updates


1:
Lesson Implementing a Caching Strategy
2:

Lab: Building Responsive Pages in ASP.NET MVC 4 Web Applications

Module Review and Takeaways

Module Overview
Many web applications need to display large amount of information and
graphics. Large volumes of data make web applications take longer to load.
Instead of having all the elements on the page load multiple times, you can
implement caching in your web applications to reduce the need to repeatedly load
the same elements. You can also use partial page updates to reduce the need to
load the entire webpage, by enabling the application to refresh only specific
sections of the webpage.

Objectives

After completing this module, you will be able to:

o Implement partial page updates that help reduce the need to reload entire pages.
Implement caching to reduce the loading time of the different elements of a
o
webpage.

Lesson 1 : Using AJAX and Partial Page Updates


While developing web applications, to update individual sections in the page,
you may need to reload the entire webpage. Asynchronous JavaScript and XML
(AJAX) in ASP.NET MVC 4 enables partial page updates, to help update
sections of a webpage, without reloading the entire page. The Ajax.ActionLink
helper helps implement partial page updates in your web application.

Lesson Objectives
After completing this lesson, you will be able to:

o Describe the benefits of using partial page updates.


o Use AJAX in an ASP.NET MVC 4 web application.
o Use the Ajax.ActionLink helper.

Why Use Partial Page Updates?

ASP.NET and MVC facilitate server-side processing. Server-side processing


enables HTML rendering to occur at the server side and the server usually
generates the HTML. When you update a webpage, any updates or actions
performed on the page require a round-trip request to the server. Such constant
server requests affect the performance of the application.

The AJAX development model helps reduce the need for refreshing an entire
webpage, each time an update of page content is required. AJAX uses

JavaScript and XML to obtain information from the client system. AJAX creates
webpages based on the XML information downloaded from the server. However,
developing web applications by using AJAX is not easy, because it requires
using complex technologies, such as JavaScript and XML. Microsoft includes a
feature in ASP.NET called partial page updates that functions along with AJAX
to reduce the need for refreshing an entire webpage, each time an update occurs.

Partial page updates use AJAX technologies to help update individual sections of
a webpage, during postback. Partial page updates:

o Require fewer lines of code.


o Help reduce the data sent to users, each time a webpage update occurs.
o Increase the responsiveness of the web application.

Question: How do partial page updates help in improving the responsiveness of a


web application?

Using AJAX in an MVC 4 Web Application

To implement AJAX in your MVC 4 application, you need to create views that
render only the updated content, and not the entire webpage.

You can initially develop your web application without using AJAX, and then
check the application for any functionality errors. This practice helps reduce the
time required to troubleshoot the application. This practice also helps separate
any application functionality errors from errors that occur while implementing
AJAX.
To implement partial page updates, you need to create a view, called a partial
view, which includes

only the section that you need to update.

For example, consider a view as shown in the following code.

An Example View

@{

Layout = null;

<!DOCTYPE html>

<html>

<head>

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

<title>Index</title>

</head>

<body>

<div>

<div id="divMessage">@ViewBag.Message</div>

@Html.ActionLink("Refresh","HelloWorld")

</div>
</body>

</html>

In the preceding code example, ActionLink helps direct users to another view
called HelloWorld.

The following code shows the HelloWorld view.

The Hello World View

@{

Layout = null;

<!DOCTYPE html>

<html>

<head>

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

<title>HelloWorld</title>

</head>

<body>

<div>

@ViewBag.Message

</div>
</body>

</html>

To implement AJAX in the preceding code example, you need to update the
HelloWorld view to render only the content that is updated.

Consider another example wherein you want to render only an updated message,
on a webpage. The following code shows a view that is updated to render only
the changed message.

A ViewBag Example

@ViewBag.Message

With AJAX, the Javascript retrieves only a specific portion of a webpage, which
you want to update, from the server. In the ViewController class, you need to
update the View function to return the PartialView class, instead of the entire
View class.

The following code shows how to update the View function to return the
PartialView class.

Returning a Partial View in a Controller Action

public class Default1Controller : Controller

//

// GET: /Default1/

public ActionResult Index()

{
ViewBag.Message = "Hello";

return View();

[HttpGet]

public PartialViewResult HelloWorld()

ViewBag.Message = "Hello World";

return PartialView();

Optionally, you can add the HttpGet or HttpPost attributes before the View
function. These attributes help indicate if the partial page update should be
performed over the HTTP POST or HTTP GET method.

Question: What is the mandatory action that you should perform to implement
partial page updates in your web application?

The Ajax.ActionLink Helper


You can use the Ajax.ActionLink helper to trigger partial page updates. The
Ajax.ActionLink helper helps initiate the Javascript, to obtain the updated
HTML information from the view and replace or insert the updated HTML
information at a specific location.

The following code shows how to use the Ajax.ActionLink helper.

Using the Ajax.ActionLink Helper

@{

Layout = null;

<!DOCTYPE html>

<html>

<head>

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

<title>Index</title>
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.3.js"

type="text/javascript"></script>

<script

src="http://ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.unobtrusive-

ajax.min.js"

type="text/javascript"></script>

</head>

<body>

<div>

<div id="divMessage">@ViewBag.Message</div>

@Ajax.ActionLink("Refresh","HelloWorld", new AjaxOptions{

HttpMethod = "POST",

UpdateTargetId = "divMessage", InsertionMode = InsertionMode.Replace })

</div>

</body>

</html>

In the preceding example, parameters such as HttpMethod and UpdateTargetId


are included along with the Ajax.ActionLink helper, to:

Obtain the HTML information from the HelloWorld view, by using the HTTP
o
POST method.
o Replace the content in the divMessage HTML element.

While using the Ajax.ActionLink helper, you need to include the jQuery and
jQuery unobtrusive libraries in the same webpage, because the Ajax.ActionLink
helper uses scripts from these two libraries.

Question: What is the primary function of the Ajax.ActionLink helper?

Lesson 2: Implementing a Caching Strategy


Web applications display information on a webpage by retrieving the information
from a database. If the information that should be retrieved from the database is
large, the application may take longer to display the information on a webpage.
ASP.NET MVC 4 supports some caching techniques to help reduce the time
required to process a user request.

Before implementing caching, you should first analyze if caching is relevant to


your application, because caching is irrelevant to webpages whose content
change frequently. To successfully implement caching in your web application,
you need to familiarize yourself with the various types of caches, such as output
cache, data cache, and HTTP cache.

Lesson Objectives
After completing this lesson, you will be able to:

o Describe the benefits of using caching.


o Describe the output cache.
o Describe the data cache.
o Describe the HTTP cache.
o Describe how to prevent caching for webpage content that changes frequently.
o Configure caching.

Why Use Caching?


Caching involves storing the information that is obtained from a database in the
memory of a web server. If the content rendered by a webpage is static in nature,
the content can be stored in caches or proxy servers. When a user requests
content from a web application, caching ensures that the user receives content
from the cache, thereby eliminating the need for repeated real-time processing.

Caching:

Reduces the need to repeatedly retrieve


o
the same information from the database.
o Reduces the need to reprocess data, if a user places a request multiple times.
Helps improve the performance of a web application, by reducing the load on
o
servers.
o Helps increase the number of users who can access the server farm.

However, caching does not help web applications that include frequent content
changes. This is because, the content rendered from a cache may be outdated,
when compared to the current information. Therefore, you should evaluate the
content of your web application and analyze the impact of rendering outdated
content, before implementing caching.

Question: How does caching help increase the scalability of a web application?

The Output Cache


Output cache allows ASP.NET engines to store the rendered content of a
webpage in the memory of the web server. Therefore, when a user requests a
specific page multiple times, the content is retrieved from the cache, thereby
avoiding the execution of programming code in the server.

Output cache is a good complement to AJAX partial page updates. Output cache
and partial page updates reduce the workload on the server and increase the
number of user requests that a server can handle.

In ASP.NET MVC 4, you can implement output

caching, by adding the OutputCache attribute to the controller.

The following code shows how to implement output caching.

Configuring the Output Cache

[OutputCache(Duration = 60)]

public PartialViewResult HelloWorld()

ViewBag.Message = "Hello World";

return PartialView();

The OutputCache attribute helps direct the rendering engine to the cache that
contains results from the previous rendering process. The Duration parameter of
the OutputCache attribute helps control the period of time in seconds for which
data should be stored in the cache.

By default, the output cache stores only one copy of the rendered content, for
each view. Consider a view with the QueryString input parameter that enables
content to change based on the variable gathered from the database or a prior
request. In this case, you can add the VaryByParam property to the
OutputCache attribute, to store a copy of each unique combination of
parameters in the cache.

The following code shows how to add the VaryByParam property to the
OutputCache attribute.

Caching by Parameter Value

[OutputCache(Duration = 60, VaryByParam="ID")]

public PartialViewResult HelloWorld()

ViewBag.Message = "Hello World";

return PartialView();

In the preceding example, observe that the VaryByParam property refers to


QueryString, instead of other MVC parameters. You can also use the
VaryByCustom property.

The following code shows how to add the VaryByCustom property to the
OutputCache attribute.

Using VaryByCustom

[OutputCache(Duration = 60, VaryByCustom="browser")]

public PartialViewResult HelloWorld()

{
ViewBag.Message = "Hello World";

return PartialView();

You can add browser as the input parameter to the VaryByCustom property.
The browser parameter helps store a copy of the rendered content corresponding
to each browser that the application is run on. If you want to control and
implement your own logic to determine when a new copy should be stored, you
need to override the GetVaryByCustomString function in the Global.asax file
of your project.

Question: How does the functioning of a web application that implements the
output cache differ from an application that does not implement output cache?

The Data Cache

Web applications usually depend on the content in a database, to render content


on a webpage.

Databases sometimes encounter performance issues caused by poorly written


queries, which can slow down the performance of database requests resulting in
poor webpage performance. You can implement the data cache in your web
application to avoid loading data from a database every time a user places a
request. The MemoryCache class allows you to implement data cache in your
web application. Implementing the data cache involves the following actions:

1. Loading information from the database


2. Storing content in the MemoryCache object
3. Retrieving data from the MemoryCache object
Ensuring that content is available in the MemoryCache object; otherwise,
4.
reloading the content

The following code shows how to add the MemoryCache object.

Using the Memory Cache

System.Data.DataTable dtCustomer =

System.Runtime.Caching.MemoryCache.Default.

AddOrGetExisting("CustomerData", this.GetCustomerData(),

System.DateTime.Now.AddHours(1));

In the preceding example, the following parameters are specified:

Key. The unique identifier of the object that should be stored in the memory
o
cache.
o Value. The object that should be stored in the memory cache.
o AbsoluteExpiration. The time when the cache should expire.

You can use the AddOrGetExisting function, instead of the Add function, to
enable the application to refresh and retrieve data in one line of code. If the cache
contains the relevant data, the AddOrGetExisting function retrieves the data
from the cache. If the cache does not contain the relevant data, the
AddOrGetExisting function allows adding the data to the cache, and then
rendering the same data on the webpage.
Question: What are the benefits of implementing data caching in MVC
applications?

The HTTP Cache

You can implement HTTP caching in the Browser Cache and the Proxy Cache.

The Browser Cache

Most web browsers store the content downloaded from web servers in their local
cache. Storing data in the local cache helps remove the need to repeatedly
download content from the server.

Web browsers frequently check content for updates. If the content is updated in
the server, web browsers download the content from the server, to attend to user
requests. Otherwise, web

browsers render content from the local cache.

The Proxy Cache

The functionality of the proxy cache is similar to the functionality of the browser
cache. However, the cache is stored on a centralized server. Users can connect to
the Internet or web servers by using this proxy server. Proxy servers store a copy
of a web application in a manner similar to a web browser storing a copy of an
application in the local drives. Many users can access the cache in a proxy server,
while only one user can access the browser cache at a time.
Question: What is the difference between HTTP cache and output cache?

Preventing Caching

Caching can sometimes create issues in web applications, because if an


application involves frequent content updates, caching prevents users from
viewing these content updates. To resolve caching issues, you can implement an
HTTP header called Cache-Control. The Cache-Control header indicates to the
web browser how to handle the local cache. All HTTP clients, such as browsers
and proxy servers, respond to the instructions provided in the Cache-Control
header to determine how to handle the local cache of a web application.

Additional Reading: For more information about setting this header, go to:
http://go.microsoft.com/fwlink/?LinkID=288972&clcid=0x409

You can use the HttpCachePolicy.SetCacheability method to specify the value


of the Cache-Control header. The HttpCachePolicy.SetCacheability method
helps control caching performance.

The following code shows how to use the HttpCachePolicy.SetCacheability


method.

Using SetCacheability

Response.Cache.SetCacheability(HttpCacheability.Private);
In the preceding example, the HttpCachePolicy.SetCacheability method takes
the Private enumeration value.

To prevent caching in your web application, you should set the Cache-Control
header value to NoCache.

The code shows how to exclude the HTTP cache in your web application.

Preventing Caching

Response.Cache.SetCacheability(HttpCacheability.NoCache);

Question: What scenarios would require you to prevent caching for a web
application?

Demonstration: How to Configure Caching


In this demonstration, you will see:

o How to configure the output cache for an MVC controller action.


Measure the difference that the configured cache makes to the delivery of the
o
page.

Demonstration Steps
On the DEBUG menu of the OperasWebSite – Microsoft Visual Studio
1.
window, click Start Debugging.
On the Operas I Have Seen page, click the Tools button, and then click F12
2.
developer tools.
On the Cache menu of the developer window, click Always refresh from
3.
server.
4. On the Network tab of the developer window, click Start Capturing.
5. On the Operas I Have Seen page, click the All Operas link.
When the page is fully loaded, in the developer window, click Stop
6.
Capturing.
In the URL section of the developer window, click
7.
http://localhost:<portnumber>/Opera, and then click Go to detailed view.
8. On the Timings tab, click the Request entry.
9. In the Duration column, note the value displayed.
10. On the Network tab, click Clear, and then click Start capturing.
11. On the Operas I Have Seen page, click the All Operas link.
When the page is fully loaded, in the developer window, click Stop
12.
capturing.
In the URL section of the developer window, click
13.
http://localhost:<portnumber>/Opera, and then click Go to detailed view.
14. On the Timings tab, click the Request entry.
In the Duration column, note the value displayed.

15. Note: The time taken by the server to render the /Opera page and return the
page to the browser is similar to the time taken by the server in the first
instance. The page is not cached.
16. In the Windows Internet Explorer window, click the Close button.
In the Solution Explorer pane of the OperasWebSite – Microsoft Visual
17. Studio window, under OperasWebSite, expand Controllers, and then click
OperaController.cs.
In the OperaController.cs code window, locate the following code.
18.
using System.Web.Mvc;
Place the mouse cursor at the end of the located code, press Enter, and then
type the following code.
19.
using System.Web.UI;

In the OperaController.cs code window, locate the following code.


20.
public ActionResult Index()
Place the mouse cursor immediately before the located code, press Enter, and
then type the following code.
21.
[OutputCache(Duration=600, Location=OutputCacheLocation.Server,

VaryByParam="none")]

On the DEBUG menu of the OperasWebSite – Microsoft Visual Studio


22.
window, click Start Debugging.
On the Cache menu of the developer window, click Always refresh from
23.
server.
24. On the Network tab, click Start capturing.
25. On the Operas I Have Seen page, click the All Operas link.
When the page is fully loaded, in the developer window, click Stop
26.
capturing.
In the URL section of the developer window, click
27.
http://localhost:<portnumber>/Opera, and then click Go to detailed view.
28. On the Timings tab, click the Request entry.
29. In the Duration column, note the value displayed.
30. On the Network tab, click Clear, and then click Start capturing.
31. On the Operas I Have Seen page, click the All Operas link.
When the page is fully loaded, in the developer window, click Stop
32.
capturing.
In the URL section of the developer window, click
33.
http://localhost:<portnumber>/Opera, and then click Go to detailed view.
34. On the Timings tab, click the Request entry.
In the Duration column, note the value displayed.

35. Note: Note that the time taken by the server to render the /Opera page and
return the page to the browser is significantly less than the time taken by the
server in the first instance.
36. On the File menu of the developer window, click Exit.
37. In the Windows Internet Explorer window, click the Close button.
In the OperasWebSite – Microsoft Visual Studio window, click the Close
38.
button.

Lab: Building Responsive Pages in ASP.NET MVC


4 Web Applications
Scenario

Your manager has asked you to include comments for photos in the Photo
Sharing application. Your manager has also highlighted that the performance of
some pages in the application is too slow for a production site.

You want to ensure that comments for photos take minimal loading time, for
which you decide to use partial page updates. You also want to return pages in
quick time, while updated information is displayed, for which you decide to
configure caching in your application.

Objectives

After completing this lab, you will be able to:

Write controller actions that can be called asynchronously and return partial
o
views.
Use common AJAX helpers to call asynchronous controller actions, and insert
o
the results into Razor views.
o Configure ASP.NET caches to serve pages in quick time.

Lab Setup

Estimated Time: 60 minutes

Virtual Machine: 20486B-SEA-DEV11

Username: Admin

Password: Pa$$w0rd
Note: In Hyper-V Manager, start the MSL-TMG1 virtual machine if it is not
already running.

Before starting the lab, you need to enable the Allow NuGet to download
missing packages during build option, by performing the following steps:

a. On the TOOLS menu of the Microsoft Visual Studio window, click Options.
b. In the navigation pane of the Options dialog box, click Package Manager.
Under the Package Restore section, select the Allow NuGet to download
c.
missing packages during build checkbox, and then click OK.

Exercise 1: Using Partial Page Updates

Scenario

You have been asked to include a comment functionality on the photo display
view of the Photo Sharing application. You want to ensure high performance by
using AJAX partial page updates.

In this exercise, you will

Import a partially complete controller to add comments, and a view to delete


o
comments.

Add code to the controller for partial page update.

The main tasks for this exercise are as follows:

1. Import the Comment controller and Delete view.


2. Add the _CommentsForPhoto action and view.
3. Add the _Create Action and the _CreateAComment views.
4. Add the _CommentsForPhoto POST action.
5. Complete the _CommentsForPhoto view.

Task 1: Import the Comment controller and Delete view.


Start the virtual machine, and log on with the following credentials:

1. o Virtual Machine: 20486B-SEA-DEV11


o User name: Admin
o Password: Pa$$w0rd
Open the PhotoSharingApplication.sln file from the following location:

2. File location: Allfiles (D):\Labfiles\Mod09\Starter


o
\PhotoSharingApplication
Create a new folder in the Views folder by using the following information:
3.
o Name of the new folder: Comment
Add an existing item to the new Comment folder by using the following
information:
4.
File location of the existing item: Allfiles (D):\Labfiles\Mod09\Comment
o
Components\Delete.cshtml
Add an existing item to the Controller folder by using the following
information:
5.
File location of the existing item: Allfiles (D):\Labfiles\Mod09\Comment
o
Components\CommentController.cs

Task 2: Add the _CommentsForPhoto action and view.

Add a new action to CommentController.cs. by using the following


information:

1. o Annotation: ChildActionOnly
o Scope: public
o Return type: PartialViewResult
o Name: _CommentsForPhoto
2. Parameter: an integer named PhotoId
In the _CommentsForPhoto action, select all the comments in the database
3. that have a PhotoID value equal to the PhotoId parameter, by using a LINQ
query.
Save the PhotoId parameter value in the ViewBag collection to use it later in
4.
the view.
Return a partial view as the result of the _CommentsForPhoto action by
using the following information:
5.
o View name: _CommentsForPhoto
o Model: comments.ToList()
Add a new partial view to display a list of comments by using the following
information:

o Parent folder: Views/Shared


6. o View name: _CommentsForPhoto
o View type: Strong.
o Model class: Comment
o Create partial view: Yes.
Bind the _CommentsForPhoto.cshtml view to an enumerable collection of
7.
comments.
Create an H3 element by using the following information:
8.
o Heading: Comments
After the heading, create a DIV element with the ID comments-tool. Within
9.
this DIV element, create a second DIV element with the ID all-comments.
For each item in the model, render a DIV element with the photo-comment
10.
class.
Within the <div class="photo-comment"> element, add a DIV element with
11. the photo-comment-from class. Within this DIV element, render the
UserName value of the model item by using the Html.DisplayFor() helper.
Add a DIV element with the photo-comment-subject class. Within this DIV
12. element, render the Subject value of the model item by using the
Html.DisplayFor() helper.
Add a DIV element with the photo-comment-body class. Within this DIV
13. element, render the Body value of the model item by using the
Html.DisplayFor() helper.
Render a link to the Delete action by using the Html.ActionLink() helper.
14.
Pass the item.CommentID value as the id parameter.
In the Views/Photo/Display.cshtml view file, just before the Back To List
link, render the _CommentsForPhoto partial view by using the following
information:
15.
o Helper: Html.Action()
o Action: _CommentsForPhoto
o Controller: Comment
16. PhotoId parameter: Model.PhotoID
Run the application in debugging mode and browse to Sample Photo 1.
17.
Observe the display of comments on the page.
18. Close Internet Explorer.

Task 3: Add the _Create Action and the _CreateAComment views.

Add a new action to the CommentController.cs file by using the following


information:

1. o Scope: public
o Return type: PartialViewResult
o Name: _Create
2. Parameter: an integer named PhotoId.
In the _Create action, create a new Comment object and set its PhotoID
3.
property to equal the PhotoId parameter.
Save the PhotoId parameter value in the ViewBag collection to use it later in
4.
the view.
5. Return a partial view named _CreateAComment.
Add a new partial view for creating new comments by using the following
information:

o Parent folder: Views/Shared


6. o View name: _CreateAComment
o View type: Strong
o Model class: Comment
o Create partial view: Yes
In the _CreateAComment view, render validation messages by using the
7. Html.ValidationSummary() helper. For the excludePropertyErrors
parameter, pass true.
After the validation messages, add a DIV element with the add-comment-
8.
tool class.
Within the <div class="add-comment-tool"> element, add a DIV element
9.
with no class or ID.
Within the DIV element you just created, add a SPAN element with the
10.
editor-label class and content Subject:
After the SPAN element you just created, add a second SPAN element with
11. the editor-field class. Within this element, render the Subject property of the
model by using the Html.EditorFor() helper.
Within the <div class="add-comment-tool"> element, add a second DIV
12.
element with no class or ID.
Within the DIV element you just created, add a SPAN element with the
13.
editor-label class and content Body:
After the SPAN element you just created, add a second SPAN element with
14. the editor-field class. Within this element, render the Body property of the
model by using the Html.EditorFor() helper.
Within the <div class="add-comment-tool"> element, add an INPUT
element by using the following information:
15.
o Element: <input>
o Type: submit
16. Value: Create
17. Save all your changes.

Task 4: Add the _CommentsForPhoto POST action.

Add a new action to the CommentController.cs file by using the following


information:

o Annotation: HttpPost
1. o Scope: public
o Return type: PartialViewResult
o Name: _CommentsForPhoto
o Parameter: a Comment object named comment.
2. Parameter: an integer named PhotoId.
In the _ComentForPhoto action, add the comment object to the context and
3.
save the changes to the context.
Select all the comments in the database that have a PhotoID value equal to the
4.
PhotoId parameter by using a LINQ query.
Save the PhotoId parameter value in the ViewBag collection to use it later in
5.
the view.
Return a partial view as the result of the _CommentsForPhoto action by
using the following information:
6.
o View name: _CommentsForPhoto
7. Model: comments.ToList()
8. Save all the changes.

Task 5: Complete the _CommentsForPhoto view.

In the _CommentsForPhoto.cshtml view file, use a using{} block to render


an HTML form around all tags by using the following information:
1.
o Helper: Ajax.BeginForm()
o Action name: _CommentsForPhoto
o PhotoId parameter: ViewBag.PhotoId
2. Ajax options: UpdateTargetId = "comment-tool"
In the form code block, in the <div class="comments-tool"> element, add a
3. new DIV element with the add-comment-box class and the ID add-
comment.
In the DIV element you just created, render the _Create action of the
4. Comment controller by using the Html.Action() helper. Pass the
ViewBag.PhotoId value as the PhotoId parameter.
Add script tags to the _MainLayout.cshtml page that reference the following
content delivery network (CDN) locations:
5.
o http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.8.0.min.js
6. http://ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.unobtrusive-ajax.js
Start the web application in debugging mode, browse to Sample Photo 1, and
7.
observe the comments displayed.
Add a new comment to Sample Photo 1.
8.
o Subject: Test Comment
9. Body content: This comment is to test AJAX-based partial page updates.
10. Stop debugging.

Results: At the end of this exercise, you will have ensured that new comments
can be added and displayed on the pages of the application without a complete
page reload. You will create a Photo Sharing application with a comments tool,
implemented by using partial page updates.

Exercise 2: Optional—Configuring the ASP.NET Caches

Scenario

You have been asked to configure the ASP.NET caches in the Photo Sharing
application to ensure optimal performance. Senior developers are particularly
concerned that the All Photos gallery might render slowly because it will fetch
and display many photos from the database at a time.

In this exercise, you will:

• Configure the output cache to store the photo index view.


Use the developer tools in Internet Explorer to examine the speed at which

image files and pages render with and without caching.
Configure the output cache to store the results of the GetImage action so that

image files can be returned from the cache.

Complete this exercise if time permits.

The main tasks for this exercise are as follows:

1. Test the All Photos page with no caching.


2. Configure caching for the Index action.
3. Retest the All Photos page with Index caching.
4. Configure caching for the GetImage action.
5. Retest the All Photo page with GetImage caching.

Task 1: Test the All Photos page with no caching.

Start the application in debugging mode and configure the browser to always
1.
refresh the page from the server by using the Internet Explorer developer tools.
Capture traffic between the browser and the server when the All Photos page
2.
is loaded, by using the Network tools.
Record the time taken by the server to render the /Photo page and return the
3. page to the browser. This value is the Request duration, which you can find on
the Timings tab.
Clear the first network capture, and capture a second request to the All Photos
4.
page.
Record the second instance of time taken by the server to render the /Photo
5. page and return the page to the browser. Observe if the duration is more or less
than the first instance.
6. Stop debugging.

Task 2: Configure caching for the Index action.

Open the PhotoController.cs code file, and add a using statement for the
1.
following namespace:
2. System.Web.UI
Configure the Index action to use the output cache by using the following
information:

3. o Duration: 10 minutes
o Location: Server
o Vary by parameters: None
4. Save all your changes.

Task 3: Retest the All Photos page with Index caching.

Start the application in debugging mode, and configure the browser to always
1. refresh the page from the server, by using the Internet Explorer developer
tools.
Capture the traffic between the browser and the server when the All Photos
2.
page is loaded, by using the Network tools.
Record the time taken by the server to render the /Photo page and return the
3. page to the browser. This value is the Request duration, which you can find on
the Timings tab.
Clear the first network capture, and capture a second request to the All Photos
4.
page.
Record the second instance of the time taken by the server to render the /Photo
5. page and return the page to the browser. Observe if the duration is more or less
than the first instance.
6. Record the time taken by the server to render the /Photo/GetImage/1 request.
7. Stop debugging.

Task 4: Configure caching for the GetImage action.


In the PhotoController, configure the GetImage action to use the output
cache, by using the following information:
1.
o Duration: 10 minutes.
o Location: Server
2. Vary by parameters: id
3. Save all your changes.

Task 5: Retest the All Photo page with GetImage caching.

Start the application in debugging mode and configure the browser to always
1. refresh the page from the server, by using the Internet Explorer developer
tools.
Capture the traffic between the browser and the server when the All Photos
2.
page is loaded, by using the Network tools.
3. Record the time taken by the server to render the /Photo/GetImage/1 request.
Clear the first network capture, and capture a second request to the All Photos
4.
page.
Record the second instance of the time taken by the server to render the
5.
/Photo/GetImage/1 request and return the page to the browser.
6. Close the developer tools, stop debugging, and close Visual Studio.

Results: At the end of this exercise, you will create a Photo Sharing application
with the Output Cache configured for caching photos.

Question: In Exercise 2, why was the Request timing for /Photo not reduced for
the first request when you configured the output cache for the index action?
Question: In Exercise 2, when you configured the output cache for the
GetImage() action, why was it necessary to set VaryByParam="id"?

Module Review and Takeaways


In this module, you used AJAX and partial page updates in MVC applications.
AJAX and partial page updates help reduce the need for reloading the entire
page, when a user places a request. Partial page updates also reduce the need for
writing multiple lines of code, to update specific portions of a webpage. You also
used caching to increase the performance of a web application.

Real-world Issues and Scenarios

Web applications usually run multiple queries to retrieve information from a


database and render content on the webpages. Users sometimes complain that
webpages take longer to load. Therefore, developers implement caching in the
web application, to reduce the need to load data from a database, every time a
user places a request. Caching helps webpages load faster, thereby increasing the
performance of the application.

Review Question(s)

Question: An application is refreshing the content every 10 seconds for the


updated information from database. User complaints that this is impacting their
work and has caused data loss. How would you propose to help resolve this
issue?

 Module 10:
Aspecto destacadoNotaExpandir aspecto destacadoExpandir nota

Using JavaScript and jQuery for Responsive


MVC 4 Web Applications
Contents:
Module Overview

Lesson Rendering and Executing JavaScript Code


1:

Lesson Using jQuery and jQueryUI


2:

Lab: Using JavaScript and jQuery for Responsive MVC 4 Web


Applications

Module Review and Takeaways

Module Overview
Responsive web design is a web designing approach that helps create visually
rich and interactive web applications. JavaScript plays an important role in the
development of responsive web applications. You need to know how to use
JavaScript to implement application logic and resize interface elements, without
triggering a full-page refresh. To simplify adding JavaScript to your web
application, you need to know how to use libraries such as jQuery, jQuery UI,
and jQuery Mobile.

Objectives

After completing this module, you will be able to:


o Add JavaScript code to your web application.
o Use the jQuery and jQuery UI libraries, in your web application.

Lesson 1 : Rendering and Executing JavaScript


Code
You can create interactive HTML elements in your web application by using
JavaScript. ASP.NET renders these interactive elements on your webpages. You
can add packaged JavaScript libraries to your project by using the NuGet tool.
You should know how to use AJAX to update the contents of webpages. By
using AJAX, you can optimize the performance of your web application. In
addition, you should know how the content delivery network (CDN) helps take
content geographically closer to users.

Lesson Objectives
After completing this lesson, you will be able to:

o Describe how to add JavaScript files to an MVC application.


o Describe how to call JavaScript functions in JavaScript libraries.
o Describe how to use JavaScript Libraries in MVC 4 web applications.
List the benefits of using CDN to improve the performance of JavaScript
o
libraries.
o Describe how to use the NuGet tool to add packages.
o Use the NuGet tool to add a JavaScript Library.

Adding JavaScript Files


You can add JavaScript code to web applications by:

o Adding the JavaScript code to HTML.


o Defining the JavaScript code in dedicated JavaScript files.

JavaScript code helps add interactive functionalities to the webpages of your


application. The following example shows how to add JavaScript to HTML.

Inserting a JavaScript Function

<body>

<script type="text/javascript">

function HelloWorld() {

alert('Hello World');

</script>

<div>

...

</div>
</body>

If you have multiple HTML pages in a web application, you need to add
JavaScript code for each HTML page. You cannot simultaneously add JavaScript
code for multiple HTML pages. Therefore, you can define the JavaScript code in
a JavaScript file (.js file). Then, you can reference the JavaScript file in multiple
HTML pages. This enables you to maintain a single JavaScript file, to edit the
JavaScript code for multiple HTML pages. You can also have multiple
JavaScript code files for a single HTML page.

The following image displays the Add New Item dialog box that helps to add a
JavaScript file.

FIGURE 10.1:ADDING A JAVASCRIPT FILE

The following example shows how to reference the new JavaScript file in HTML
pages.

Referencing JavaScript Files

<script src="~/Scripts/JavaScript1.js" type="text/javascript"></script>


You can create the Scripts folder in the root folder of your MVC project, and
then save all JavaScript files in the Scripts folder.

Question: What are the advantages of using a JavaScript file?

Calling JavaScript Procedures

You can call functions defined in JavaScript files by using script blocks or event
handlers.

The following code shows how to call the HelloWorld function from a script
block.

Using a Script Block

<body>

<script type="text/javascript">

HelloWorld();

</script>

<div>

Hello
</div>

</body>

Before calling a JavaScript function, you need to define the function by using a
script block. Then, you must reference the JavaScript file from the HTML pages.

If you want to avoid calling the JavaScript function directly, you can use the
onclick JavaScript event to trigger JavaScript functions. The onclick event
initiates the JavaScript function assigned to an HTML file, when you click the
corresponding HTML element. JavaScript functions that are attached to
document object model (DOM) events are called event handlers.

The following code shows how to add the HelloWorld event handler to the
button’s onclick event.

Using an Event Handler

<body>

<div>

Hello

<input type="button" value="Hello" onclick="HelloWorld();" />

</div>

</body>

Additional Reading: For more information about events that are available for
HTML elements, go to
http://go.microsoft.com/fwlink/?LinkID=288973&clcid=0x409

Question: What is the advantage of initiating JavaScript functions by using


JavaScript events?
JavaScript Libraries

You can reduce the time taken to develop applications by using JavaScript
libraries.

JavaScript libraries help to:

o Reduce the amount of code you need to write to add functions.


o Reduce the time the system takes to debug the application.

Some commonly used JavaScript libraries include the following:

jQuery
o
(http://go.microsoft.com/fwlink/?LinkID=288974&clcid=0x409)
o jQuery UI (http://go.microsoft.com/fwlink/?LinkID=288975&clcid=0x410)
jQuery Mobile
o
(http://go.microsoft.com/fwlink/?LinkID=288976&clcid=0x411)
jQuery Validation
o
(http://go.microsoft.com/fwlink/?LinkID=288977&clcid=0x412)
o jQuery Cycle (http://go.microsoft.com/fwlink/?LinkID=288978&clcid=0x413)
jQuery DataTables
o
(http://go.microsoft.com/fwlink/?LinkID=288979&clcid=0x409)
o Prototype (http://go.microsoft.com/fwlink/?LinkID=299651&clcid=0x409)
o MooTools (http://go.microsoft.com/fwlink/?LinkID=299652&clcid=0x409)
You can use JavaScript libraries to make your application more interactive. The
functioning of JavaScript codes depends on the version of the library you use.
Not all code may work with all versions of a library.

The jQuery library (and its related libraries) has the additional advantage of
dealing with the differences in the DOM across different browsers and different
browser versions.

Question: What is the advantage of using JavaScript libraries?

Using Content Delivery Networks for JavaScript


Libraries

A content delivery network (CDN) is a group of geographically distributed


servers used for hosting contents for web applications. In many cases, you can
bring web content geographically closer to your applications users by using a
CDN to host libraries. This will also improve the scalability and robustness of the
delivery of that content.

The amount of content stored in a CDN varies among different web applications.
Some applications store all their content on a CDN, while other applications store
only some of their

content.
Microsoft has a dedicated CDN called Microsoft Ajax CDN that hosts some
popular JavaScript libraries, such as:

o jQuery
o jQuery UI
o jQuery Mobile
o jQuery Validation
o jQuery Cycle
o jQuery DataTables
o Ajax Control Toolkit
o ASP.NET Ajax
o ASP.NET MVC JavaScript Files

Note that Microsoft does not own the license of the JavaScript libraries
mentioned in the preceding list. Microsoft only hosts the libraries for developers.

You can often reduce the loading time of your web application, by using the
JavaScript libraries hosted on Microsoft Ajax CDN. Web browsers can cache
these JavaScript libraries on a local system.

The following code shows how to use JavaScript libraries.

Linking to JavaScript Libraries

<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.8.0.js"

type="text/javascript"></script>

Additional Reading: For more information about Microsoft AJAX CDN, go to


http://go.microsoft.com/fwlink/?LinkID=293689&clcid=0x409

Question: How can CDN help improve the performance of a web application?

Using the NuGet Tool to Add Packages


You can use the NuGet package manager to manage JavaScript libraries. You
can avoid adding JavaScript libraries manually to your web application by
installing the NuGet package manager in your application. This practice helps
reduce the need for configuration tasks, while adding JavaScript libraries to an
application.

Microsoft Visual Studio 2012 supports installing and using NuGet packages. You
can search for NuGet packages in the NuGet store of Microsoft Visual Studio
2012. Then, you can directly install them into your MVC application.

The following image shows the application page that you can use to manage
NuGet packages.
FIGURE 10.2:MANAGING NUGET PACKAGES

After you select the NuGet package that you wish to install, click Install, to
download and install the package into your project.

Additional Reading: To search for NuGet packages and analyze the details of
each package, go to
http://go.microsoft.com/fwlink/?LinkID=288981&clcid=0x410

Question: Why should you use NuGet packages to add JavaScript libraries to
your web application?

Demonstration: How to Use NuGet to Add a JavaScript


Library
In this demonstration, you will see how to:

o Add the jQueryUI library to an application by using NuGet Package Manager.


Access the location where jQueryUI components are added in the MVC
o
application.
o Link to a script file in the site template view.

Demonstration Steps

1. In the Solution Explorer pane of the

OperasWebSite - Microsoft Visual Studio

window, expand OperasWebSite.

Note: There is no folder named Scripts at the top level of the project.

In the Solution Explorer pane, expand Content.


2.
Note: The Content folder has only one file named OperaStyles.css, and there
are no sub-folders.
On the PROJECT menu of the OperasWebSite - Microsoft Visual Studio
3.
window, click Manage NuGet Packages.
In the navigation pane of the OperasWebSite – Manage NuGet Packages
4.
dialog box, ensure Online is selected, and then click All.
In the result pane of the OperasWebSite – Manage NuGet Packages dialog
5. box, click jQuery UI(Combined Library), click Install, and then, when the
installation is complete, click Close.
In the Solution Explorer pane, expand Scripts.
6.
Note: NuGet Package Manager has added five files for jquery and jqueryUI
to the application. Note the version number for jquery and jqueryUI.
In the Solution Explorer pane, under Contents, expand themes, expand base,
and then click jquery-ui.css.
7.
Note: NuGet Package Manager has added style sheets to the Content folder.
These styles are used to set the styles for jQueryUI widgets, and the most
important of these style sheets is jquery-ui.css.
In the Solution Explorer pane, collapse base, expand Views, and then expand
8.
Shared.
9. In the Solution Explorer pane, under Shared, click _SiteTemplate.cshtml.
In the _SiteTemplate.cshtml code window, locate the following code.
10.
</head>

Place the mouse cursor before the located code, type the following code, and
then press Enter.

<script type="text/javascript" src="@Url.Content("~/Scripts/jquery-ui-


11.
1.10.0.js")"></scripts>

Note: In the above code, note that the version number provided is 1.10.0.
When you type the code, replace the version number 1.10.0 with the latest
version number.
In the _SiteTemplate.cshtml code window, locate the following code.
12.
<title>@ViewBag.Title</title>
Place the mouse cursor at the end of the located code, press Enter, and then
type the following code.

13. <link type="text/css" rel="stylesheet"

href="@Url.Content("~/Content/themes/base/jquery-ui.css")"/>

Note: You can now use jQueryUI calls on any views in the application.
On the FILE menu of the OperasWebSite - Microsoft Visual Studio
14.
window, click Save All.
In the OperasWebSite - Microsoft Visual Studio window, click the Close
15.
button.

Lesson 2: Using jQuery and jQueryUI


jQuery is a JavaScript library that simplifies the adding of JavaScript to HTML
pages. jQuery is an open-source software that you can use for free. It helps
reduce the amount of code that you need to write, to perform tasks such as
accessing and modifying HTML elements on a webpage. You can use the ajax
function in jQuery to call a web service in your application. You can also use
jQuery UI to add interactions, animations, effects, and widgets to your web
applications.

Lesson Objectives
After completing this lesson, you will be able to:

o Describe jQuery.
Describe how to link web applications to jQuery Libraries for client-side
o
scripting.
o Describe how jQuery helps access the HTML elements of a webpage.
o Describe how to modify elements by using jQuery.
o Describe how to call a web service by using jQuery.
o Describe jQuery UI.
o Add a jQuery UI widget to an MVC 4 web application.

Introduction to jQuery

jQuery is a JavaScript library that you can use with different browsers. jQuery
was first released in 2006. jQuery helps query the HTML Document Object
Model (DOM) and obtain a set of HTML DOM elements. This feature of jQuery
helps:

o Reduce the amount of code that you need to write, to perform a task.
o Reduce the development time of HTML applications.

jQuery includes the following features:

o DOM element selections


o DOM traversal and modification
o DOM manipulation, based on CSS selectors
o Events
o Effects and animations
o AJAX
o Extensibility through plug-ins
o Utilities
o Compatibility methods
o Multi-browser support
Additional Reading: For more information about jQuery, go to:
http://go.microsoft.com/fwlink/?LinkID=288982&clcid=0x411

The jQuery family includes the following two companion modules:

jQuery UI. This library adds functions and other supporting elements that help
o
implement a rich interface to HTML-based applications.
jQuery mobile. This library adds functions that optimize the application
o
interface for mobile devices.

Question: Why should you use jQuery while developing web applications?

Linking to jQuery Libraries

jQuery Original Version and jQuery Minified Version provide similar


functionalities; however, they optimize web applications for different purposes:

jQuery Original Version (jQuery-<version>.js). This is the uncompressed


o
version of the jQuery library, with files sizes larger than 200 kilobytes (KB).
jQuery Minified Version (jQuery-<version>.min.js). This includes the
compressed and gZip versions of jQuery,
o
with file sizes of about 30 KB.

When you develop the production environment, you can use jQuery Minified
Version to reduce the loading time of the web application. If you use the minified
version while working on the development environment, you cannot access the
source code of the JavaScript libraries during the debug operation. Therefore,
you can use the original version of jQuery, while creating the development
environment.

The following code shows how to reference the jQuery library in your web
application. You can add the line of code in the <head> element of your HTML.

Referencing jQuery

<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.8.0.min.js"

type="text/javascript"></script>

Bundling and Minification

Bundling is a new feature in ASP.NET 4.5 that you can use in MVC 4 web
applications. Bundling helps combine multiple JavaScript libraries into a single
HTTP request.

Minification compresses code files before incorporating them in the client


application. Bundling and minification help reduce the loading time of web
applications by reducing both the number and size of HTTP requests.

To use bundling and minification in your web application, you should perform
the following steps:

Reference the Microsoft.AspNet.Web.Optimization library in your


1.
application by using NuGet packages.
2. In the App_Start folder of your project, add the BundleConfig.cs file.
In the BundleConfig.cs file, add the following code.

public static void


3. RegisterBundles(System.Web.Optimization.BundleCollection bundles)

{
bundles.Add(new

System.Web.Optimization.ScriptBundle("~/bundles/jquery").Include(

"~/Scripts/jquery-

{version}.js","~/Scripts/JavaScript1.js"));

4. In the Global.asax Application_Start event, add the following code.


BundleConfig.RegisterBundles(System.Web.Optimization.BundleTable.Bundles)

The ScriptBundle class enables you to define the bundle that helps combine
multiple JavaScript libraries into a single file. You can use a special placeholder,
such as {version} in the JavaScript path, to help update the version of jQuery
libraries. ASP.NET replaces {version} with the latest version number of the
JavaScript libraries present in the Scripts folder. If the minified version of jQuery
is available in the Scripts folder, the MVC 4 engine selects the minified version
for bundling. Then, in your View file, you can include the following lines of code
to render the bundled JavaScript file.

<head>

@Scripts.Render("~/bundles/jquery")

</head>

You should add the following line of code in a page or namespace of the
Web.config file in the View folder. This code helps trigger the functioning of
@Scripts.Render.

<add namespace="System.Web.Optimization"/>
Based on the compilation setting in the Web.config file, the jQuery library
renders minified versions of Javascript. For example, the following code sets the
debug attribute of the compilation element to false, which allows jQuery to use
the non-minified version of the libraries, making debugging of the libraries
easier.

<compilation debug="false" />

Question: What are the benefits of using the minified version of jQuery in the
production environment?

Accessing HTML Elements by Using jQuery

jQuery helps access HTML elements, to create interactive web applications. You
use the following selector to select elements by element name, id, or CSS class,
while adding jQuery code to access HTML elements.

$(element name|#id|.class)

The following jQuery selector accesses the HTML element with the HelloButton
ID.

$(“#HelloButton”)
You can use jQuery to access or modify all instances of a specific HTML
element, in an HTML page. The following jQuery selector identifies all instances
of the A element in an HTML page.

$(“a”)

After accessing the HTML elements, you can perform actions on the elements,
such as:

o Modifying the attributes on the HTML elements.


Defining event handlers to respond to events associated with the selected
o
HTML elements.

The following example adds an event handler to the click event of the
HelloButton HTML element.

Using a jQuery Event Handler

$("#HelloButton").click(function (event) {

alert("Hello World");

});

If the jQuery scripts load before the webpage loads, you may encounter errors
such as object not defined. You can place the jQuery code in the
document.ready event, to prevent the code from loading until all HTML
elements in the page load.

The following code shows how to use the document.ready function

Using the Document Ready Function

$(document).ready(function () {

//Code placed here will not execute before the page is fully loaded.
});

The following complete example shows how to access HTML elements by using
jQuery.

A Complete Example

<body>

<div>

Hello

<input type="button" value="Hello" id="HelloButton" />

</div>

<script type="text/javascript">

$(document).ready(function () {

$("#HelloButton").click(function (event) {

alert("Hello World");

});

});

</script>

</body>

Question: Why should you include the jQuery code in the document.ready
event?

Modifying HTML Elements by Using jQuery


You can use jQuery to query HTML DOM and obtain HTML elements. You can
use jQuery functions to modify the attributes associated with the HTML
elements. The following are some commonly used jQuery functions, which
enable you to modify HTML elements:

You can use the val function to get or set the value of an HTML element. The
following example shows how to use the val function to set the value of the
HelloButton element to “Hello World”.

The val Function

$('#HelloButton').val('Hello World');

You can use the css function to get or set the inline CSS style associated with an
HTML element. The following example shows how to use the css function to set
the background color of an HTML element to blue.

The css Function

$('#HelloButton').css('background-color','blue);

You can use the addclass function to assign a CSS class to an HTML element.
The following example shows how to use the addclass function to add the
input_css_class to an HTML element.

The addclass Function


$('#HelloButton').addClass('input_css_class');

Additional Reading: For more information about jQuery functions, go to


http://go.microsoft.com/fwlink/?LinkID=288983&clcid=0x412

Question: If querying HTML DOM returns multiple HTML elements, how will
jQuery functions handle these elements?

Calling a Web Service by Using jQuery

jQuery includes the ajax function that helps:

1. Perform asynchronous calls to web services.


2. Retrieve the data returned from web services.

The following example illustrates how to use the ajax function.

Using the ajax Function

var req= $.ajax({

type: "POST",

dataType: "json",

url: "Customer.asmx/GetCustomerInfo",
data: "{'ID': '123'}",

contentType: "application/json; charset=utf-8",

success: function (msg) {

alert("Data Saved: " + msg);

},

failure: function (msg) {

alert(msg);

});

The ajax function uses the parameters type, datatype, url, data, contentType,
success, and failure to control how to call the web services. These parameters
are described as follows:

type. This parameter controls the request type that you should use while
o
querying the web services.
o dataype. This parameter defines the data type to be sent for AJAX services.
o url. This parameter provides the URL of the web services.
data. This parameter defines the data that you should provide as a parameter to
o
the web services.
contentType. This parameter defines the HTTP content type that you should
o
use, when you submit HTTP requests to web services.
success. This parameter defines the name of the function, which will be
o
triggered when the call completes successfully.
failure. This parameter defines the name of the function, which will be
o
triggered when the call completes with errors.

When calls to the web services complete, jQuery triggers one of two callback
functions based on the success of the call.
Additional Reading: For more information about the AJAX function, go to
http://go.microsoft.com/fwlink/?LinkID=288984&clcid=0x413

Question: Why should you call web services by using jQuery?

Introduction to jQueryUI

jQuery simplifies interacting with JavaScript elements, by providing a simple


query-based syntax. jQuery UI is a library that includes widgets, animations, and
themes that help you to build a rich user interface.

jQuery Widgets

You can add different types of widgets to your pages by using the following
jQuery functions:

o Accordion. This function adds accordion containers to your webpage.


Autocomplete. This function adds auto-
o
complete boxes that are based on user input.
o Button. This function adds buttons to your webpage.
o Datepicker. This function adds date-pickers to your webpage.
o Dialog. This function adds dialog boxes to your webpage.
o Menu. This function adds a menu to your webpage.
Progressbar. This function adds animated and static progress bars to your
o
webpage.
o Slider. This function adds sliders to your webpage.
o Spinner. This function adds a number spinner to a data entry box.
o Tabs. This function adds tabs to your webpage.
o Tooltip. This function displays a tooltip for interface elements.

jQuery Effects

You can add various effects by using the following jQuery functions:

o Color Animation. This function animates colors.


Toggle Class, Add Class, Remove Class, and Switch Class. This function adds
o
or removes CSS classes.
Effect. This function adds a variety of effects, such as appear, slide-down,
o
explode, and fade-in.
o Toggle. This function toggles any jQuery effect on and off.
o Hide and Show. This function displays or hides any jQuery effect.

jQuery Utility

You can align your webpage content by using the Position jQuery utility. This
utility helps align an element in relation to the position of another element.

To use jQuery UI:

Download the script and supporting files from


1.
http://go.microsoft.com/fwlink/?LinkID=288985&clcid=0x414
2. Reference the JavaScript libraries in the HTML files.

The following line of code shows how to use jQuery UI.

Linking to jQuery UI

<script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.9.2/jquery-

ui.min.js"
type="text/javascript"></script>

Question: What is the key difference between jQuery and jQuery UI?

Demonstration: How to Add a jQueryUI Widget


In this demonstration, you will see how to:

Create a set of expandable sections on a webpage by using the Accordion


o
widget.

Demonstration Steps

On the DEBUG menu of the OperasWebsite – Microsoft Visual Studio


1.
window, click Start Debugging.
2. On the Operas I Have Seen page, click the All Operas link.
In the Main Opera List section, click the Details link corresponding to Cosi
3.
Fan Tutte.
Under Reviews, note that there are three opera reviews displayed for Cosi
4.
Fan Tutte, simultaneously.
5. In the Windows Internet Explorer window, click the Close button.
In the Solution Explorer pane of the OperasWebsite – Microsoft Visual
6.
Studio window, under Shared, click _ReviewsForOpera.cshtml.
In the _ReviewsForOpera.cshtml code window, locate the following code.
7.
<h3>Reviews</h3>

Place the mouse cursor immediately before the located code, type the
following code, and then press Enter.

<script>
8.
$(function() {

$("#reviews-tool").accordion();
});

</script>

On the DEBUG menu of the OperasWebsite – Microsoft Visual Studio


9.
window, click Start Debugging.
10. On the Operas I Have Seen page, click the All Operas link.
In the Main Opera List section, click the Details link corresponding to Cosi
11.
Fan Tutte.
Under Reviews, note that there are three expandable sections, and each
12. section contains a review.
Note: You can expand each section and then read the review content.
13. In the Windows Internet Explorer window, click the Close button.
In the OperasWebSite – Microsoft Visual Studio window, click the Close
14.
button.

Lab: Using JavaScript and jQuery for Responsive


MVC 4 Web Applications
Scenario

You have been asked to add a slideshow page to the web application that will
show all the photos in the database. Unlike the All Photos gallery, which shows
thumbnail images, the slideshow will display each photo in a large size.
However, the slideshow will display only one photo at a time, and cycle through
all the photos in the order of ID.

You want to use jQuery to create this slideshow because you want to cycle
through the photos in the browser, without reloading the page each time. You
also want to animate slide transitions and show a progress bar that illustrates the
position of the current photo in the complete list. You will use jQueryUI to
generate the progress bar.
Begin by importing a partially complete view that will display all photos
simultaneously in the correct format. Then, change styles and add jQuery code to
the application to create your slideshow.

Objectives

After completing this lab, you will be able to:

o Render and execute JavaScript code in the browser.


o Use the jQuery script library to update and animate page components.
o Use jQueryUI widgets in an MVC application.

Lab Setup

Estimated Time: 40 minutes

Virtual Machine: 20486B-SEA-DEV11

User name: Admin

Password: Pa$$w0rd

Note: In Hyper-V Manager, start the MSL-TMG1 virtual machine if it is not


already running.

Before starting the lab, you need to enable the Allow NuGet to download
missing packages during build option, by performing the following steps:

a. On the TOOLS menu of the Microsoft Visual Studio window, click Options.
b. In the navigation pane of the Options dialog box, click Package Manager.
Under the Package Restore section, select the Allow NuGet to download
c.
missing packages during build checkbox, and then click OK.

Exercise 1: Creating and Animating the Slideshow View

Scenario
Your team has created a view that displays photos of the right size and format.
However, the view displays all photos simultaneously, one below the other.

In this exercise, you will:

Import the view and modify the style sheet so that the photos are displayed on
o
top of each other.
Using jQuery, set the order for each photo so that each photo is displayed
o
sequentially.

The main tasks for this exercise are as follows:

1. Import and test the slideshow view.


2. Modify the style sheet.
3. Animate the photo cards in the slideshow.
4. Link to the script and test the animation.

Task 1: Import and test the slideshow view.

Start the virtual machine, and log on with the following credentials:

1. o Virtual machine: 20486B-SEA-DEV11


o User name: Admin
o Password: Pa$$w0rd
Open the PhotoSharingApplication.sln file from the following location:

2. File location: Allfiles (D):\Labfiles\Mod10\Starter


o
\PhotoSharingApplication
Add the SlideShow.cshtml view file to the Photo folder, from the following
location:
3.
o File location: Allfiles (D):\Labfiles\Mod10\Slide Show View
In the PhotoController.cs file, edit the SlideShow action method. Instead of
4. throwing an exception, return the SlideShow view you just added. Pass a list
of all the photos in the context object as the model.
Add a new site map node to the Mvc.sitemap file to link to the SlideShow
action by using the following information:

o Tag: <mvcSiteMapNode>
5. o Title: Slideshow
o Visibility: *
o Controller: Photo
o Action: SlideShow
Start the web application in debugging mode, clear the browser cache, and
6.
then browse to the Slideshow view to examine the results.
7. Stop debugging.

Task 2: Modify the style sheet.

In the Content folder, open the PhotoSharingStyles.css style sheet. Add the
following properties to the style that selects <div> tags with the slide-show-
card class:

1. o position: absolute
o top: 0
o left: 0
o z-index: 8
Add a new style to the PhotoSharingStyles.css style sheet by using the
following information:
2.
o Selector: #slide-show DIV.active-card
o z-index: 10
Add a new style to the PhotoSharingStyles.css style sheet by using the
3. following information:
o Selector: #slide-show DIV.last-active-card
o z-index: 9
Start debugging, and then clear the Internet Explorer browser cache to ensure
4.
that the style sheet is reloaded.
5. Navigate to the Slideshow view and examine the results.
6. Stop debugging.

Task 3: Animate the photo cards in the slideshow.

1. Add a new top-level folder, named Scripts, to the Photo Sharing application.
2. Add a new JavaScript file, SlideShow.js, to the Scripts folder.
In the SlideShow.js file, create the following global variables:

o percentIncrement
3.
o percentCurrent

Set the percentCurrent value to 100.


4. Create a new function named slideSwitch with no parameters.
Within the slideSwitch function, add a line of code that selects the first <div>
5. element with active-card class that is a child of the element with an ID of
slide-show. Store this element in a new variable named $activeCard.
Add an if statement stating that if the $activeCard contains no elements, use
6. the last DIV element with slide-show-card class that is a child of the element
with an ID of slide-show.
Add a line of code that selects the next element after $activeCard. Store this
7.
element in a new variable named $nextCard.
Add an if statement stating that if $nextCard contains no elements, use the
8.
first DIV element with slide-show-card class and ID slide-show.
9. Add the last-active-card class to the $activeCard element.
Set the opacity of the $nextCard element to 0.0 by using the css() jQuery
10.
function.
Add the active-card class to the $nextCard element. This applies the z-
11.
order value 10, from the style sheet.
Use the animate() function to fade the $nextCard element to opacity 1.0
over a time period of 1 second. When the animate() function is complete,
remove the following classes from the $activeCard element:
12.
o active-card
o last-active-card
Create a new anonymous function that runs when the document is fully
13.
loaded.
In the new anonymous function, use the setInterval() function to run the
14.
slideSwitch() function every 5 seconds.
15. Save all the changes.

Task 4: Link to the script and test the animation.


1. Open the SlideShow.cshtml view file.
2. Add a SCRIPT element that links to the SlideShow.js script file.
Start the application in debugging mode and navigate to the Slideshow view.
3.
Observe the fade effects.
4. Stop debugging.

Results: At the end of this exercise, you will have created a Photo Sharing
application with a slideshow page that displays all the photos in the application,
sequentially.

Exercise 2: Optional—Adding a jQueryUI ProgressBar Widget

Scenario

The slideshow pages you added work well. Now, you have been asked to add
some indication of progress through the slideshow. You want to use a progress
bar to show the position of the current photo in the list of photos in the
application. In this exercise, you will:
o Create a display by using the JQueryUI progress bar.
o Test the script that you created.

Complete this exercise if time permits.

The main tasks for this exercise are as follows:

1. Complete the slideshow view and template view.


2. Modify the slideshow script.
3. Test the slideshow view.

Task 1: Complete the slideshow view and template view.

1. Open the SlideShow.cshtml view file from the Photo folder.


Within the <div id="slideshow-progress-bar-container">element, add a
2.
new <div> element with the ID slide-show-progress-bar.
Add a <script>tag to the Views/Shared/_MainLayout.cshtml view to link
the view to jQuery UI. Ensure the <script> tag appears after the other
<script>tags in the HEAD element. Link the view to the following location:
3. http://ajax.aspnetcdn.com/ajax/jquery.ui/1.10.0/jquery-ui.min.js

Note: In the code, note that the version number provided is 1.10.0. When
typing the code, replace the version number 1.10.0 with the latest version
number.
Add a <link> tag to link to the jQuery UI style sheet by using the following
information:

o Type: text/css
4. o Rel: stylesheet
Href: http://code.jquery.com/ui/1.9.2/themes/base/jquery-ui.css

o Note: In the code, note that the version number provided is 1.9.2. When
typing the code, replace the version number 1.9.2 with the latest version
number.
5. Save all the changes.
Task 2: Modify the slideshow script.
1. Open the SlideShow.js JavaScript file.
2. Create a new function named calculateIncrement that takes no parameters.
In the new function, create a new variable named cardCount. Use this
3. variable to store the number of <div class="slide-show-card"> elements
within the <div id="slide-show"> element.
Divide 100 by the cardCount variable, and store the result in
4.
percentIncrement.
Run the jQueryUI progressbar() function on the <div id="slidehow-
5.
progress-bar">element. Set the value to 100.
Before the call to setInterval(), insert a call to the new calculateIncrement()
6.
function.
At the beginning of the slideSwitch() function, add the value of
7.
percentIncrement to the value of percentCurrent.
Add an if statement stating that if percentCurrent is more than 100, set
8.
percentCurrent is to equal percentIncrement.
Run the jQueryUI progressbar() function on the <div id="slideshow-
9.
progress-bar"> element. Set the value to percentCurrent.
10. Save all the changes.

Task 3: Test the slideshow view.

Start the web application in debugging mode and clear the browser cache.
1.
Navigate to the Slideshow view and examine the results.
2. Stop debugging and close Visual Studio.

Results: At the end of this exercise, you will have created a slideshow page with
a progress bar that displays the position of the current photo in the list of photos.

Question: What is the use of adding the two links to the _MainLayout.cshtml
file in Task 1 of Exercise 2?

Question: You added <script> tags to the _MainTemplate.cshtml file to enable


jQueryUI. Is this the optimal location for this link?
Module Review and Takeaways
You have seen how to use JavaScript in a web application. JavaScript helps the
application interact with the actions of users and provide response to users,
without reloading an entire webpage. You also saw how to use the jQuery library
to access the HTML DOM structure and modify HTML elements. jQueryUI is a
complement to the jQuery library, which contains functions to build rich user
interfaces.

Review Question(s)

Question: You are building an application that needs to update various parts of
the page every 10 seconds. Your team is proposing to use IFRAME. But you
want to reduce the number of pages to be created. What type of technology
should you propose to achieve this?

 Module 11:
Aspecto destacadoNotaExpandir aspecto destacadoExpandir nota

Controlling Access to ASP.NET MVC 4 Web


Applications
Contents:
Module Overview

Lesson Implementing Authentication and Authorization


1:
Lesson Assigning Roles and Membership
2:

Lab: Controlling Access to ASP.NET MVC 4 Web Applications

Module Review and Takeaways

Module Overview
Authentication is a vital requirement in most web-based applications. Developers
usually display only restricted information to all users. Web applications require
users to authenticate themselves to view exclusive information. Web applications
also display specific information that is relevant to specific user roles. Microsoft
ASP.NET 4.5 includes various authentication models, including local
authentication providers, claim-based authentication systems, and federated
authentication systems. You need to know how to use these authentication
models to implement authentication functionality in your web application. You
should also know how to authorize users and roles in your application to restrict
information access according to user and role membership.

Objectives

After completing this module, you will be able to:

o Implement authentication and authorization systems in your web application.


o Manage users and roles in your web application.
o Authorize users and roles in your web application.
Lesson 1 : Implementing Authentication and
Authorization
Membership providers, which were introduced in ASP.NET 2.0, help you to
create secure authentication and authorizations systems for web applications.
You need to know how to use the membership provider model in ASP.NET 4.5,
to change authentication methods with minimum changes to the code. You can
use claim-based authentication and federated authentication to allow external
users to authenticate themselves, and access and use the web application. You
should know how to configure restrictions in the web application to ensure that
users access only specific information that is permitted and relevant to them.

Lesson Objectives
After completing this lesson, you will be able to:

List the local authentication options available for an ASP.NET 4 web


o
application.
o Describe how client-based authentication works.
o Describe how federated authentication works.
o Describe how to restrict access to resources.
o Authorize access to specific users to MVC 4 web application controller actions.

Local Authentication Providers


Authentication providers include code that runs when ASP.NET needs to
authorize a user. The code authenticates users by using the information stored in
back-end databases, such as Active Directory or Microsoft SQL Server. The
membership system in ASP.NET 4.5 includes the following authentication
providers:

ActiveDirectoryMembershipProvider, SqlMembershipProvider,
SimpleMembershipProvider, and UniversalProviders. The
SimpleMembershipProvider and

UniversalProviders are new authentication providers that support the OAuth


authentication mechanism.

The ASP.NET 4.5 membership system allows application developers to switch


amongst authentication providers, without modifying the code.

The following is a description of the authentication providers—


ActiveDirectoryMembershipProvider and SqlMembershipProvider:

ActiveDirectoryMembershipProvider. This provider class is defined in the


o System.Web.Security namespace, and the provider enables you to use Active
Directory as the membership and role repository of your web application.
SqlMembershipProvider. This provider class is defined in the
o System.Web.Security namespace. The provider works with a specific table
schema that you can generate by using the aspnet_regdb.exe command.

ActiveDirectoryMembershipProvider and SqlMembershipProvider are


configured to work only with a specific table schema or directory. To overcome
this restriction, Microsoft developed SimpleMembershipProvider and
UniversalProviders to replace ActiveDirectoryMembershipProvider and
SqlMembershipProvider.

SimpleMembershipProvider. This is a new generation of membership providers


o that works with the SQL Server, SQL Server Compact Edition, Windows
Azure SQL Database, and other versions of SQL Server.
SimpleMembershipProvider requires only three key parameters—table name,
user ID, and user name. You use this provider to implement authentication that
works with any SQL Server database table schema.
UniversalProviders. This is a set of membership providers that works with any
database that Entity Framework supports. However, these providers work only
o with the database schema designed by Microsoft. While initializing a universal
provider, if the schema does not exist in the database, the provider generates
the schema.

Question: What is the benefit of using SimpleMembershipProvider?

Claims-Based Authentication

Claims-based authentication is a model that facilitates single sign-on. Single


sign-on is a feature that allows you to receive a claim when you log on to a
centralized authentication system.

The claim is a ticket that authentication systems use to authenticate user logons.
The claim contains user identity information that helps authentication systems
identify users. With claims-based authentication systems, you can focus efforts
on developing business functions, rather than worrying about authenticating
users.

Claims-based authentication facilitates:

o Authenticating users to access applications.


o Storing user account information and passwords.
o Checking enterprise directories for user information.
Integrating the application with the identity systems of other platforms or
o
companies.

To implement claims-based authentication in your web application, you need to


use Windows Identity Foundation (WIF) 4.5. WIF 4.5.is a set of .NET
Framework classes that helps read information from the claims in a web
application.

The following steps describe the functioning of claims-based authentication


systems:

When an unauthenticated user requests a webpage, the request is redirected to


1.
the Identity Provider (IP) pages.
2. The IP requires you to enter credentials such as the user name and password.
After you enter the credentials, the IP issues a token. Then, the token is
3.
returned to the web browser.
The web browser is redirected to the webpage that you originally requested.
WIF determines if the token satisfies the requirements to access the webpage.
4. If the token satisfies all requirements, a cookie is issued to establish a session.
This cookie ensures that the authentication process occurs only once. Then, the
authentication control is passed on to the application.

Question: What are the benefits of using claims-based authentication?

Federated Authentication
Federations rely on claims-based authentication to allow external parties such as
trusted companies to access their applications.

Federations use the WS-Federations claim standard to enable the exchange of


claims between two parties in a standardized manner.

WIF provides support for federations by using the


WSFederationAuthenticationModule HTTP module.
WSFederationAuthenticationModule enables you to implement support for
federations in your ASP.NET 4.5 application, without implementing individual
logic.

Federated authentication enables Security Token Service (STS) to:

o Process the claims from business partners.


o Extract user information from the claims.

STS enables you to focus more on writing the business logic. It eliminates the
need to manage the authentication information of business partners, in your web
application.

Configuring the WSFederationAuthenticationModule helps specify the STS to


which non-authenticated requests should be redirected. WIF provides two
methods of federated authentication—FederatedPassiveSignIn and Passive
Redirect.
FederatedPassiveSignIn Control

Consider cases when unauthenticated users try to access protected resources and
you want to redirect these users to a logon page. For such cases, you can embed
the FederatedPassiveSignIn control in the logon page of your web application,
to redirect unauthenticated users to the logon page. The FederatedPassiveSignIn
control is configured with issuer (STS) information.

You can use the FederatedPassiveSignIn control to:

o Exclude application-wide protection.


o Include a logon page with clickable controls.

Passive Redirect

Consider cases when unauthenticated users try to access a protected resource, and
you want to redirect these users to an STS without using an application logon
page. For such cases, you can use passive redirect.

Passive redirect enables STS to:

o Verify the identity of the unauthenticated users.


o Issue security tokens that contain the appropriate claims for users.

Passive redirect requires you to add WSFederationAuthenticationModule in


the pipeline of the Hypertext Transfer Protocol (HTTP) modules, to identify
unauthenticated user requests and redirect users to the STS you specify. Adding
WSFederationAuthenticationModule in the HTTP pipeline processes the claim
information before passing the claim to the ASP.NET 4.5 engine.

You can instantiate WSFederationAuthenticationModule and use it to trigger


the sign-on process. This functionality is similar to that of the
FederatedPassiveSignIn control; however, passive redirect implements this
sign-on functionality with minimum coding effort.

Question: What are the benefits of using federated authentication?


Restricting Access to Resources

You can restrict user access by implementing the Authorize attribute in a


controller, instead of using the Web.config file as you would use in an ASP.NET
WebForms application. The Web.config file requires physical files to exist, for
access control to work. You cannot use the Web.config file to restrict user access
because MVC applications route requests to actions, not pages.

The following code shows how to add the Authorize attribute to your controller
class.

Authorizing Action Methods

[Authorize()]

public ActionResult GetEmployee()

return View();

Observe the Authorize attribute in the code sample. If you specify this attribute,
ASP.NET 4.5 mandates that users should be authorized to access the view
returned by the code sample.
If you add the Authorize attribute at the class level, the attribute requires users to
log on before they can access anything in the controller class. To allow
anonymous users to access a specific portion of your class, you can use the
AllowAnonymous attribute.

The following code shows how to use the AllowAnonymous attribute.

Using the AllowAnonymous Attribute

[AllowAnonymous()]

public ActionResult Register()

return View();

Question: Why should you use the Authorize attribute, instead of the
Web.config file to control authorization of pages in your ASP.NET MVC
application?

Demonstration: How to Authorize Access to Controller


Actions
In this demonstration, you will see how to:

o Generate authentication for access to a controller action.


Handle unauthenticated requests for actions that require authentication by using
o
ASP.NET.

Demonstration Steps
On the DEBUG menu of the OperasWebSite - Microsoft Visual Studio
1.
window, click Start Debugging.
2. On the Operas I Have Seen page, click All Operas.
On the Index of Operas page, click the Create New link.
3.
Note: The Create an Opera page is displayed without logging on to the
application. This enables anonymous users to create new operas.
4. In the Windows Internet Explorer window, click the Close button.
In the Solution Explorer pane of the OperasWebSite - Microsoft Visual
5. Studio window, expand OperasWebSite, expand Controllers, and then click
OperaController.cs.
In the OperaController.cs code window, locate the following code.
6.
public ActionResult Create()

Place the mouse cursor before the located code, type the following code, and
then press Enter.
7.
[Authorize]

In the OperaController.cs code window, locate the following code.

[HttpPost]
8.

public ActionResult Create(Opera newOpera)

Place the mouse cursor before the located code, type the following code, and
then press Enter.
9.
[Authorize]

On the FILE menu of the OperasWebSite - Microsoft Visual Studio


10.
window, click Save All.
On the DEBUG menu of the OperasWebSite - Microsoft Visual Studio
11.
window, click Start Debugging.
12. On the Operas I Have Seen page, click All Operas.
On the Index of Operas page, click the Create New link.
13.
Note: The Login view is now displayed and this prevents anonymous users
from creating new operas.
14. On the Index of Operas page, click the Register link.
15. In the User name box of the Register page, type David Johnson.
In the Password box, type Pa$$w0rd, in the Confirm password box, type
16.
Pa$$w0rd, and then click Register.
17. On the Operas I Have Seen page, click All Operas.
On the Index of Operas page, click the Create New link.
18.
Note: The Add an Opera page is displayed because the request is
authenticated.
19. In the Windows Internet Explorer window, click the Close button.
In the OperasWebSite - Microsoft Visual Studio window, click the Close
20.
button.

Lesson 2: Assigning Roles and Membership


Roles and memberships complement authentication features, to help you control
all modes of access in web applications. To define access levels for different
types of users, you need to know how to implement roles and users. ASP.NET
4.5 provides role providers and membership providers to help you assign roles
and users. ASP.NET 4.5 also enables you to create custom role providers and
custom membership providers. These custom providers allow you to store role
and user information in data sources not supported by ASP.NET 4.5, such as a
FoxPro or Oracle database.

Lesson Objectives
After completing this lesson, you will be able to:

o Describe role providers in ASP.NET 4.5.


o Describe how to add user accounts to roles.
o Describe how to build custom role providers.
o Describe membership services.
o Describe how to build custom membership providers.
o Add code to an MVC 4 web application to help users reset their password.

Role Providers in ASP.NET 4.5

Role providers help develop applications by using a role-based security model.


Similar to membership providers, two types of role providers are available in
ASP.NET 4.5—ActiveDirectoryRoleProvider and SqlRoleProvider:

ActiveDirectoryRoleProvider. This provider class is defined in the


o System.Web.Security namespace, and the provider enables you to use Active
Directory as the management model for roles.
SqlRoleProvider. This provider class is defined in the System.Web.Security
namespace. The provider works with only a specific table schema in Microsoft
o
SQL Server. You can generate this schema by using the aspnet_regdb.exe
command.
WindowsTokenRoleProvider. This provider uses the Windows authentication
token to determine the role of users. Then, the provider checks if users belong
o
to any group stored in the Windows authentication token that was generated
when they first logged on. The format of the group name is Domain\Group.

ActiveDirectoryRoleProvider and SqlRoleProvider have restrictions such as


lack of support for non-SQL databases or developer-defined schema. Therefore,
Microsoft developed SimpleRoleProvider and UniversalProviders to replace
ActiveDirectoryRoleProvider and SqlRoleProvider. The following list
describes the SimpleRoleProvider and UniversalProviders:

SimpleRoleProvider. This is a new generation of role provider that works with


SQL Server, SQL Compact Editions, and others versions of SQL Server.
o
SimpleRoleProvider enables you to implement authorization based on the
table defined by application developers.
UniversalProviders. This is a database agnostic version that works with any
database that Entity Framework supports. However, the database schema is
o
determined by Microsoft. The provider usually generates tables during
initialization.

You can choose a role provider based on the membership provider that you
select. You can also mix role providers; for example, you can combine
SimpleMembershipProvider and UniversalRoleProvider. However, you
should avoid mixing role providers because the manner in which each provider
identifies users is different.

Question: What is the difference between SimpleRoleProvider and


SqlRoleProvider?

Adding User Accounts to Roles

When you use a database-based role provider, such as SimpleRoleProvider or


UniversalRoleProvider, you can load the initial data onto the database by
directly editing the table. You can also edit the table by using the
AddUsersToRoles function. To use the AddUsersToRoles function, you need to
implement the custom management tool in your application. The custom
management tool helps call the AddUsersToRoles function, to add roles to a
database.

The following code shows how to use the

AddUsersToRoles function.

Using the AddUsersToRoles Function

AddUserToRoles("Peter", new string[] {"Admin","Staff"})

You can also use the AddUsersToRoles function in business applications to add
users to a role. However, you must ensure that the role to which you want to add
users exists, before using the AddUsersToRoles function. ASP.NET 4.0 and all
previous versions of ASP.NET include the Website Administration Tool
(WSAT). Unfortunately, WSAT does not work with the SimpleRoleProvider.

Question: Why should we not use WSAT while using SimpleRoleProvider?

Building a Custom Roles Provider

ASP.NET 4.5 allows you to build custom role providers. Custom role providers
enable you to implement role management that uses your own database schema
and logic. To build a custom role provider, you need to create a class that inherits
the RoleProvider class.

The following code shows how to build a custom role provider.

Creating a Custom Role Provider

public class CustomRoleProvider :

RoleProvider

In the RoleProvider class, you need to implement the GetRolesForUser


function. The GetRolesForUser function takes the user name as the input and
returns a list of roles to which the user belongs. You can write your own code to
obtain role information from the database or other back-end stores.

The following code shows how to use the GetRolesForUser method.

Implementing the GetRolesForUser Function

public override string[] GetRolesForUser(string username)

//code to return a list of roles for users

After implementing the GetRolesForUser function, you need to apply the


custom role provider to the application by modifying the Web.config file.

The following code shows how to apply the custom role provider to the
application.
Configuring a Site to Use a Custom Role Provider

<roleManager defaultProvider="CustomRoleProvider" enabled="true"

cacheRolesInCookie="false">

<providers>

<clear />

<add name="CustomRoleProvider" type="CustomRoleProvider” />

</providers>

</roleManager>

Question: Why should you create a custom role provider?

Providing Membership Services

You need to add the

SimpleMembershipProvider to the membership section of the Web.config file


to use it for membership services.

The following code shows how to add SimpleMembershipProvider to the


Web.config file.
Configuring the Simple Membership Provider

<membership

defaultProvider="SimpleMembershipProvider"

>

<providers>

<clear/>

<add name="SimpleMembershipProvider"

type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />

</providers>

</membership>

Next, you need to create a User table. If you do not have a User table created
already, you can modify the AccountModel.cs file, to generate the table. To view
the AccountModel.cs file, you should select the Internet Application template,
when you create the project.

In the following code sample, the UserProfile class from AccountModel.cs has
been modified to add an additional property, Country.

Creating a User Table

[Table("UserProfile")]

public class UserProfile

[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]

public int UserId { get; set; }

public string UserName { get; set; }

public string Country { get; set; }

After modifying the AccountModel.cs file, you need to call the


WebSecurity.InitializeDatabaseConnection function in the App.Start.cs file.
The WebSecurity.InitializeDatabaseConnection function ensures that
SimpleMembershipProvider is configured with connection strings to the
database.

The following code shows how the membership provider connects to the User
table, by using the DBConn connection string.

Connecting to the User Table

WebSecurity.InitializeDatabaseConnection(“DBConn”,”User”,”id”,”Username”,

false)

If a specific table does not exist in a database, the autoCreateTables parameter


helps indicate to the membership provider that it may create the table. To
initialize SimpleMembershipProvider, you need to add the
InitializeSimpleMembership attribute to the AccountController class.

The following code shows how to add the InitializeSimpleMembership


attribute to the AccountController class.

Adding the InitializeSimpleMembership Attribute

[Authorize]
[InitializeSimpleMembership]

public class AccountController : Controller

Question: Why should we use the InitializeDatabaseConnection method?

Building a Custom Membership Provider

If you need to add functionality to a membership provider, such as custom logic


for authentication, you need to implement a custom membership provider.

The following code shows how to implement a custom membership provider.

A Custom Membership Provider

public class CustomMembershipProvider :

SimpleMembershipProvider

}
After implementing the custom membership provider, you override the
ValidateUser method defined in SimpleMembershipProvider. The following
code shows how to override the ValidateUser method defined in
SimpleMembershipProvider.

Overriding the ValidateUser Method

public override bool ValidateUser(string username, string password)

In the preceding code sample, the ValidateUser method validates the user name
and password against the membership store.

Perhaps, you want to add logic to get the decryption key for passwords. To add
this logic, you can override the Provider constructor, when the custom
membership provider is initializing. Overriding the Provider constructor
initializes the encryption engine.

Overriding the Provider Constructor

public CustomAdminMembershipProvider(SimpleSecurityContext

simpleSecurityContext)

After adding logic to the custom membership provider, you need to modify the
Web.config file to apply the custom provider class to the application.

Adding a Custom Provider to Web.config

<membership defaultProvider="CustomMemberProvider">
<providers>

<clear/>

<add name="CustomMemberProvider" type="

CustomAdminMembershipProvider " />

</providers>

</membership>

Question: Why should you implement a custom membership provider?

Demonstration: How to Reset a Password


In this demonstration, you will see how to write code that uses a Membership
Services Provider to reset the user’s password. Using this code, you can enable
users to control their own passwords and reset the password without involving a
site administrator.

Demonstration Steps
In the Solution Explorer pane of the OperasWebSite - Microsoft Visual
1.
Studio window, under Controllers, click AccountController.cs.
In the AccountController.cs code window, locate the following comment.
2.
//Add Reset Password Code Here

In the AccountController.cs code window, replace the located comment with


the following code, and then press Enter.
3.
try
{

catch (Exception)

In the try code block, type the following code.

changePasswordSucceeded =
4. Membership.Provider.ChangePassword(User.Identity.Name,

model.OldPassword, model.NewPassword);

In the catch code block, type the following code.


5.
changePasswordSucceeded = false;

On the FILE menu of the OperasWebSite - Microsoft Visual Studio


6.
window, click Save All.
On the DEBUG menu of the OperasWebSite - Microsoft Visual Studio
7.
window, click Start Debugging.
8. On the Operas I Have Seen page, click the Log In link.
On the Logon page, in the User name box, type David Johnson, in the
9.
Password box, type Pa$$w0rd, and then click Log in.
10. On the Operas I Have Seen page, click the Reset Password link.
On the ResetPassword page, in the Current password box, type Pa$$w0rd,
11.
and then in the New password box, type Pa$$w0rd2.
In the Confirm new password box, type Pa$$w0rd2, and then click Change
12. Password.
Note: On the ResetPassword page, the message, “Your password has been
changed.” is displayed.
13. In the Windows Internet Explorer window, click the Close button.
In the OperasWebSite – Microsoft Visual Studio window, click the Close
14.
button.
15. If the Microsoft Visual Studio warning message appears, click Yes.

Lab: Controlling Access to ASP.NET MVC 4 Web


Applications
Scenario

A large part of the functionality for your proposed Photo Sharing application is in
place. However, stakeholders are concerned about security because there are no
restrictions on the tasks that users can complete. The following restrictions are
required:

o Only site members should be able to add or delete photos.


o Only site members should be able to add or delete comments.

You have been asked to resolve these concerns by creating a membership system
for the Photo Sharing application. Visitors should be able to register as users of
the web application and create user accounts for themselves. After registration,
when the users log on to the application, they will have access to actions such as
adding and deleting photos and comments. Anonymous users will not have
access to perform these actions. Additionally, registered users should also be able
to reset their own password.

Objectives

After completing this lab, you will be able to:

Configure a web application to use ASP.NET Form Authentication with


o
accounts stored in Windows Azure SQL database.
o Write models, controllers, and views to authenticate users in a web application.
o Provide access to resources in a web application.
o Enable users to reset their own password.

Lab Setup

Estimated Time: 90 minutes

Virtual Machine: 20486B-SEA-DEV11

User name: Admin

Password: Pa$$w0rd

Note: In Hyper-V Manager, start the MSL-TMG1 virtual machine if it is not


already running.

Before starting the lab, you need to enable the Allow NuGet to download
missing packages during build option, by performing the following steps:

On the TOOLS menu of the Microsoft Visual Studio window, click


o i. Options.
ii. In the navigation pane of the Options dialog box, click Package Manager.
Under the Package Restore section, select the Allow NuGet to download
iii.
missing packages during build checkbox, and then click OK.
After completing the lab, take a Snapshot of the 20486B-SEA-DEV11 virtual
o machine. Ensure that this Snapshot is applied before initiating the lab in
Module 13.

Exercise 1: Configuring Authentication and Membership


Providers

Scenario

You want to use a Windows Azure SQL database to store user accounts and
membership information.
In this exercise, you will:

o Create a Windows Azure SQL database.


o Configure a provider to connect to the database.

The main tasks for this exercise are as follows:

1. Configure a new Windows Azure SQL database.


2. Install universal providers.
3. Configure providers in Web.config.

Task 1: Configure a new Windows Azure SQL database.

Start the virtual machine, and log on with the following credentials:

1. o Virtual Machine: 20486B-SEA-DEV11


o User name: Admin
o Password: Pa$$w0rd
Log on to the Windows Azure portal by using the following information:

2. o Portal address: http://manage.windowsazure.com


o User name: <username>
o Password: <password>
Create a new database server and a new custom database by using the
following information:

o Database name: PhotoAppServices


3. o Database server: New SQL Database Server
o Logon name: <your first name>
o Logon password: Pa$$w0rd
o Logon password confirmation: Pa$$w0rd
o Region: <a region close to you>
In the list of allowed IP addresses for the PhotoAppServices database, add the
following IP address ranges:

4. o Rule name: First Address Range


o Start IP address: <first address in range>
o End IP address: <last address in range>

Task 2: Install universal providers.

Open the PhotoSharingApplication.sln file from the following location:

1. File location: Allfiles (D):\Labfiles\Mod11\Starter


o
\PhotoSharingApplication
Install the Microsoft ASP.NET Universal Providers package in the
2.
PhotoSharingApplication project by using the NuGet Package Manager.

Task 3: Configure providers in Web.config.

Remove the connection string named DefaultConnection from the top-level


1.
Web.config file.
Obtain the connection string for the PhotoAppServices database and add it to
2.
the Web.config file.
Configure the web application to use Forms authentication in Web.config, by
using the following information:

3. o Parent element: <system.web>


o Element: <authentication>
o Mode: Forms
Configure the logon page for the web application by using the following
information:
4.
o Parent element: <authentication>
o Element: <forms>
o Logon URL: ~/Account/Login
o Timeout: 2880
Configure the default profile provider to use the connection string named
5.
PhotoAppServices.
Configure the Default Membership Provider to use the connection string
6.
named PhotoAppServices.
Configure the Default Role Provider to use the connection string named
7.
PhotoAppServices.
Configure the Default Session Provider to use the connection string named
8.
PhotoAppServices.
9. Save all the changes.

Results: At the end of this exercise, you will have created a Photo Sharing
application that is configured to use Windows Azure SQL database for user
accounts and membership information. In subsequent exercises, you will add
model classes, actions, and views to implement authentication for this database.

Exercise 2: Building the Logon and Register Views

Scenario

You have configured the Photo Sharing application to connect to Windows


Azure SQL database for authentication and membership services. However, to
use forms authentication in an MVC application, you need to build model
classes, controllers, and views that enable users to log on, log off, and register for
an account.

In this exercise, you will:

o Add model classes.


o Add controllers.
o Import logon and register views.
o Test the developed components.
The main tasks for this exercise are as follows:

1. Add account model classes.


2. Add an account controller.
3. Import Logon and Register views.
4. Add authentication controls to the Template view.
5. Test registration, log on, and log off.

Task 1: Add account model classes.


1. Add a new Class file named AccountModelClasses.cs to the Models folder.
Add references to the following namespaces, to the new class file:

2. o System.ComponentModel.DataAnnotations

o System.Data.Entity
Remove the AccountModelClasses class and add a new class by using the
following information:

3. o Scope: Public
o Name: UsersContext
o Inherit: DbContext
In the UsersContext class, create a constructor that passes the
4.
PhotoAppServices connection string to the base class constructor.
In the AccountModelClasses.cs code file, add a new public class named
5.
Login.
Add a new property to the Login class by using the following information:

o Scope: public
o Type: string
6. o Name: UserName

o Access: Read/Write
o Display name: User name
o Use the Required annotation.
Add a new property to the Login class by using the following information:

o Scope: public
o Type: string
7. o Name: Password

o Access: Read/Write
o Data type: Password
o Use the Required annotation.
Add a new property to the Login class by using the following information:

o Scope: public
8. o Type: bool
o Name: RememberMe
o Access: Read/Write
o Display name: Remember me?
In the AccountModelClasses.cs code file, add a new public class named
9.
Register.
Add a new property to the Register class by using the following information:

o Scope: public
o Type: string
10. o Name: UserName
o Access: Read/Write
o Display name: User name
o Use the Required annotation.
Add a new property to the Register class by using the following information:

o Scope: public
11. o Type: string
o Name: Password
o Access: Read/Write
o Data type: Password
o Use the Required annotation.
Add a new property to the Register class by using the following information:

o Scope: public
o Type: string
o Name: ConfirmPassword
12.
o Access: Read/Write
o Data type: Password
o Display name: Confirm password
Ensure that this property matches the Password property by using the
o
Compare annotation.
13. Save all the changes.

Task 2: Add an account controller.

Add a new controller named AccountController to the MVC web


1.
application by using the Empty MVC controller template.
Delete the default Index action from the AccountController file and add
using statement references for the following namespaces:
2.
o System.Web.Security
o PhotoSharingApplication.Models
Create a new action method in the AccountController class by using the
following information:

3. o Scope: public
o Return type: ActionResult
o Name: Login
o Parameter: a string named returnUrl
In the Login action, store the returnUrl value in the ViewBag collection,
4.
and then return a view named Login.
Create a new action method in the AccountController class by using the
following information:

o HTTP verb: POST


5. o Scope: public
o Return type: ActionResult
o Name: Login
o Parameters: a Login object named model and a string named returnUrl
Within the Login action method code block for the HTTP POST verb, check
6.
if the ModelState is valid.
Add an if…else statement to check the user’s credentials by using the
following information:

7. o Method: Membership.ValidateUser
o User name: model.UserName
o Password: model.Password
If the user’s credentials are correct, authenticate the user by using the
following information:

8. o Method: FormsAuthentication.SetAuthCookie
o User name: model.UserName
o Create persistent cookie: model.RememberMe
If returnUrl is a local URL, redirect the user to the returnUrl. Otherwise,
9.
redirect the user to the Index action of the Home controller.
If the user’s credentials are incorrect, add a model error to the ModelState
object by using the following information:
10.
o Key: An empty string
o Error message: The username or password is incorrect
If the ModelState is not valid, return the current view and pass the model
11.
object so that the user can correct errors.
Create a new action method in the AccountController class by using the
following information:

12. o Scope: public


o Return type: ActionResult
o Name: LogOff
o Parameters: None
In the LogOff action, log off the user, and then redirect to the Index action of
13.
the Home controller by using the FormsAuthentication.SignOut() method.
Create a new action method in the AccountController class by using the
following information:

14. o Scope: public


o Return type: ActionResult
o Name: Register
o Parameters: None
15. In the Register action, return the Register view.
Create a new action method in the AccountController class by using the
following information:

o HTTP verb: POST


16. o Scope: public
o Return type: ActionResult
o Name: Register
o Parameter: a Register object named model.
Within the Register action method code block for the HTTP POST verb,
17.
check if the ModelState is valid.
If the ModelState is valid, create a try…catch block that catches exceptions
18.
of the type MembershipCreateUserException e.
In the try block, create a new user with the right user name and password by
19. using the Membership.CreateUser method. Store the result in a
MembershipUser object named NewUser.
Authenticate the new user and redirect the browser to the Index action of the
20.
Home controller.
In the catch block, add a model error to the ModelState object by using the
following information:
21.
o Key: Registration Error
o Error message: Report the error status code as a string
If the ModelState is not valid, return the current view and pass the model
22.
object so that the user can correct errors.
23. Save all the changes.

Task 3: Import Logon and Register views.

1. Add a new folder named Account to the Views folder.


Add the Login.cshtml file to the Account folder from the following location:
2.
o File location: Allfiles (D):\Labfiles\Mod11\Account Views
Add the Register.cshtml file to the Account folder from the following
location:
3.
o File location: Allfiles (D):\Labfiles\Mod11\Account Views

Task 4: Add authentication controls to the Template view.

1. Open the _MainLayout.cshtml page for editing.


Immediately before the DIV element with clear-floats class, insert a DIV
2.
element with login-controls class.
In the new DIV element, write a Razor if… else code block that checks
3.
whether the current request is from an authenticated user.
If the request is from an authenticated user, render a greeting message that
4.
includes the authenticated user’s name.
After the greeting message, render a link to the LogOff action by using the
following information:

5. o Helper: Html.ActionLink()
o Link text: Log Off
o Action name: LogOff
o Controller name: Account
If the request is from an anonymous user, render a link to the Login action by
using the following Information:

6. o Helper: Html.ActionLink()
o Link text: Log In
o Action name: Login
o Controller name: Account
After the Log In link, render a link to the Register action by using the
following Information:

7. o Helper: Html.ActionLink()
o Link text: Register
o Action name: Register
o Controller name: Account
8. Save all the changes.

Task 5: Test registration, log on, and log off.

Start the web application in debugging mode and register a user account by
using the following information:
1.
o User name: David Johnson
o Password: Pa$$w0rd
2. Log off and then log on with the credentials you just created.
3. Stop debugging.
Results: At the end of this exercise, you will create a Photo Sharing application
in which users can register for an account, log on, and log off.

Exercise 3: Authorizing Access to Resources

Scenario

Now that you have enabled and tested authentication, you can authorize access to
resources for both anonymous and authenticated users.

You should ensure that:

o Only site members can add or delete photos.


o Only site members can add or delete comments.
o The account controller actions are authorized properly.
Only authenticated users see the_Create view for comments in the Display
o
view.

The main tasks for this exercise are as follows:

1. Restrict access to Photo actions.


2. Restrict access to the Comment actions.
3. Restrict access to the Account actions.
4. Check authentication status in a view.
5. Test authorization.

Task 1: Restrict access to Photo actions.


In the PhotoController.cs file, add the [Authorize] annotation to ensure that
1.
only authenticated users can access the Create action for the GET requests.
Add the [Authorize] annotation to ensure that only authenticated users can
2.
access the Create action for the HTTP POST verb.
Add the [Authorize] annotation to ensure that only authenticated users can
3.
access the Delete action.
Add the [Authorize] annotation to ensure that only authenticated users can
4.
access the DeleteConfirmed action for the HTTP POST verb.
5. Save all the changes.

Task 2: Restrict access to the Comment actions.

In the CommentController.cs file, add the [Authorize] annotation to ensure


1.
that only authenticated users can access the _Create action.
Add the [Authorize] annotation to ensure that only authenticated users can
2.
access the Delete action.
Add the [Authorize] annotation to ensure that only authenticated users can
3.
access the DeleteConfirmed action for the HTTP POST verb.
4. Save all the changes.

Task 3: Restrict access to the Account actions.

In the AccountController.cs file, add the [Authorize] annotation to ensure


1.
that only authenticated users can access all actions by default.
Add the [AllowAnonymous] annotation to ensure that anonymous users can
2.
access the Login action.
Add the [AllowAnonymous] annotation to ensure that anonymous users can
3.
access the Login action for the HTTP POST verb.
Add the [AllowAnonymous] annotation to ensure that anonymous users can
4.
access the Register action.
Add the [AllowAnonymous] annotation to ensure that anonymous users can
5.
access the Register action for the HTTP POST verb.
6. Save all the changes.

Task 4: Check authentication status in a view.

1. Open the _CommentsForPhoto.cshtml partial view.


In the _CommentsForPhoto.cshtml partial view, add an if statement to
2. ensure that the _Create partial view is only displayed if the request is
authenticated.
If the request is not authenticated, render a link to the Login action of the
3.
Account controller to display the text To comment you must log in.
4. Save all the changes.

Task 5: Test authorization.

Start the web application in debugging mode and then attempt to add a new
1.
photo to the web application, without logging on to the application.
Without logging on to the application, view any photo in the application and
2.
attempt to add a comment.
Log on to the web application by using the following credentials:

3. o User name: David Johnson


o Password: Pa$$w0rd
Add a comment of your choice to the photo by using the following
information:
4.
o Subject: Authenticated Test Comment
5. Stop debugging.

Results: At the end of this exercise, you will have authorized anonymous and
authenticated users to access resources in your web application.

Exercise 4: Optional—Building a Password Reset View

Scenario

Site visitors can now register as users of the Photo Sharing application and log on
to the site so that they can add photos and comments. However, they do not have
the facility to change their password. In this exercise, you will create a password
reset page by using the membership services provider.
Complete this exercise if time permits.

The main tasks for this exercise are as follows:

1. Add a local password model class.


2. Add reset password actions.
3. Import the reset password view.
4. Add a link to the reset password view.
5. Test password reset.

Task 1: Add a local password model class.

Add a new class to the AccountModelClasses.cs file by using the following


information:
1.
o Scope: public
o Name of the class: LocalPassword
Add a new property to the LocalPassword class by using the following
information:

o Scope: public
o Type: string
2. o Name: OldPassword
o Access: Read/Write
o Data type: Password
o Annotation: [Required]
o Display name: Current password
Add a new property to the LocalPassword class by using the following
information:

3. o Scope: public
o Type: string
o Name: NewPassword
o Access: Read/Write
o Data type: Password
o Annotation: [Required]
o Display name: New password
Add a new property to the LocalPassword class by using the following
information:

o Scope: public
o Type: string
4. o Name: ConfirmPassword
o Access: Read/Write
o Data type: Password
o Display name: Confirm new password
Use the Compare annotation to ensure this property matches the
o
NewPassword property.
5. Save all the changes.

Task 2: Add reset password actions.

In the AccountController class, add a new enumeration by using the


following information:

1. o Scope: public
o Name: ManageMessageId
o Values: ChangePasswordSuccess, SetPasswordSuccess
Add a new action to the AccountController class by using the following
information:

2. o Scope: public
o Return type: ActionResult
o Name: ResetPassword
o Parameters: an optional ManageMessageId object named message
If the message parameter is not null, set the ViewBag.StatusMessage
3.
property to Your password has been changed.
Set the ViewBag.ReturnUrl property to the URL of the ResetPassword
4.
action.
5. Return a view named ResetPassword.
Add a new action to the AccountController class by using the following
information:

o Annotation: HttpPost
6. o Scope: public
o Return type: ActionResult
o Name: ResetPassword
o Parameter: a LocalPassword object named model
In the new ResetPassword action for the HTTP POST verb, set the
7.
ViewBag.ReturnUrl property to the URL of the ResetPassword action.
8. Include an if statement to check whether the ModelState is valid.
If the ModelState is valid, create a new Boolean variable named
9. changePasswordSucceeded, and then add a try… catch block that catches
all exceptions.
In the try block, change the user’s password by using the following
information:

o Method: Membership.Provider.ChangePassword
10. o User name: User.Identity.Name
o Old password: model.OldPassword
o New password: model.NewPassword
o Store the result in changePasswordSucceeded
11. In the catch block, set the changePasswordSucceeded variable to false.
After the try…catch code block, if changePasswordSucceeded is true,
redirect to the ResetPassword action and pass the
12.
ManageMessageId.ChangePasswordSucccess value to the message
parameter.
If changePasswordSucceeded is false, add a model error to the ModelState
object by using the following information:

13. o Key: An empty string

Message: The current password is incorrect or the new password is


o
invalid
If the ModelState is not valid, return the current view and pass the model
14.
object so that the errors can be corrected.
15. Save all the changes.

Task 3: Import the reset password view.

Add the ResetPassword.cshtml file to the Views/Account folder from the


following location:
1.
o Allfiles (D):\Labfiles\Mod11\Account Views

Task 4: Add a link to the reset password view.

Add a new link to the _MainLayout.cshmtl template view by using the


following information:

1. o Position: After the link to the LogOff action


o Text: Reset
o Action: ResetPassword
o Controller: Account
2. Save all the changes.

Task 5: Test password reset.

Start the web application in debugging mode, and then log on with the
1. following credentials:
o User name: David Johnson
o Password: Pa$$w0rd
2. Change the password from Pa$$w0rd to Pa$$w0rd2.
3. Stop debugging and close the open windows.

Results: At the end of this exercise, you will build a Photo Sharing application in
which registered users can reset their own password.

Question: In Exercise 3, when you tried to add a photo before logging on to the
application, why did ASP.NET display the Login view?

Question: How can you ensure that only Adventure Works employees are
granted access to the Delete action of the Photo controller?

Module Review and Takeaways


In this module, you discussed the various membership and role providers in
ASP.NET 4.5. You compared the benefits of using SimpleProviders and
UniversalProviders with the benefits of using other providers, for database-
centric applications. However, for applications that need to use Windows for
authentication and authorization, you can use the existing role and membership
providers. You also viewed how to implement custom providers, to add
functionalities such as password encryption to your web application.

Review Question(s)

Question: What is the key difference between implementing authentication and


authorization in ASP.NET 4.5 from implementing the same in the previous
versions of ASP.NET?

Real-world Issues and Scenarios

When you create web applications, you may need to create custom providers
because you do not want to use the schema provided by Microsoft. However, you
can use SimpleProviders to remove the need to develop custom providers and
reduce the effort required for building applications.

 Module 12:
Aspecto destacadoNotaExpandir aspecto destacadoExpandir nota

Building a Resilient ASP.NET MVC 4 Web


Application
Contents:
Module Overview

Lesson Developing Secure Sites


1:

Lesson State Management


2:

Lab: Building a Resilient ASP.NET MVC 4 Web Application

Module Review and Takeaways

Module Overview
Security is always the top priority for web applications, because publicly
accessible web applications are usually the targets of different types of web
attacks. Hackers use web attacks to access sensitive information. To help prevent
these attacks, you need to know how to use AntiXSS and request validation for
your web application. Using various security mechanisms, you can build a secure
web application. Another problem that developers usually face is the need to
retain information amongst multiple postbacks. You need to know how to use
state management techniques to retain information for multiple HTTP requests.
Using state management, you can help reduce the need for users to re-enter
information every time they need to place a request.

Objectives

After completing this module, you will be able to:

o Develop secure sites.


o Implement state management.

Lesson 1 : Developing Secure Sites


Web applications are often subject to security attacks. These attacks prevent the
applications from functioning properly, and the attackers try to access sensitive
information stored in the underlying data store. ASP.NET provides built-in
protection mechanisms that help prevent such attacks. However, such
mechanisms also tend to affect the operation of your applications. You should
know when to enable or disable the protection mechanisms to avoid any impact
on the functionalities of your application. You also need to know how to use
Secure Sockets Layer (SSL) to prevent unauthorized access to information during
information transmission.

Lesson Objectives
After completing this lesson, you will be able to:

o Describe how to avoid malicious attacks that use cross-site scripting.


o Describe the common attack techniques used by malicious users.
o Describe how to disable attack protection in your MVC application.
o Decide whether to disable attack protection in various scenarios.
o Describe the role of Secure Sockets Layer in helping secure web applications.

Cross-Site Scripting

Cross-site scripting involves the malicious insertion of scripts in a user session.


Cross-site scripting poses information to other websites, by using the
authentication information of users, without their knowledge. For example,
consider the code inserted into a web application to maliciously post messages on
social networking websites, without the knowledge of the users.

When a script is inserted into a web application, the script has full access to the
Document Object Model (DOM) of the HTML. This access allows the attacker to
create fake input boxes in the

application, create fake users, and post fake information on the web application.

The cross-site scripting attack usually takes input from improperly escaped
output. These scripting attacks usually impact query strings. For example,
consider the following URL:

http://localhost/Default1/?msg=Hello

The following code shows how to access the msg querystring parameter from a
controller action.
Accessing a Query String Parameter

public ActionResult Index(string msg)

ViewBag.Msg = msg;

return View();

The following code shows how to display the value of the querystring parameter
in a view.

Displaying the Query String Parameter

<div class="messages">@ViewBag.Msg<div>

After running the preceding code samples, the application should display the
resultant word, Hello. Now, consider a scenario where the query string parameter
msg is changed to a less benign value resulting in the following URL:

http://localhost/Default1/?msg=<script>alert('pwnd')</script>

As a result, the script block included in the query string is displayed to users. In
such cases, attackers can inject malicious code into your app by using the value
of a query string parameter.

ASP.NET includes request validation, to help protect the input values that are
subject to cross-site scripting attacks. However, attackers can bypass this
mechanism by using encoding to subvert common cross-site scripting filters. For
example, here is the same query string, this time encoded:

http://localhost/Default1/?msg=Jon\x3cscript\x3e%20alert(\x27pwnd\x27)%20\x
3c/script\x3e
You can modify the view class to use the @Ajax.JavaScriptStringEncode
function to help prevent cross-site scripting attacks, instead of directly using the
input from query strings. The following line of code shows how to use the
@Ajax.JavaScriptStringEncode function.

Using the JavaScriptStringEncode Function

<div class="messages">@Ajax.JavaScriptStringEncode(ViewBag.Msg)<div>

You can also import the AntiXSS library to check the query string content for
possible attacks. The AntiXSS library is part of the Web Protection Library,
which was developed by Microsoft to detect more complex web attacks than
those that the request validation of ASP.NET can detect.

Additional Reading: To view more information on the AntiXSS library, go to


http://go.microsoft.com/fwlink/?LinkID=293690&clcid=0x409

After importing the AntiXSS library in your MVC application, you can use the
library to encode any output content in HTML.

The following code shows how to use the AntiXSS library.

Using the AntiXSS Library

@using Microsoft.Security.Application

<div class="messages">@Encoder.JavaScriptEncode(ViewBag.Msg)<div>

The code in the preceding sample illustrates how to encode input values by using
the JavaScriptEncode method of the AntiXSS library, when displaying output in
HTML. This practice ensures that the input values are safe for display.

Question: What causes cross-site scripting attacks?

Other Attack Techniques


In addition to cross-site scripting attacks, hackers can use other types of attacks,
including cross-site request forgery and SQL injection attacks to subvert web
applications.

Cross-Site Request Forgery

Cross-site request forgery (CSRF) is an attack that occurs when you open a URL
in a web browser, by using your user context, without knowing that you are
allowing attackers to make changes to your system. For example, consider that
your application uses query strings to pass information

to other applications. You receive an email message with a link such as the
following:

<a href="http://localhost/Default1/?id=100">Click Me</a>

When you click the link, the action associated with the view runs on your web
browser. Because, you are an authenticated user in the application, the attacker
can now access your system.

You can prevent CSRF by using the following rules:

Ensure that a GET request does not replay by clicking a link. The HTTP
1. specifications for GET requests imply that GET requests should be used only
for retrieval and not for state modifications.
Ensure that a request does not replay if an attacker uses JavaScript to simulate
2.
a form POST request.
Prevent any data modifications that use the GET request. These modifications
should require some user interaction. This practice of introducing user
3. interaction does not help prevent form-based attacks. However, user
interaction limits several types of easier attacks, such as malicious links
embedded in XSS-compromised sites.

The @Html.AntiForgeryToken() function helps protect your system from


CSRF by using unique tokens that are passed to the application along with
requests. The @Html.AntiForgeryToken() function uses not only a hidden form
field but also a cookie value, making it more difficult to forge a request.

The following code shows how to use the @Html.AntiForgeryToken() function


in a view.

Using an Anti-Forgery Token

@using (Html.BeginForm())

@Html.AntiForgeryToken();

@Html.EditorForModel();

<input type="submit" value="Submit" />

The following code shows how to force Anti-Forgery token checking in a


controller by using the ValidateAntiForgeryToken attribute.

Forcing Anti-Forgery Token Checking

[HttpPost]
[ValidateAntiForgeryToken()]

public ActionResult Index(User user)

Return View();

Note the ValidateAntiForgeryToken() attribute in the preceding code sample.


This attribute enables the controller to check if the user input from the HTML
form includes the token generated by the @Html.AntiForgeryToken(), before
accepting a request.

SQL Injection Attack

SQL injection attacks are similar to cross-site scripting attacks. However, the
difference is that the user input is used to create dynamic SQL, instead of HTML.
Observe the following line of code.

cmd.CommandText = "select userID from Users where userID = '" +

Request.QueryString["user"] + "'";

Consider a scenario where an attacker modifies the query string as displayed in


the following line of code.

user=1' AND 1=1 GO SELECT * from Users WHERE NOT 0='

The following line of code denotes the resultant SQL.

select userID from Users where userID = '1' AND 1=1 GO SELECT * from

Users WHERE NOT

0=''
In this case, SQL returns everything from the Users table.

To prevent SQL injection attacks, you should:

1. Validate user input.


2. Avoid using string concatenations to create dynamic SQL.
3. Use parameterized commands with dynamic SQL.
4. Store all sensitive and confidential information in encrypted formats.
Ensure that the application does not use or access the database with
5.
administrator privileges.

Question: What is the best way to prevent SQL injection attacks if you cannot
avoid dynamic SQL?

Disabling Attack Protection

Request validation is an ASP.NET feature that examines an HTTP request and


determines if it contains potentially dangerous content.

Potentially dangerous content can include any HTML markup or JavaScript code
in the body, header, query string, or cookies of the request.

However, request validation can also cause the application to function


improperly by preventing some input from entering the application page for
processing. Consider a situation in which your application uses an HTML editor
to generate HTML code for user input, before saving the input
on the database. In this case, you may want to disable the request validation to
allow the HTML editor to function properly.

You can choose to disable request validation at different levels, such as, in the
Web.config file, on a webpage, or in a specific HTML element.

The following code shows how to disable request validation for your application
in the Web.config file.

Disabling Request Validation

<system.web>

<httpRuntime requestValidationMode="2.0" />

</system.web>

The following code shows how to add the ValidateInput(false) attribute to the
controller, to disable request validation for an action in a controller.

Using the ValidateInput Attribute

[HttpPost]

[ValidateInput(false)]

public ActionResult Edit(string comment)

return View(comment);

The following code shows how to add the AllowHtml attribute to the Prop1
property of the model, to disable request validation for this property
Using the AllowHtml Attribute

[AllowHtml]

public string Prop1 { get; set; }

You should consider using attack protection techniques that:

o Have a minimum impact on the application.


o Involve minimum fields to accept HTML elements in the request validations.

Question: Describe a scenario when you would want to disable request


validation?

Secure Sockets Layer

Secure Sockets Layer (SSL) is an application layer protocol that helps:

o Encrypt content by using the public key infrastructure (PKI) keys.


o Protect the content that is transmitted between the server and client.
o Prevent unauthorized access of content during transmission.
o Reassure users that a site is genuine and certified.

You can use SSL on views that accept user input if the input includes sensitive
information, such as credit card information and passwords. Using SSL on such
crucial views ensures the confidentiality of the content and the authenticity of the
sender. However, you may not be able to analyze your code and easily detect if a
user accesses the web application by using SSL.

ASP.NET MVC 4 includes the RequireHttps attribute that enables you to use
SSL on the views that involve sensitive information. The RequireHttps attribute
redirects users to the SSL link, if they request a view by using normal HTTP.

The following code shows how to add the RequireHttps attribute in your
controller class and action methods to require a user to use the SSL protocol.

Using the RequireHttps Attribute

[RequireHttps]

public class Controller1

[RequireHttps]

public ActionResult Edit()

You can use the RequireHttps attribute at the controller level or action level.
This flexibility allows you to choose SSL when required in your web application.

Note that web servers require you to configure the PKI certificate so that the
server accepts SSL connections. SSL certificates need to be purchased from a
certificate authority (CA). During application development, you can use the self-
sign certificate to simplify the configuration process.
Question: What action is required to be performed on the web server, before
implementing SSL?

Lesson 2: State Management


While developing applications, you may want to create functions that require
information to be retained across requests. For example, consider an application
in which you need to first select a customer and then work on the order relevant
to the customer. HTTP is a stateless protocol. Therefore, ASP.NET includes
different state management techniques to help store information for multiple
HTTP requests. You need to know how to configure and scale state storage
mechanisms to support web server farms.

Lesson Objectives
After completing this lesson, you will be able to:

o Describe the benefits of storing state information.


o List the options for storing state information.
o Configure state storage.
o Describe the scalability of state storage mechanisms.
o Store and retrieve state information in an MVC 4 web application.

Why Store State Information?


HTTP is a stateless protocol that does not relate submitted requests to each other.
HTTP treats each request as a new request. However, this independence among
the requests affects business applications that have information dependencies
amongst functions. For example, consider that you can access the Update
Address function only after you provide the user logon information. The page
that handles the User Logon function is different from the page that handles the
Update Address function. Therefore, these functions require two separate HTTP

requests. With the default HTTP implementation, the server may lose the result
of the logon request, when a user accesses the Update Address page. ASP.NET
implements the session management technology to retain dependent information
for multiple HTTP requests.

Session management enables web applications to store values for multiple HTTP
requests, regardless of whether the request is directed to the same page or
multiple pages. The session management process involves two techniques—
server-side techniques and client-side techniques, to retain user information
pertinent to multiple HTTP requests.

Client-Side Session Management

Client-side session management technologies include:

o Hidden fields
o Cookies
o Query strings

Client-side session management technologies help retain dependent information


when a user triggers the HTTP POST action by clicking a button on a webpage.
Then, when a page is rendered, the server generates the dependent information.

Note: If you are familiar with ASP.NET Web Forms, you may have used View
State and Control State as client-side state storage. These techniques are not
available in MVC because they rely on Web Forms server controls.

Server-Side Session Management


Server-side options provide higher security for storing page information than the
client-side options because information retained by using client-side options is
not visible to the client system. However, server-side options require more web
server resources such as memory for storing data. This additional usage of
resources can lead to scalability issues if the size of the information to be stored
is large.

ASP.NET provides the following server-side session management options:

o Application state
o Session state
o TempData
o Profile properties
o Database support

Additional Reading: For more information about ASP.NET state management


recommendations, go to
http://go.microsoft.com/fwlink/?LinkID=288986&clcid=0x415

Question: Why do you need to implement session management?

State Storage Options

You can store values for requests, and the subsequent requests related to the
previous requests, by using the TempData object. By default, the TempData
object uses the Session variable to store information relevant to requests.
You can use the TempData object to access session information, instead of using
the Session variable. The TempData object includes logic to handle redirection
of information to different views.

You can use the sessionState element in the Web.config file, to define the
repository that

should retain the session state information. You can also use the sessionState
element to turn off session-state support. The following list describes some of the
commonly used session state storage options:

o The InProc mode. Stores the session in the ASP.NET process.


The StateServer mode. Stores session information in dedicated services running
o on the web server or on a dedicated server. It does not store information on
Internet Information Services (IIS).
o The SQLServer mode. Stores the session information in a SQL Server database.
o The Off mode. Deactivates the session state support in your application.

Question: Consider that you have a web server that contains multiple web
servers. You want to allow users to access the same state information for all the
web servers they access. In this case, which state storage mode should you used?

Configuring State Storage

You can configure state storage to use the StateServer and SQLServer modes.
The StateServer Mode

You need to run the ASP.NET state service on the server used for storing session
information, before using the StateServer mode. The ASP.NET state service is
installed as a service when ASP.NET and the .NET Framework are installed as
part of Microsoft .NET Framework. The ASP.NET service is installed at the
following location:

systemroot \Microsoft.NET\Framework\ versionNum

ber \aspnet_state.exe

To configure an ASP.NET application for using the StateServer mode, you


should perform the following steps:

In the Web.config file of the application, set the mode attribute of the
o
sessionState element to StateServer.
In the Web.config file of the application, set the stateConnectionString
o
attribute to tcpip=<serverName>:42424.

To configure StateServer support in your application, you should perform the


following steps:

1. Run the services.msc file.


Set the ASP.NET state service Startup Type attribute to automatic, and right-
2.
click the service.
Open the Web.config file, identify the sessionState element, and then update
3.
the code.

Consider that a session state is stored on the SampleStateServer remote


computer. The following code shows how to configure the StateServer mode.

Configuring the State Server Mode

<configuration>
<system.web>

<sessionState mode="StateServer"

stateConnectionString="tcpip=SampleStateServer:42424"

cookieless="false"

timeout="20"/>

</system.web>

</configuration>

Note: The objects stored in session state must be serializable, if the mode is set to
StateServer or SQLServer.

The SQLServer Mode

Before using the SQLServer mode, you need to install the ASP.NET session
state database on the SQL Server.. You can install the ASP.NET session state
database by using the aspnet_regsql.exe tool. To configure an ASP.NET
application for using the SQLServer mode, you should perform the following
steps:

In the Web.config file of the application, set the mode attribute of the
o
sessionState element to SQLServer.
In the Web.config file of the application, set the sqlConnectionString attribute
o
to a connection string for your SQL Server database.

To create the session state database on SQL Server, you should perform the
following steps:

1. Open the command prompt with administrative privileges.


From the <systemroot\Microsoft.NET\Framework\versionNumber> folder on
2.
your web server, run the Aspnet_regsql.exe tool.
Open the Web.config file, identify the sessionState element, and then update
3.
the code.

Consider that a session state is stored on the SampleSqlServer SQL Server. The
following code shows how to configure the SQLServer mode.

Configuring SQL Server Session State Storage

<configuration>

<system.web>

<sessionState mode="SQLServer"

sqlConnectionString="Integrated Security=SSPI;data

source=SampleSqlServer;" />

</system.web>

</configuration>

You can customize the behavior of the aspnet_regsql.exe tool by using switches
such as -E, -S, and -d. You can use these switches to change the name of the
default ASPState database.

Additional Reading: For more information about the aspnet_regsql.exe tool, go


to: http://go.microsoft.com/fwlink/?LinkID=293693&clcid=0x409

Question: Which tool should you install before using the SQLServer mode?

Scaling State Storage Mechanisms


The StateServer and SQLServer modes help access the state storage on a web
server. These modes allow multiple servers to access state storage information.
This process distributes the web workload among multiple web servers.

You can implement partitioning of session state to allow multiple state servers or
multiple SQL Server databases to handle session state information. You can
apply the logic for partitioning, by implementing the IPartitionResolver
interface in your application. You need to configure the Web.config file to
control the session

management engine. Configuring the session management engine helps you use
the logic to identify the appropriate web server on which you can store
information.

The following code shows how to configure the Web.config file, to enable the
IPartitionResolver interface.

Using the IPartitionResolver Interface

<configuration>

<system.web>

<sessionState

mode="SQLServer"
partitionResolverType=

"PartitionResolverClass" />

</system.web>

</configuration>

You can use the IPartitionResolver interface only when the session state uses
the SQLServer or StateServer modes. In the preceding code sample, note that no
connection string is specified by using the sqlConnectionString or
stateConnectionString attributes.

Additional Reading: For more details about implementing state partitioning, go


to: http://go.microsoft.com/fwlink/?LinkID=288988&clcid=0x417

Question: When should you implement the IPartitionResolver interface?

Demonstration: How to Store and Retrieve State


Information
In this demonstration, you will see how to:

o Store and retrieve user preferences from session state in controller actions.

Demonstration Steps
In the Solution Explorer pane of the OperasWebSite – Microsoft Visual
1. Studio window, under OperasWebSite, expand Controllers, and then click
HomeController.cs.
In the HomeController.cs code window, locate the following code.

public ActionResult About()


2.

{
return View();

Place the mouse cursor at the end of the located code, press Enter twice, and
then type the following code.

public ContentResult GetBackground()


3.
{

Place the mouse cursor within the GetBackground action code block, and
then type the following code.

string style;

if (Session["BackgroundColor"] != null)
4.
{

else

}
Place the mouse cursor within the if statement code block you just added, and
then type the following code.
5.
style = String.Format("background-color: {0};",

Session["BackgroundColor"])

Place the mouse cursor within the else statement code block you just added,
and then type the following code.
6.
style = "background-color: #dc9797;";
Place the mouse cursor at the end of the GetBackground action code block
and outside the if…else statements, press Enter, and then type the following
7. code.

return Content(style);

Place the mouse cursor outside any action code block but inside the
HomeController class, and then type the following code.

public ActionResult SetBackground(string color)


8.
{

Place the cursor within the SetBackground action code block, and then type
the following code.

9. Session["BackgroundColor"] = color;

return View("Index");

In the Solution Explorer pane, expand Views, expand Home, and then click
10.
Index.cshtml.
In the Index.cshtml code window, place the mouse cursor at the end of the P
element, press Enter twice, and then type the following code.

<p>
11.
Choose a background color:

</p>

Place the mouse cursor at the end of the text in the P element, press Enter,
12. and then type the following code.
@Html.ActionLink("Pink", "SetBackground", new { color = "#dc9797"})

Place the mouse cursor at the end of the link you just created, press Enter, and
then type the following code.
13.
@Html.ActionLink("Blue", "SetBackground", new { color = "#82bbf2"})

In the Solution Explorer pane, expand Shared, and then click


14.
_SiteTemplate.cshtml.
In the _SiteTemplate.cshtml code window, locate the following code.
15.
<body>

Replace the located code with the following code.


16.
<body style="@Html.Action("GetBackground", "Home")">

On the DEBUG menu of the OperasWebSite – Microsoft Visual Studio


17.
window, click Start Debugging.
On the Operas I Have Seen page, click the Blue link, and then note that the
18.
blue background color has been applied to the home page.
On the Operas I Have Seen page, click the All Operas link.
19.
Note: If the background color of the page is blue, click the Refresh button.
On the Index of Operas page, click the Details link corresponding to the title,
20.
Cosi Fan Tutte.
On the Cosi Fan Tutte page, note that the blue background color has been
applied to the page.
21.
Note: The blue background preference is applied to all pages of the
application.
22. On the Opera: Cosi Fan Tutte page, click Home.
On the Operas I Have Seen page, click the Pink link, and then note that the
23. pink background color has been applied to the home page.
Note: If the background color of the page is blue, click the Refresh button.
24. On the Operas I Have Seen page, click All Operas.
On the Index of Operas page, click the Details link corresponding to the title,
25.
Cosi Fan Tutte.
On the Cosi Fan Tutte page, note that the pink background color has been
applied to the page.
26.
Note: The pink background preference is applied to all pages of the
application.
27. In the Windows Internet Explorer window, click the Close button.
In the OperasWebSite – Microsoft Visual Studio window, click the Close
28.
button.
29. If the message Do you want to stop debugging? is displayed, click Yes.

Lab: Building a Resilient ASP.NET MVC 4 Web


Application
Scenario

The senior developer has asked you to implement the following functionality in
your Photo Sharing web application.

Any visitor of the application, including anonymous users, should be able to


o
mark a photograph as a favorite.
If a user has marked a favorite, a link should be available to display the favorite
o
photo.
o Favorite photos should be displayed in the slideshow view.

Objectives

After completing this lab, you will be able to:

o Store a setting for an anonymous or authenticated user in session state.


o Check a user preference when rendering an action link.
o Render a webpage by checking state values in the application.

Lab Setup

Estimated Time: 45 minutes

Virtual Machine: 20486B-SEA-DEV11

User name: Admin

Password: Pa$$w0rd

Note: In Hyper-V Manager, start the MSL-TMG1 virtual machine if it is not


already running.

Before starting the lab, you need to perform the following step:

Download Manage Nuget packages from the Project menu and note the
o
version number for the jquery.ui package.
Enable the Allow NuGet to download missing packages during build option,
by performing the following steps:

On the TOOLS menu of the Microsoft Visual Studio window, click


o i. Options.
ii. In the navigation pane of the Options dialog box, click Package Manager.
Under the Package Restore section, select the Allow NuGet to download
iii.
missing packages during build checkbox, and then click OK.

Exercise 1: Creating Favorites Controller Actions

Scenario

You have been asked to build functionality that stores the favorite photos of the
visitors in the session state of the web application. After users add photos to their
favorites, they will be able to view a slideshow of all the photos they selected as
favorites.
In this exercise, you will:

o Create the Favorites Slideshow action.


o Create the Add Favorite action.

The main tasks for this exercise are as follows:

1. Create the Favorites Slideshow action.


2. Create the Add Favorite action.

Task 1: Create the Favorites Slideshow action.

Start the virtual machine, and log on with the following credentials:

1. o Virtual machine: 20486B-SEA-DEV11


o User name: Admin
o Password: Pa$$w0rd
Open the PhotoSharingApplication.sln file from the following location:

2. File location: Allfiles (D:)\Labfiles\Mod12\Starter


o
\PhotoSharingApplication
In the PhotoController.cs code file, add a new action by using the following
information:

3. o Scope: public
o Return type: ActionResult
o Name: FavoritesSlideShow
In the FavoritesSlideShow action, create and instantiate a new enumerable
4.
list of Photo objects named favPhotos.
Create a new enumerable list of integers named favoriteIds. Set this list to be
5. equal to the Session["Favorites"] variable by casting this variable as a list of
integers.
6. If favoriteIds is null, set favoriteIds to be a new enumerable list of integers.
Create a new Photo object named currentPhoto. Do not instantiate the new
7.
object.
Create a new foreach code block that loops through all the integers in the
8.
favoriteIds list.
For each integer in the favoriteIds list, obtain the Photo object with the right
9. ID value by using the context.FindPhotoById() method. Store the object in
the currentPhoto variable.
If the currentPhoto variable is not equal to null, then add currentPhoto to
10.
the favPhotos list.
At the end of the FavoritesSlideShow action, return the SlideShow view and
11.
pass the favPhotos list as a model class.
12. Save all the changes.

Task 2: Create the Add Favorite action.

Add a new action to the PhotoController.cs file by using the following


information:

1. o Scope: public
o Return type: ContentResult
o Name: AddFavorite
o Parameter: an integer named PhotoId
Create a new enumerable list of integers named favoriteIds. Set this list to be
2. equal to the Session["Favorites"] variable, by casting the variable as a list of
integers.
3. If favoriteIds is null, set favoriteIds to be a new enumerable list of integers.
4. Add the PhotoId value to the favoriteIds list of integers.
5. Set the Session["Favorites"] variable to equal the favoriteIds variable.
Return HTML content by using the following information:

6. o Method: Content()
o Content: The picture has been added to your favorites
o Content type: text/plain
o Encoding: System.Text.Encoding.Default
7. Save all the changes.

Results: After completing this exercise, you will be able to create controller
actions that store values in the session state of the web application, and retrieve
values from the same session state.

Exercise 2: Implementing Favorites in Views

Scenario

You have created the necessary controller actions to implement favorite photos.
Now, you should implement the user interface components to display a control
for adding a favorite. If a user has favorites, you should display a link to the
FavoritesSlideShow action.

In this exercise, you will:

o Add an AJAX action link in the Photo Display view.


o Add a link and update the site map.

The main tasks for this exercise are as follows:

1. Add an AJAX action link in the Photo Display view.


2. Add a link and update the site map.
3. Test favorites.

Task 1: Add an AJAX action link in the Photo Display view.

1. Open the Display.cshtml view for the Photo controller.


At the end of the <div class="photo-metadata"> element, insert a new <div>
2.
element with the ID, addtofavorites.
In the DIV element, include the Ajax.ActionLink() helper to render a link to
the AddFavorite action by using the following information:

o Text: Add this photo to your favorites


o Action: AddFavorite
o Controller: Photo
3. Route values: Pass the Model.PhotoID value to the PhotoId action
o
parameter.
o Pass a new AjaxOptions object.
o Update target ID: addtofavorites
o HTTP method: GET
o Insertion mode: Replace
4. Save all the changes.

Task 2: Add a link and update the site map.


1. Open the _MainLayout.cshtml view for editing.
After the breadcrumb trail, add a Razor @if statement to ensure that the
2.
Session["Favorites"] variable is not null.
If the Session["Favorites"] variable is not null, render a <div> element with
3.
the ID, favorites-link.
In the DIV element, render a link to the FavoritesSlideShow action by using
the following information:

4. o Helper: Html.ActionLink()
o Link text: Favorite Photos
o Action: FavoritesSlideShow
o Controller: Photo
5. Save all the changes.
6. Open the Mvc.sitemap file.
Add a new site map node to the Mvc.sitemap file by using the following
information:
7.
o Title: Favorites
o Visibility: SiteMapPathHelper,!*
o Controller: Photo
o Action: FavoritesSlideShow
8. Save all the changes.

Task 3: Test favorites.

1. Start the web application in debugging mode.


2. Add three photos of your choice to your favorite photos.
3. Browse to the home page and click the Favorite Photos link.
4. Stop debugging and close Visual Studio.

Results: After completing this exercise, you will be able to :

Create the user interface components for the favorite photos functionality.

Test the functionality of the user interface components.

Question: In this lab, you stored the list of favorite photos in the session state.
While testing, your manager notices that authenticated users lose their favorite
photos list whenever they close their browser. Where would you store a list of
favorites for each authenticated user so that the list is preserved whenever a user
logs on to the web application?

Question: How would you create a view of favorite photos with the card-style
presentation users see on the All Photos page?

Module Review and Takeaways


Web applications are usually subject to different kinds of attacks. These attacks
enable attackers to access sensitive information stored in the database and to
perform malicious actions. You can use AntiXSS and request validation, to
protect the applications from web attacks. You can also use state management
techniques to store information for multiple HTTP requests to help avoid users
from typing the same information more than once.
Review Question(s)

Question: Recently, an error occurred in one of applications that you had


developed for your company. After performing few tests, you realize that the
issue was due to an HTML code that was passed from the user to the server. You
want to prevent such issues in the future. What would you consider to do?

Real-world Issues and Scenarios

While implementing web applications, you may want to use a rich format input
editor, to enable users to format the input within text boxes. Therefore, you may
need to disable request validation, to enable ASP.NET to capture and process
user input.

Complex business functions usually involve multiple views. Such functions can
pose problems because information must be shared across multiple views.
Session state management helps resolve these problems, because it enables
retaining information pertinent to multiple views.

 Module 13:
Aspecto destacadoNotaExpandir aspecto destacadoExpandir nota

Using Windows Azure Web Services in


ASP.NET MVC 4 Web Applications
Contents:
Module Overview

Lesson Introducing Windows Azure


1:
Lesson Designing and Writing Windows Azure Services
2:

Lesson Consuming Windows Azure Services in a Web Application


3:

Lab: Using Windows Azure Web Services in ASP.NET MVC 4 Web


Applications

Module Review and Takeaways

Module Overview
Developers often place all application logic in the application code. While this
practice works for small-scale applications, it may not work for applications with
a large number of users. An alternate approach is to make the code modular, by
modifying the applications to use web services.

Windows Azure is a cloud-based platform that enables you to host web


applications and services. You can use Windows Azure to make your web
application more scalable and manageable. To effectively use Windows Azure,
you need to know how to write a web service. You also need to know how to call
a web service from a web application or from other applications, such as a
mobile device application.

Objectives
After completing this module, you will be able to:

o Describe Windows Azure.


o Design Windows Azure services.
o Call Windows Azure services from a web application.

Lesson 1 : Introducing Windows Azure


Windows Azure is a Microsoft platform that helps meet specific needs of hosting
web applications, such as creating scalable and highly available web applications.
Windows Azure enables you to host services, applications, and databases.
Windows Azure also helps you create cost-effective and secure web offerings
that suit businesses of various types and sizes. You need to know how to host
applications, services, and databases on Windows Azure to increase the
scalability, flexibility, and availability of your web offerings.

Lesson Objectives
After completing this lesson, you will be able to:

o Describe Windows Azure.


o Describe the hosting services available in Windows Azure.
o Explain how to host web applications in Windows Azure.
Describe the data storage options offered by Azure Storage and Windows
o
Azure SQL Database.
o Determine when to use Windows Azure.

What Is Windows Azure?


The Windows Azure application platform provides comprehensive services to
host applications, files, media, and databases. Windows Azure is a flexible
platform that supports businesses of various sizes, helps reduce the effort to
develop scalable web applications, and decreases development costs.

Microsoft hosts Windows Azure in multiple data centers, across the United
States, Europe, and Asia.

Windows Azure provides the following categories of services:

Execution Models. Provides three different

o execution models—virtual machines

(VMs), web applications, and cloud services, for running applications


Windows Azure Identity Management. Includes Windows Azure Active
o Directory and Access Control services to help manage identities,
authentication, and authorization in a web application.
Data Management. Includes services to host and manage relational database
o
and Blob content
Business Analytics Solutions. Includes services that helps perform business
information analysis by using SQL Server Reporting Services and Apache
o
Hadoop. Business analytics solutions support all the data stores distributed
across multiple Windows Azure data centers.
Networking Services. Includes services that provide networking capabilities to
o
securely connect multiple services in Microsoft data centers.
Messaging with Service Bus. Includes services that enable applications to
o
communicate on Windows Azure.
Media Management. Includes services that bring content geographically closer
to users and help store large volumes of content outside the web application.
o
Storing content outside the application helps improve the performance of the
application.

Question: What are the benefits of hosting applications on Windows Azure?

Benefits of Hosting Services in Windows Azure

Windows Azure enables you to configure application logic to run as services.


Services denote a portion of the application code, which performs specific
business logic based on user inputs, such as retrieving product pricing
information. These services usually do not require:

o Administrator access to Windows.


o Complete access to the user interface of Windows.
Access to other functionalities that allow interacting with users, which VMs
o
facilitate.

Windows Azure cloud services do not use a dedicated VM. However, Windows
Azure cloud services use a role-based model that relies on the VM to host
applications. The role-based model includes a web role and a worker role. Each
role is a VM that is preconfigured to support automated deployment and
monitoring of applications.

While deploying these cloud services, you need not create the VM. You only
need to upload a configuration file to direct Windows Azure how to configure the
application. You need not upload this configuration file on the VM; you can
upload the file on to the staging environment. Then, the Windows Azure
management agent copies this configuration information to the production
servers.

Windows Azure cloud services do not retain state data in a role, because the VM
has no permanent storage. You can either use other services to retain state data or
design the application in a stateless manner.

Question: What are the benefits of using Windows Azure cloud services?

Benefits of Hosting Web Applications in Windows Azure

Hosting web applications on Windows Azure is similar to hosting services,


because both cases use virtual machines. However, unlike services, web
applications provide full access to the IIS instance assigned to your application.
You can use a web application to host ASP.NET websites, static content, open
source applications, and other file-based web applications.

Hosting web applications in Windows Azure provides the following benefits:


It automates the process of deploying
o
applications to different hosting servers.
It simplifies the process of scaling up and down as your application usage
o
grows or contracts.

Question: What are the key benefits of using Windows Azure web applications?

Windows Azure Storage Services

Windows Azure includes the following storage services:

Azure Storage. This is also known as BLOB (Binary Large Object) service.
You can use Azure storage to store objects or file content relevant to your web
o
applications. Each Blob includes a unique URL that allows applications to
directly access content in the Azure Storage.
SQL Database. This is a relational database service on the Windows Azure

platform. You can use SQL Database as

o the database engine for storing application data in a web application hosted in
Azure or on any other Internet server. Other applications, such as desktop
packages and mobile apps can connect to the same database over the Internet.
When you use SQL Database in Windows Azure, you:
Increase the availability and scalability of the data store and any applications

built on that data store.
▪ Reduce investments in hardware.

Question: What are the benefits of using Windows Azure SQL Database?

Discussion: Windows Azure Scenarios

Consider the following scenarios. In each case, discuss which Azure service will
best suit the scenario.

You are creating a photo sharing application, and you want to enable each user
to discuss the photos with their friends. You need to ensure that the photos in
1. your application do not occupy large disk storage in your web farm. Therefore,
you do not want to store the photos, which the users upload, in your
application database or server.
You are creating a Windows-based business
2.
application. This application requires a centralized database that users can
access by using the Internet.
You are writing business logic for your company, and both public and internal
3.
applications want to use this business logic.
You are creating an application that uses a third-party component. The third-
4.
party component requires full access to the Windows console.
Lesson 2: Designing and Writing Windows Azure
Services
Windows Azure cloud services provide a scalable hosting platform for web
applications. You can use Windows Azure cloud services to host Windows
Communication Foundation (WCF) services. Hosting such services helps transfer
key business logic from a web application onto a cloud platform. You need to
know about the life cycle of the Windows Azure services to add and modify code
during the different stages of application development. You also need to know
how to use diagnostic tools in Windows Azure, to identify the problems that
occur in your application

Lesson Objectives
After completing this lesson, you will be able to:

o Describe Windows Azure Visual Studio project templates.


o Write code to create a web service.
o Describe the life cycle of a web service.
o Deploy a web service.
o Debug a Windows Azure web service.

Windows Azure Visual Studio Project Templates


Microsoft Visual Studio provides project templates such as Windows Azure
project, web role project, and worker role project, which help create applications
and host them on Windows Azure.

Windows Azure Project

The Windows Azure project template facilitates role-based projects. This


template includes service definition and service configuration files.

Web Role Project

The web role project provides templates for the

following web roles:

o ASP.NET Web Forms


o ASP.NET MVC4
o ASP.NET MVC3
o ASP.NET MVC2
o WCF Service
o Silverlight Business Application

Worker Role Project

A worker role performs background processing by communicating with storage


services and other Internet-based services, without interacting with end users.
Worker role projects are ideal for long running services and other modular
business logic.

Question: Which project template should you use to create Windows


Communication Foundation (WCF) services?

Coding a Web Service


Modular programming plays an important role in developing applications,
because it enables you to re-use application code. Re-using services enables
cross-application sharing of business logic.

To create code for a web service, you need to perform the following steps:

Open Microsoft Visual Studio and create a Windows Azure WCF Service web
1.
role project.
Rename the IService1 interface that the template creates by default. You can
use the Visual Studio Refactor menu to rename the
2.
interface and update references to it throughout the solution.
Modify the interface code to define the interface-level properties and methods.
The following code shows a simple service interface that defines a single
method. Note the [ServiceContract] and [OperationContract] annotations.

[ServiceContract]

3. public interface IMyServiceInterface

[OperationContract]

string GetHelloWorld();
}

Rename the Service1 class that the template creates by default. Again, you can
4.
use the Refactor menu to help with this task.
Modify the service code to implement the methods required in the service
interface. The following code shows a simple service class that implements the
previous simple interface.

public class MyService : IMyServiceInterface

5. public string GetHelloWorld()

return "Hello Azure

Press F5 to test the services locally by using the Windows Azure emulator.
6. This practice ensures that the services function appropriately, before deploying
the services on Windows Azure.

Question: Why should you test the service code before deploying the service on
Windows Azure?

The Life Cycle of a Service


The RoleEntryPoint class defines the method that Windows Azure hosts call,
based on the development stage of the application. The RoleEntryPoint class
also helps define the functions that add logic to services. WCF services may
sometimes inherit the RoleEntryPoint class; however, worker roles services
mandatorily inherit the RoleEntryPoint class.

The RoleEntryPoint class helps define the following three life-cycle methods:

OnStart. Windows Azure triggers this


o
method when the application starts.
o OnStop. Windows Azure triggers this method when the application stops.
o Run. Windows Azure triggers this method to start long running processes.

The OnStart and OnStop methods return a Boolean value to the Windows
Azure host, when a function completes running. If the OnStart and OnStop
methods returns false, Windows Azure stops the application from running. You
should ensure that the OnStart and OnStop methods always return true, to
ensure that your application continues running.

Windows Azure does not trigger the OnStop method if a process terminates
because of exceptions. Windows Azure treats all uncaught exceptions as
unhandled exceptions that cause processes to terminate.

While defining the RoleEntryPoint class, you must:


Call the Application_Start method after the RoleEntryPoint.OnStart method
o
finishes.
Call the Application_End method before calling the RoleEntryPoint.OnStop
o
method.

Question: When should you use the RoleEntryPoint class?

Deploying a Web Service

When you create an application project, the system creates two files—
ServiceDefinition.csdef and ServiceConfiguration.cscfg. These files control the
Windows Azure instance that helps run the application.

The following list describes the ServiceDefinition.csdef and


ServiceConfiguration.cscfg files:

o ServiceDefinition.csdef. It helps define roles for your application.


ServiceConfiguration.cscfg. It is a hosted

o file that helps configure the instance assigned for your application. For
example, you can use ServiceConfiguration.cscfg to configure the number of
instances for your application.

Two copies of ServiceConfiguration.cscfg are available, a cloud version and a


local version, which you can use to locally test the services before deploying on
Windows Azure. You can manually update the details in the
ServiceConfiguration.cscfg file by using the Windows Azure property window.

Additional Reading: For more information about configuring a Windows Azure


project, go to: http://go.microsoft.com/fwlink/?LinkID=288989&clcid=0x418

You can use the Package tool in Microsoft Visual Studio to generate the service
package:

In the Solution Explorer pane, right-click the web service project, and then
1.
click Package.
In the Service Configuration box of the Package Windows Azure
2. Application dialog box, ensure that Cloud is selected, and then, in the Build
Configuration box, click Release.
Click Package. Visual Studio creates the .cspkg file and the .cscfg file for the
3.
service and displays them in the File Explorer window

Then, you need to upload the services package to the staging environment of the
Windows Azure platform by using the management portal. Package files have the
.cspkg extension. When you upload the package, you also need to upload the
ServiceConfiguration.cscfg file. The ServiceConfiguration.cscfg file directs
Windows Azure on how to configure the hosting environment.

After uploading and deploying the package on the Windows Azure platform, you
can access the service by using a URL, for example:

http:// <guid>.cloudapp.net/<service file name>

Question: When should you use the ServiceConfiguration.cscfg file?

Debugging a Windows Azure Web Service


You can debug a Windows Azure application by using the following tools:

o Diagnostic log
o IntelliTrace
o Remote Desktop

Diagnostic Logs

To debug Windows Azure web services, you need to include the Diagnostic
module in the ServiceDefinition.csdef file. The Diagnostics module helps access
the Application

Programming Interface (API), to perform diagnosis.

The following code shows how to include the Diagnostic module in the
ServiceDefinition.csdef file.

Configuring the Diagnostic Modulec

<?xml version="1.0" encoding="utf-8"?>

<ServiceDefinition name="MyHostedService"

xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinit

ion">

<WebRole name="WebRole1">
<Imports>

<Import moduleName="Diagnostics" />

</Imports>

</WebRole>

</ServiceDefinition>

Running the code in the preceding sample displays diagnostic data.

Additional Reading: For more information about the data types that you can
configure your application to collect, go to:
http://go.microsoft.com/fwlink/?LinkID=288990&clcid=0x419

To enable your application to monitor additional information, you need to add


the following lines of code in the OnStart method of your application file.

Add Data Sources

var config = DiagnosticMonitor.GetDefaultInitialConfiguration();

config.WindowsEventLog.DataSources.Add("System!*");

DiagnosticMonitor.Start("Microsoft.WindowsAzure.Plugins.Diagnostics.Conne

ctionString",

config);

The lines of code in the preceding sample help:

Configure the Windows Azure service to capture the Windows Event log. The
o
Windows Azure engine generates this log when the service runs.
Save the Windows Event log to the log files that are stored in LocalStorage.
o You can access the log files by using the Windows Azure storage explorer and
download the files.

IntelliTrace

IntelliTrace is a feature in Windows Azure that enables you to:

o Access event log information.


Debug the application.

Note: The virtual machines in Windows Azure always run 64-bit operating
o
systems. If you have Visual Studio 2010 Ultimate installed on a machine that
runs a 32-bit operating system, you must install this Intellitrace hotfix. This
Intellitrace hotfix helps install the 64-bit IntelliTrace components.

Additional Reading: To install the Intellitrace hotfix, go to:


http://go.microsoft.com/fwlink/?LinkID=288991&clcid=0x420

You can enable IntelliTrace, while you deploy or package services. You can also
configure services to enable IntelliTrace for specific events. This configuration
helps capture detailed information such as Windows log and system
configurations.

The following image displays the IntelliTrace Settings dialog box.


FIGURE 13.1:THE INTELLITRACE SETTINGS DIALOG BOX

IntelliTrace also helps in problem diagnosis. You can simulate some problems
that you may encounter while running web services. Then, you can download the
IntelliTrace logs from Windows Azure by using the Server Explorer. These logs
can help you to access and understand the problems.

The following image displays the IntelliTrace tool in the Server Explorer.

FIGURE 13.2:INTELLITRACE LOGS

Remote Desktop

If you use Windows Azure Cloud Services, you can configure the application to
provide remote desktop access to an instance. This configuration provides full
access to Windows event logs.

You can enable remote desktop access when you publish your cloud service. To
do this, in the Visual Studio Publish wizard, on the Settings page, select Enable
Remote Desktop for all roles. Then, you specify the credentials that a user
should use to access the remote desktop console. All instances of your
application that run on Windows Azure will use these credentials.

After publishing the application on Windows Azure, you can access the remote
desktop by using the management portal.

Question: What is the difference between using diagnostic logs and IntelliTrace?
Lesson 3: Consuming Windows Azure Services in a
Web Application
After completing the setup and deployment of the Windows Azure Services, you
need to add logic to your application to use the services from ASP.NET MVC
application and HTML code. You can call a Windows Azure web service using
server-side code or by using client-side code.

Lesson Objectives
After completing this lesson, you will be able to:

o Call a Windows Azure web service by using server-side code.


o Explain how to call a Windows Azure web service by using jQuery and JSON.
o Call a Windows Azure web service by using jQuery.

Calling a Windows Azure Service by Using Server-Side


Code

You can call web services hosted on Windows Azure in the same manner with
which you call standard web services or WCF services. To call a web service,
you need to:

1. Add the service reference in your application.


2. Use the generated proxy class.
To add a service reference in an application, you need to use the URL of the
service. You can deploy a service in the production environment, by using the
following URL format:

http://<urlname>.cloudapp.net/<servicename>.sv

You can deploy a service in the staging environment, by using the following
URL format:

http://<guid>.cloudapp.net/<servicename>.svc

To use the WCF service hosted on Windows Azure, from your MVC application,
you need perform the following steps:

In the Solution Explorer pane, right-click your project name, and then click
1.
Add Service Reference.
2. Enter the URL of the WCF service, and then click Go.
Define the local namespace of the service, and then click Add Service
3.
Reference.
Add the following code to an MVC controller class to use the generated proxy
4.
class and call the web service created earlier in this module.
public ActionResult Index()

Service1Client client = new Service1Client();

GetHelloWorldRequest request = new GetHelloWorldRequest();

GetHelloWorldResponse response = client.GetHello(request);

ViewBag.Response = response.GetHelloWorldResult;

return View();
}

Question: What is the key difference between deploying a service in the


production environment and deploying a service in the staging environment?

Calling a Windows Azure Service by Using jQuery

You can enable the jQuery ajax function to call WCF services, by configuring
the services to accept POST requests in the JavaScript Object Notation (JSON)
data format. JSON is a data format that facilitates requests and responses
between client and server systems.

The following code shows how to configure services to accept POST requests in
the JSON data format.

Accepting POST Requests

[ServiceContract]

public interface IService

[OperationContract]

[WebInvoke(Method = "POST",
BodyStyle = WebMessageBodyStyle.Wrapped,

ResponseFormat = WebMessageFormat.Json)]

string GetHelloWorld();

You can use the ajax function in jQuery to submit requests to WCF services.
While adding the ajax function, you need to specify parameters such as type,
url, contentType, and dataType. The following code shows how to use the ajax
function in jQuery, to call an Azure-hosted WCF service.

Sending Requests to a WCF Service

// Function to call WCF Service

function CallService() {

$.ajax({

type: 'POST',

url: 'http://<guid>.cloudapp.net/service1.svc/GetHelloWorld',

data: '{}',

contentType: 'application/json; charset=utf-8',

dataType: “json”,

processdata: true,

success: function(msg) {

ServiceSucceeded(msg);
},

error: ServiceFailed// When Service call fails

});

function ServiceFailed(result) {

function ServiceSucceeded(result) {

result=result.GetHelloWorldResult;

After successfully calling the WCF service, the code in the preceding sample
triggers the ServiceSucceeded callback function.

Demonstration: How to Call a Windows Azure Service


by Using jQuery
In this demonstration, you will see how to call a web service by using jQuery.

Demonstration Steps
In the Solution Explorer pane of the OperasWebSite – Microsoft Visual
1. Studio window, expand OperasWebSite, expand Views, expand Home, and
then double-click Index.cshtml.
In the Index.cshtml code window, locate the following code.

@Html.ActionLink("operas I've seen.", "Index", "Opera")


2.

</p>
Place the mouse cursor after the located code, press Enter twice, and then
type the following code.

3. <form>

</form>

Place the mouse cursor in the FORM element code block you just created,
and then type the following code.
4.
<input type="button" value="Get Latest Quote" name="GetLatestQuote"

onclick="callWebService();" />
Place the mouse cursor at the end of the INPUT element, press Enter, and
then type the following code.
5.
<p id="quote-display"></p>

In the Index.cshtml code window, locate the following code.


6.
</form>

Place the mouse cursor at the end of the located code, press Enter twice, and
then type the following code.

7. <script type="text/javascript">

</script>

Place the mouse cursor in the SCRIPT element code block you just created,
and then type the following code.

8. function callWebService() {

}
Place the mouse cursor in the callWebService function code block, and then
type the following code.
9.

var serviceUrl = '@Url.Content("~/WebServices/QuotesService.asmx")';


In the callWebService function code block, place the mouse cursor at the end
of the variable you just created, press Enter, and then type the following code.

$.ajax({

type: "POST",

url: serviceUrl + "/LatestQuote",

data: {},

10.
contentType: "application/json; charset=utf-8",

dataType: "json",

success: OnSuccess,

error: OnError

});
Place the mouse cursor at the end of the callWebService function code block,
but within the SCRIPT element, press Enter twice, and then type the
following code.
11.
function OnSuccess(response) {

}
Place the mouse cursor in the OnSuccess function code block, and then type
the following code.

12. $('#quote-display').html(response.d);

Note: response.d is the property you use to access JSON data from the
server.
Place the mouse cursor at the end of the OnSuccess function code block, but
within the SCRIPT element, press Enter twice, and then type the following
code.
13.
function OnError(response) {

Place the mouse cursor within the OnError function, and then type the
following code.
14.
$('#quote-display').html("Could not obtain the latest quote");

On the DEBUG menu of the OperasWebSite – Microsoft Visual Studio


15.
window, click Start Debugging.
On the Operas I Have Seen page, click Get Latest Quote.
16.
Note: jQuery calls the web service and displays a quote on the home page.
Note that you need not reload the page to display the quote.
17. In the Windows Internet Explorer window, click the Close button.
In the OperasWebSite – Microsoft Visual Studio window, click the Close
18.
button.

Lab: Using Windows Azure Web Services in


ASP.NET MVC 4 Web Applications
Scenario
In the Photo Sharing application, the users have the option to add location
information of a photo when they upload it. The senior developer recommends
that you should store the location as a longitude and latitude, and an address so
that other applications can use the data in mash-ups. You have been asked to
create a service, hosted in Windows Azure, which will perform this conversion.
You have to call this service from the Photo Upload page in the Photo Sharing
application.

Objectives

After completing this lab, you will be able to:

o Install the Windows Azure software development kit (SDK).


o Create a Bing Maps developer account and trial key.
o Write a web service in Visual Studio that is hosted in Windows Azure.
o Call a Windows Azure web service from server-side code in a web application.

Lab Setup

Estimated Time: 75 minutes

Virtual Machine: 20486B-SEA-DEV11

User name: Admin

Password: Pa$$w0rd

Note: In Hyper-V Manager, start the MSL-TMG1 virtual machine if it is not


already running.

Before initiating this lab, you need to perform the following steps:

Apply the Snapshot of the virtual machine, 20486B-SEA-DEV11, that was


o▪
taken after completing the lab in module 11.
Navigate to Allfiles (D):\Labfiles\Mod

11\Starter\PhotoSharingApplication\PhotoSharingApplication, and then
copy the web.config file.
Navigate to Allfiles (D):\Labfiles\Mod

13\Starter\PhotoSharingApplication\PhotoSharingApplication, and then
paste the web.config file.
Enable the Allow NuGet to download missing packages during build

option, by performing the following steps:
On the TOOLS menu of the Microsoft Visual Studio window, click
i.
Options.
ii. In the navigation pane of the Options dialog box, click Package Manager.
Under the Package Restore section, select the Allow NuGet to download
iii.
missing packages during build checkbox, and then click OK.
After completing this lab, you need to take the Snapshot of the virtual machine.
o You need to apply this Snapshot before initiating the labs in module 14, 15 and
16.

Exercise 1: Accessing Windows Azure and Bing Maps

Scenario

To develop a Windows Communication Foundation (WCF) service that is hosted


in Windows Azure, you must install the Windows Azure SDK. To resolve
address details to latitude and longitude data, you will use the Bing Maps
Location API. You will call this API from the WCF service hosted in Windows
Azure so that you can re-use your web service from other Adventure Works
websites and applications.

In this exercise, you will:

o Install the Windows Azure SDK.


o Create a Bing Maps developer account.
o Create a Bing Maps Key.
The main tasks for this exercise are as follows:

1. Install the Windows Azure SDK.


2. Create a Bing Maps developer account.
3. Create a Bing Maps key.

Task 1: Install the Windows Azure SDK.

Start the virtual machine, and log on with the following credentials:

1. o Virtual Machine: 20486B-SEA-DEV11


o User name: Admin
o Password: Pa$$w0rd
Navigate to the following webpage:
2.
o http://www.microsoft.com/web/downloads/platform.aspx
3. Download and run the Web Platform Installer.
Use the Web Platform Installer to download and install the Windows Azure
4.
SDK for .NET (VS 2012).

Task 2: Create a Bing Maps developer account.

Navigate to the following webpage:


1.
o https://www.bingmapsportal.com
Log on to the Bing Maps Account Center web application by using following
the Windows Live account credentials:
2.
o User name: <Your Windows Live account name>
o Password: <Your Windows Live account password>
Register a new Bing Maps developer account by using the following
information:
3.
o Account Name: <Your account name>
o Contact Name: <Your name>
o Email Address: <Your Windows Live account name>

Task 3: Create a Bing Maps key.

Create a new Bing Maps key in the Photo Sharing application by using the
following information:

1. o Application name: Photo Sharing Application


o Key type: Trial
o Application type: Public website

Results: After completing this exercise, you will be able to register an


application to access the Bing Maps APIs.

Exercise 2: Creating a WCF Service for Windows Azure

Scenario

You want to create a WCF service to resolve a locality string to a latitude and
longitude by looking up the information in the Bing Maps Geocode SOAP
service. After creating the WCF service, you need to host the service in Windows
Azure by using the Windows Azure Cloud Service project template from the
Windows Azure SDK.

In this exercise, you will:

o Add a new Windows Azure Cloud Service project to the web application.
o Create the Location Checker Service interface.
o Add a service reference to the Bing Maps Geocode service.
o Write the Location Checker service.
o Publish the Service in Windows Azure.

The main tasks for this exercise are as follows:


1. Add a new Windows Azure Cloud Service project to the web application.
2. Create the Location Checker Service interface.
3. Add a service reference to the Bing Maps Geocode service.
4. Write the Location Checker service.
5. Publish the Service in Windows Azure.

Task 1: Add a new Windows Azure Cloud Service project to the web
application.

Open the PhotoSharingApplication.sln file from the following location:

1.
File location: Allfiles
o
(D):\Labfiles\Mod13\Starter\PhotoSharingApplication
Add a new project to the PhotoSharingApplication web application by using
the following information:

2. o Template: Windows Azure Cloud Service


o Name: LocationChecker
o .NET Framework 4.5 role: WCF Service Web Role
3. Rename the WCFServiceWebRole1 project as LocationCheckerWebRole.
4. Rename the IService1.cs file as ILocationCheckerService.cs.
5. Rename the Service1.svc file as LocationCheckerService.svc.
Rename the WCFServiceWebRole1 namespace as
6. LocationCheckerWebRole throughout the LocationCheckerService.svc.cs
file.
7. Rename the Service1 class as LocationCheckerService.
In the ServiceDefinition.csdef file, set the value of vmsize for the
8.
LocationCheckerWebRole to ExtraSmall.
9. Save all the changes.

Task 2: Create the Location Checker Service interface.


Remove all the method declarations from the ILocationCheckerService
1.
interface.
Add a new method declaration to the ILocationCheckerService interface by
using the following information:

2. o Annotation: [OperationContract]
o Return type: string
o Name: GetLocation
o Parameter: a string named address
3. Save all the changes.

Task 3: Add a service reference to the Bing Maps Geocode service.

Add a service reference to the LocationCheckerWebRole project by using the


following information:

1 Address:
. o
http://dev.virtualearth.net/webservices/v1/geocodeservice/geocodeservice
.svc?wsdl.
o Namespace: GeocodeService
In the LocationCheckerService.svc code file, add a using statement for the
2 following namespace:
.
o LocationCheckerWebRole.GeocodeService
3
Save all the changes.
.

Task 4: Write the Location Checker service.

Remove the following public methods from the LocationCheckerService


class:
1.
o GetData
o CompositeType
Add a new method to the LocationCheckerService class by using the
following information:

2. o Scope: public
o Return type: string
o Name: GetLocation
o Parameter: a string named address
In the GetLocation method, create a string variable, results, and initialize the
3.
value of the results variable to an empty string.
From the Bing Maps Account Center page, copy the key you created for the
4.
Photo Sharing Application.
In the GetLocation method, create a string variable, key, and paste the key
5.
from the Bing Maps Account Center page as a value of the key variable.
Open the Geocoding Code.txt from the following location:
6.
o Allfiles (D):\Labfiles\Mod13\Service Code
Copy all the text from the Geocoding Code.txt file and paste the text into the
7.
GetLocation method, immediately after the key variable initialization.
8. At the end of the GetLocation method, return the string variable results.
9. Save all the changes.

Task 5: Publish the Service in Windows Azure.

Package the LocationChecker project by using the following information:


1
. o Service configuration: Cloud
o Build configuration: Debug
2
In Windows Internet Explorer, log on to the Windows Azure Portal.
.
Create a new cloud service by using the following information:
3
.
o URL: <Your Windows Live Account Name>LocationService
Region: <Choose a location near you>
o
Note: If your Windows Live Account Name includes dots or @ symbols,
replace these characters with dashes.
Upload a new staging deployment to the new cloud service by using the
following information:

oName: LocationChecker
Package location: Allfiles
4
. o(D):\Labfiles\Mod13\Starter\PhotoSharingApplication\LocationChecker\
bin\Debug\app.p ublish
oPackage: LocationChecker.cspkg
oConfiguration: ServiceConfiguration.Cloud.cscfg
oDeploy even if one or more roles contain a single instance.

Results: After completing this exercise, you will be able to create a WCF cloud
service. You will also be able to publish the WCF cloud service in Windows
Azure.

Exercise 3: Calling a Web Service from Controller Action

Scenario

Now that you have created and deployed the Location Checker WCF service in
Windows Azure, you can call the service from the Photo Sharing ASP.NET
MVC web application. You can also call the service from other .NET code, such
as desktop applications, if necessary.

In this exercise, you will use the Location Checker service to add latitude and
longitude data to new photos as they are added to the Photo Sharing application.

The main tasks for this exercise are as follows:

1. Add a service reference to the Photo Sharing application.


2. Call the WCF service from the photo create action.
3. Configure the Services Database connection string.
4. Test the Location Checker service.

Task 1: Add a service reference to the Photo Sharing application.

Add a new Service Reference to the PhotoSharingApplication project by


using the following information:

1. Address: Copy the URL from the CLOUD SERVICE page in the Windows
o
Azure Portal
o Namespace: GeocodeService
Add a using statement for the following namespace to the PhotoController.cs
code file:
2.
o PhotoSharingApplication.GeocodeService
3. Save all the changes.

Task 2: Call the WCF service from the photo create action.

Add a new method to the PhotoController class by using the following


information:

1. o Scope: private
o Return type: string
o Name: CheckLocation
o Parameter: a string named location
In the CheckLocation method, create a new variable by using the following
information:

2. o Type: LocationCheckerServiceClient
o Name of the variable: client
o Value of the variable: Null
In the CheckLocation method, create a new string variable, response, and
3.
initialize the value of the response variable to Null.
4. Add a new try…catch statement that catches all errors in a variable named e.
In the try block, set the client variable to be a new
5.
LocationCheckerServiceClient.
Pass the location parameter to the client.GetLocation method and store the
6.
result in the response variable.
7. In the catch block, store the e.Message property in the response variable.
8. At the end of the CheckLocation method, return the response string.
At the start of the Create action method for the HTTP POST verb, add an if
9.
statement that checks that photo.Location is not an empty string.
In the if statement, pass the photo.Location property to the CheckLocation
10.
method and store the result in a new string variable named stringLongLat.
Add an if statement to check whether the stringLongLat variable starts with
11.
the string, Success.
In the if statement, create a new array of characters named splitChars and
12.
add the single character ":" to the array.
Pass the splitChars array to the Split method of stringLongLat, and store
13.
the result in a new array of strings named coordinates.
Set the photo.Latitude property to the second string in the coordinates array
14. and set the photo.Longitude property to the third string in the coordinates
array.
15. Save all the changes.

Task 3: Configure the Services Database connection string.

In the Windows Azure Portal, copy the ADO.NET connection string for the
1.
PhotoSharingAppServices database to the clipboard.
Paste the connection string into the connectionString value for the
2.
AzureAppServices connection string.
3. Save all the changes.
Task 4: Test the Location Checker service.

1. Set PhotoSharingApplication as the startup project for the solution.


Run the web application in debugging mode, and then log on to the web
application by using the following credentials:
2.
o User name: David Johnson
o Password: Pa$$w0rd2
Add a new photo to the application by using the following information:

3. o Title: Testing Locations


o Photo: Allfiles (D):\Labfiles\Mod13\Sample Photos\Beach.jpg
o Location: Florence, OR
Browse to the Home page and display your new photo to check the Latitude
4.
and Longitude properties.
5. Stop debugging and close Visual Studio.

Results: After completing this exercise, you will be able to add a service
reference for a Windows Azure WCF service to a .NET Framework application.
You will also be able to call a WCF service from an MVC controller action.

Question: What is the advantage of calling the Bing Maps Geocoding service
from a WCF service in Windows Azure, instead of calling the Geocoding service
directly from the Create action in the MVC web application?

Question: Why is latitude and longitude data useful for photos in the Photo
Sharing application?

Module Review and Takeaways


You can upload applications and services on Windows Azure to enable better
scalability and re-usability of the application logic. Windows Azure includes
different roles that support application needs such as hosting and storage. You
can also use cloud services to host WCF services, and use the hosting services
available in MVC and HTML applications.

Review Question(s)

Question: Your teammate enquired whether you would be using Windows Azure
or self host the server for the application. What should you recommend to your
teammate based on the fact that the application loading would be seasonal?

 Module 14:
Aspecto destacadoNotaExpandir aspecto destacadoExpandir nota

Implementing Web APIs in ASP.NET MVC 4


Web Applications
Contents:
Module Overview

Lesson Developing a Web API


1:

Lesson Calling a Web API from Mobile and Web Applications


2:

Lab: Implementing APIs in ASP.NET MVC 4 Web Applications


Module Review and Takeaways

Module Overview
Most web applications require integration with external systems such as mobile
applications. You need to know how to use Web APIs to promote application
interaction with external systems. You can use the Web API to implement
Representational State Transfer (REST) services in your application. REST
services help reduce application overhead and limit the data that is transmitted
between client and server systems. You need to know how to call Web API
services by using server-side code, jQuery code, and JSON.NET library to
effectively implement REST-style Web APIs in your application.

Objectives

After completing this module, you will be able to:

o Develop a Web API.


o Call a Web API from mobile and web applications.

Lesson 1 : Developing a Web API


You need to know how to develop Web API for applications, because Web API
facilitates creating APIs for mobile applications, desktop applications, web
services, web applications, and other applications. By creating a Web API, you
make the information in your web application available for other developers to
use in their systems. Each web application has a different functional
methodology; this difference can cause interoperability issues in applications.
REST services have a lightweight design, and Web API helps implement REST
services to solve the interoperability issues. You need to know how to use the
different routing methods that ASP.NET provides to implement REST services.
Lesson Objectives
After completing this lesson, you will be able to:

o Describe Web APIs.


o Create a Web API for an MVC 4 web application.
o Describe REST services.
o Describe data return formats.
o Explain how to use routes and controllers to implement REST in Web APIs.
o Explore a Web API by using Internet Explorer as a client.

What Is a Web API?

Web API is a framework that is part of ASP.NET MVC 4 that enables you to
build Representational State Transfer (REST)-enabled APIs. REST-enabled APIs
help external systems use the business logic implemented in your application to
increase the reusability of the application logic. Web API facilitates two-way
communication between the client system and the server through tasks such as:

o Instructing an application to perform a specific task


o Reading data values
o Updating data values

Web API enables developers to obtain business information by using REST,


without creating complicated XML requests such as Simple Object Access
Protocol (SOAP). Web APIs use URLs in requests, thereby eliminating the need
for complicated requests. For example, the following URL obtains information
for a customer entity with the ID 1:

http://api.contoso.com/api/customers/1

Web API uses such URLs in requests and obtains results in the JSON format.
The following code shows a Web API request response in the JSON format.

A Web API JSON Response

[{"Id":1,"Name":"Tomato

soup","Category":"Groceries","Price":1.0},{"Id":2,"Name":

"Yo-

yo","Category":"Toys","Price":3.75},{"Id":3,"Name":"Hammer","Category":

"Hardware","Price":16.99}]

REST and Web API enable all kinds of different applications, including mobile
device applications, to interact with services. In particular, REST and Web API
provide the following benefits for mobile applications:

They reduce the processing power needed to create complex request messages
o
for data retrieval.
They enhance the performance of the application by reducing the amount of
o
data exchange between client and server.

Question: What is the key benefit of using REST with Web APIs?

Routing in Web API


When you create a new project by using the Web API template in ASP.NET
MVC 4, it includes a default routing rule. This routing rule helps map HTTP
requests to the Web API controllers and actions by using HTTP verbs and the
request URL.

You can make use of a naming convention to map requests to actions, or you can
control the behavior of the mapping by using annotations on action methods.

The Default API Route

Like standard MVC web applications, MVC Web

API uses routes to map requests to the right API

controller and action. In the Visual Studio project templates, the default API
route is defined in the WebApiConfig.cs file in the App_Start folder.

The following code shows the default route.

The Default API Route

routes.MapHttpRoute(

name: "API Default",

routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }

);

In the preceding code sample, observe that the default route includes the literal
path segment api. This segment ensures that Web API requests are clearly
separate from MVC controller routes, because Web API requests must start with
api.

The first placeholder variable, {controller} helps identify the API controller to
forward the request to. As for MVC controllers, Web API appends the word,
Controller, to this value to locate the right API controller class. For example,
Web API routes a request to the URI, api/products, to the controller called,
ProductsController. As for MVC controllers, the optional placeholder variable,
{id}, is sent to the action as a parameter.

You can also define your own API routes in the same manner as you do for MVC
routes. Observe, however, that Web API routes can handle requests from many
types of client systems, including mobile device applications, desktop
applications, web applications, and web services. MVC routes only handle web
browser requests.

Using the Action Naming Convention

The default Web API route does not include a placeholder variable for the action
name. This is because Web API uses the HTTP verb and a naming convention to
route requests to the right action within a given controller.

Clients can make HTTP requests with one of four standard verbs: GET, POST,
PUT, and DELETE. Other verbs are possible. Web API looks for an action
whose name begins with the requested HTTP verb. For example, if the client
sends a DELETE request to the URI api/products/23, Web API looks for a
controller called ProductsController. Within this controller, it locates an action
whose name begins with Delete. According to the default route, the segment 23
is the {id} parameter. If there is more than one action whose name begins with
Delete, Web API chooses the action that accepts a parameter called id.

The HttpGet, HttpPut, HttpPost, and HttpDelete Attributes

You can use the HttpGet, HttpPut, HttpPost, or HttpDelete attributes in your
controller action to override the action naming convention. You can also use
these verbs to specify that a function is mapped to a specific HTTP verb. The
following table describes how the HTTP attributes map to the HTTP verbs.

Attribute HTTP Verb

HttpGet GET

HttpPut PUT

HttpPost POST

HttpDelete DELETE

The following code illustrates the use of the HttpGet attribute on the FindProduct
action.

Specifying the HTTP Verb

public class ProductsController : ApiController

[HttpGet]

public Product FindProduct(id) {}

}
In the preceding code sample, observe that the HTTP attributes only allow
mapping of one HTTP verb to an action in the controller.

The AcceptVerbs Attribute

The use of the AcceptVerbs attribute allows you to specify custom HTTP Verbs
or multiple HTTP verbs to the same actions in the controller.

The following code shows the use of the AcceptVerbs attribute to map specific
HTTP verbs to the action.

The AcceptVerbs Attribute

public class ProductsController : ApiController

[AcceptVerbs("GET", "HEAD")]

public Product FindProduct(id) { }

[AcceptVerbs("MKCOL")]

public void MakeCollection() { }

The ActionName attribute

By default, the action name is the name of the action you specify in the
controller. You can use the ActionName attribute to specify the action name to
be used in the routing.

The following code shows how to map an action to an HTTP request by using a
custom action name.

Mapping an Action
public class ProductsController : ApiController

[HttpGet]

[ActionName("Thumbnail")]

public HttpResponseMessage GetThumbnailImage(int id);

[HttpPost]

[ActionName("Thumbnail")]

public void AddThumbnailImage(int id);

Question: What is the purpose of using the HTTP attributes?

Creating a Web API for an MVC 4 Web Application

MVC4 provides a Web API project template that helps implement Web API in a
project.

The following image shows the list of project templates available in Microsoft
Visual Studio.
FIGURE 14.1:THE NEW PROJECT DIALOG BOX

To implement a Web API template in your project, you need to perform the
following steps:

1. In the New Project dialog box, click ASP.NET MVC 4 Web Application.
In the Select a Template box of the New ASP.NET MVC 4 Project dialog
2.
box, click Web API.

The following image shows the New ASP.NET MVC 4 Project dialog box.
FIGURE 14.2:THE NEW ASP.NET MVC 4 PROJECT DIALOG BOX

After selecting the Web API template, you need to add a new MVC controller
class that derives from ApiController. The API controller class hosts application
code for handling Web API requests. ASP.NET MVC4 engine maps the URL
together with the HTTP verb and the controller or the action function of a
controller, in the following format.

<http verb> http://<hostname>/api/<entity name>/<parameters>

The HTTP verb communicates to the Web API about the operations that it should
perform; whereas, the rest is to communicate which entity and operations to
perform on. Therefore, HTTP plays an important role. For example, consider the
following API controller class.

public class ProductsController : ApiController


{

public IEnumerable<Product> GetAllProducts()

public Product GetProductById(int id)

In the preceding code sample, note the controller classes GetAllProducts and
GetProductById. The GetAllProducts controller class helps obtain a full list of
products from the database. You can map the following URL and HTTP verb
with the GetAllProducts controller class.

GET /api/products

The GetProductById controller class helps obtain a specific product by using


the ID detail. You can map the following URL with the GetProductById
controller class.

GET /api/products/id

Question: What is the syntax that the ASP.NET MVC engine uses for mapping
controllers and action functions?

RESTful Services
REST uses URLs and HTTP verbs to uniquely identify the entity that it operates
on and the action that it performs. REST helps retrieve business information from
the server. However, in addition to data retrieval, business applications perform
more tasks such as creating, updating, and deleting information on the database.
Web API and REST facilitate handling such additional tasks. They use the HTTP
method to identify the operation that the application needs to perform.

The following table provides information on some HTTP methods that Web API
and REST use.

HTTP Description
Verb

GET Use this method with the following URL to obtain a list of all
customers.

/api/customers

GET Use this method with the following URL to obtain a customer
by using the ID detail.
HTTP Description
Verb

/api/customers/id

GET Use this method with the following URL to obtain customers
by using the category detail.

/api/customers?country=country

POST Use this method with the following URL to create a customer
record.

/api/customers

PUT Use this method with the following URL to update a customer
record.

/api/customers/id

DELETE Use this method with the following URL to delete a customer
record.
HTTP Description
Verb

/api/customers/id

Web API allows developers to use a strong typed model for developers to
manipulate HTTP request. The following code shows how to use the POST,
PUT, and DELETE methods for the create, update, and delete requests to handle
the creation, retrieval, updation, and deletion (CRUD) of the customer records.

CRUD Operations

public HttpResponseMessage PostCustomer(Customer item)

public void PutCustomer(int id, Customer item)

public void DeleteProduct(int id)

Question: What is the mandatory requirement of create and update requests?

Data Return Formats


When a client makes a request to a Web API controller, the controller action
often returns some data. For GET requests, for example, this data might be all the
properties of a specific product or all the properties of all the products.

Web API can return this data in one of two formats: JavaScript Object Notation
(JSON) or XML.

JSON and XML Data Formats

Both JSON and XML are text formats that represent information as strings. You
can also use

JSON outside the JavaScript code.

The following code is a simple example of JSON.

A JSON Response

{"Name":"Albert","Age":29,"Height":145,"Skills":["Programming",

"Technical Writing"]}

You can represent the same data in the previous code sample, by using XML as
shown in the following code.

An XML Response

<Employee Name="Albert" Age="29" Height="145">


<Skills>

<Skill Name="Programming" />

<Skill Name="Technical Writing" />

</Skills>

</Employee>

When a client makes a request, the client can specify the data format for the
response. If the data format is not specified, Web API formats data as JSON by
default.

Media Formatters

Web API uses a media formatter to format or serialize the information that a Web
API REST service returns. Web applications usually use the JSON format to
format the data that functions return. However, you can alternatively use the
XML media formatter or add a custom media formatter to control the data
returned. Media formatters format the content that the server renders to the client
systems.

For example, consider that you want Web API to return CSV files. In this case,
you need to create a custom media formatter, to create as output data files in the
CSV format, instead of XML files in the JSON format.

The following code shows to add a new class in your project, to create a custom
media formatter.

A Custom Media Formatter

public class CsvFormatter : BufferedMediaTypeFormatter

{
}

Media formatter classes inherit from the following classes:

o MediaTypeFormatter. This is the fundamental class for all formatter classes.


BufferedMediaTypeFormatter. This is an extended class of formatter classes,
o
which provides support for buffering and asynchronous operations.

Additional Reading: For more information on creating media formatters, go to:


http://go.microsoft.com/fwlink/?LinkID=288992&clcid=0x421

Question: Why should you use a media formatter for Web API REST services?

Using Routes and Controllers in Web APIs

ASP.NET MVC4 uses a route table to map a URL and a controller. When you
create a project, ASP.NET adds a default route by using the Web API template.
This default route helps support the operations of the REST-style Web APIs.

The following code shows the default route.

The Default API Route

routes.MapHttpRoute(

name: "API Default",


routeTemplate:

"api/{controller}/{id}",

defaults: new { id =

RouteParameter.Optional }

);

Consider that you want to include multiple actions, such as creating customers
with XML and JSON, in the same HTTP method. In this case, you cannot use the
default route because it requires a new request for each HTTP method and URL
combination. Therefore, you need to update the routing by modifying the Route
Map in the WebApiConfig class.

The following code shows how to update the routing, to support multiple
operations in the same HTTP method.

Supporting Multiple Operations

routes.MapHttpRoute(

name: "ActionApi",

routeTemplate: "api/{controller}/{action}/{id}",

defaults: new { id = RouteParameter.Optional }

);

You can use the WebApiConfig class to enable multiple versions of API to
coexist in the same project. For example, you can include /api/v1/{controller} as
Version One of your API and include /api/v2/{controller} as a new version or
Version Two of the API.

You may want to include supporting functions in the controller class, and hide
the supporting functions from the REST functions. You can eliminate the
exposure of the function to the REST interface by adding the NoAction attribute
to the action function.

The following code shows how to add the NoAction attribute to the action
function.

Using NoAction

[NonAction]

public string GetPrivateData()

By default, Web API exposes all public methods as REST services. You can
prevent this by making the function private, but this action prevents application
code in the same project from accessing the function. Therefore, you can use the
NonAction attribute for functions that need to be in public, but do not need to be
exposed in REST.

Question: What is the key benefit of using the routing map?

Demonstration: How to Explore a Web API by Using


Internet Explorer
In this demonstration, you will see how to:

o Create a simple Web API for an existing ASP.NET MVC 4 web application.
Download and examine the JSON files that the Web API generates by using
o
Internet Explorer.

Demonstration Steps
1. In the Solution Explorer pane, expand OperasWebSite.
In the Solution Explorer pane, under OperasWebSite, right-click Controllers,
2.
point to Add, and then click Controller.
In the Controller name box of the Add Controller dialog box, type
3. OperasApiController, in the Template box, click Empty API Controller,
and then click Add
In the OperasApiController.cs code window, locate the following code.
4.
using System.Web.Http;

Place the mouse cursor at the end of the located code, press Enter, and then
type the following code.
5.
using OperasWebSite.Models;

Place the mouse cursor in the OperasApiController class code block, press
Enter, and then type the following code.
6.
private OperasDB contextDB = new OperasDB();

Place the mouse cursor at the end of the code you just typed, press Enter
twice, and then type the following code.

public IEnumerable<Opera> GetOperas()


7.
{

}
Place the mouse cursor in the GetOperas action code block, and then type
the following code.
8.
return contextDB.Operas.AsEnumerable();

Place the mouse cursor at the end of the GetOperas action code block, press
Enter twice, and then type the following code.

public Opera GetOperas(int id)


9.
{

Place the mouse cursor in the GetOperas action code block you just created,
and then type the following code.
10.
Opera opera = contextDB.Operas.Find(id);

Place the mouse cursor at the end of the code you just entered, press Enter,
and then type the following code.

if (opera == null)

11. {

throw new HttpResponseException(HttpStatusCode.NotFound);

Place the mouse cursor at the end of the code you just entered, press Enter,
and then type the following code.
12.
return opera;
On the FILE menu of the OperasWebSite – Microsoft Visual Studio
13.
window, click Save All.
On the DEBUG menu of the OperasWebSite – Microsoft Visual Studio
14.
window, click Start Debugging.
In the Address bar of the Windows Internet Explorer window, type
15.
http://localhost:<yourPortNumber>/api/OperasApi, and then click Go to.
16. In the Navigation bar, click Open.
If the “How do you want to open this type of file (.json)?” message is
17. displayed, click More options, and then click Microsoft Visual Studio
Version Selector.
On the EIDT menu of the OperasApi.json – Microsoft Visual Studio
18.
window, point to Find and Replace, and then click Quick Find.
In the Search Item box of the Quick Find dialog box, type Rigoletto, and
19.
then click Find Next.
20. In the Microsoft Visual Studio dialog box, click OK.
In the Quick Find dialog box, click the Close button.

21. Note: Visual Studio finds the JSON data for the Rigoletto opera. Note that
this is just one entry in the JSON data, which includes all operas in the web
application.
In the OperasApi.json – Microsoft Visual Studio window, click the Close
22.
button
In the Address bar of the Windows Internet Explorer window, type
23. http://localhost: <yourPortNumber>/api/OperasApi/3, and then click Go
to.
24. In the Navigation bar, click Open.
If the “How do you want to open this type of file (.json)?” message is
25. displayed, click More options, and then click Microsoft Visual Studio
Version Selector.
In the 3.json - Microsoft Visual Studio window, note that only the
26. information relating to the Nixon in China opera is displayed.
Note: The value for the OperasID parameter corresponding to the Nixon in
China opera is 3.
27. In the 3.json - Microsoft Visual Studio window, click the Close button.
28. In the Windows Internet Explorer window, click the Close button.
In the OperasWebSite – Microsoft Visual Studio window, click the Close
29.
button.

Lesson 2: Calling a Web API from Mobile and Web


Applications
After you complete the development of the Web API services, you need to create
the client applications to call these services. Calling Web API services is
different from calling WCF services. However, the methods that you need to use
to call these services are similar, regardless of the platform. You need to know
how to call Web API services by using server-side code, jQuery code and
JSON.NET library, to effectively implement Web API services in most
application platforms.

Lesson Objectives
After completing this lesson, you will be able to:

o Call Web APIs by using server-side code.


o Call Web APIs by using jQuery.
o Call Web APIs by using Windows Phone applications.

Calling Web APIs by Using Server-Side Code


You can call REST-style services by using ASP.NET server-side code. You can
use the HttpWebRequest class to create a manual HTTP request to the REST
services. ASP.NET provides a .NET library that you can use in web applications
to call REST-enabled Web API services from the .NET server. To use the .NET
library, you need to install the Microsoft.AspNet.WebApi.Client NuGet
package. This NuGet package provides access to the HttpClient class. The
HttpClient class simplifies interacting with Web APIs, because it reduces coding
efforts.

After installing the NuGet package, you need to initialize the HttpClient class.
The following code illustrates how to initialize the HttpClient class.

Initializing the HttpClient Class

HttpClient client = new HttpClient();

client.BaseAddress = new Uri("http://localhost/");

client.DefaultRequestHeaders.Accept.Add(new

MediaTypeWithQualityHeaderValue("application/json"));

The last line of code in the preceding code sample informs the client system
about the media type that the client system should use. The default media type
that applications use is application/json. However, applications can use any
other media type, based on the media type that the REST-style services support.
The following code shows how to call Web API REST services by using server-
side code.

Calling the API from Server-Side Code

HttpResponseMessage response = client.GetAsync("api/customers").Result;

if (response.IsSuccessStatusCode)

var products =

response.Content.ReadAsAsync<IEnumerable<Customer>>().Result;

else

Console.WriteLine("{0} ({1})", (int)response.StatusCode,

response.ReasonPhrase);

After running the code in the preceding code sample, you need to define a data
model that aligns itself with the one used by the Web API service to enable the
.NET library to:

o Process the results of the server-side code.


o Return results as .NET objects for the application to use.

Then, you can use the GetAsync and ReadAsAsync methods to:

o Create requests to Web API REST services.


o Parse the content into .NET objects.
The PostAsJsonAsync function uses the HTTP POST method to call Web API
services that support the POST method.

Question: What is the benefit of using the Microsoft.AspNet.WebApi.Client


NuGet package?

Calling Web APIs by Using jQuery Code

You can call Web API services in the same manner as you call other services that
use technologies such as WCF. You can also call Web API services by using the
jQuery ajax function.

The following code shows how to call a Web API service by using the jQuery
ajax function.

Using the jQuery ajax Function

$.ajax({

url:

'http://localhost/api/customers/,

type: 'GET',

dataType: 'json',
success: function (data) {

},

error: function (e) {

});

In the preceding code sample, observe the dataType parameter of the ajax
function. You should set this parameter to json or another data type that the Web
API service supports. Most applications use JSON because it is light weight. The
ajax function has built-in functionalities that parse JSON results for the ease of
developers.

You can use JSON.stringify() in the data parameter of the ajax function to
serialize the JavaScript objects into JSON objects for sending to the Web API
method. The following code shows how to use JSON.stringify() in the data
parameter of the ajax function.

Using the stringify function

var customer = {

ID:'1',

CustName: 'customer 1'

};

$.ajax({

url: 'http://localhost/api/customer',
type: 'POST',

data:JSON.stringify(customer),

contentType: "application/json;charset=utf-8",

success: function (data) {

},

error: function (x) {

});

Question: What is the benefit of using JSON.stringify() in the ajax function?

Calling Web APIs Using Windows Phone Applications

You can use NuGet packages to call Web API REST services in .NET
applications. However, in Windows Phone web applications, you need to use the
JSON.NET library to call Web API REST services. The JSON.NET library is
more light weight and it enhances the performance of Windows Phone
applications. You can download the library from

http://go.microsoft.com/fwlink/?LinkID=288993&clcid=0x422

The JSON.NET library contains a set of .NET classes that help create JSON
requests to any REST-style
APIs. To use the JSON.NET library, you need to download it and place the
JSON.NET assembly in the /WindowsPhone folder of the /bin folder.

The following code shows how to call an HTTP request by using the WebClient
class.

Using the WebClient Class

WebClient webClient = new WebClient();

Uri uri = new Uri("http://localhost/api/customer/");

webClient.DownloadStringCompleted += new

DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);

webClient.DownloadStringAsync(uri);

When you make a request by using the WebClient class, the JSON.NET library
processes the request and produces results from the WebClient class to return
.NET objects. When you call Web APIs by using the library, you need to add the
DownloadStringCompleted event handler. This event handler helps place logic
to handle the data that Web APIs return.

In the DownloadStringCompleted event handler, you should add the code


similar to the following.

Coding the Event Handler

using Newtonsoft.Json;

/// Lines skipped

List<Customer> customers =

JsonConvert.DeserializeObject<List<Customer>>(e.Result);
foreach (Customer em in customers)

The code in the preceding sample helps enable the JSON.NET library to
deserialize the results into .NET objects.

Question: What is the key benefit of using the JSON.NET library?

Lab: Implementing APIs in ASP.NET MVC 4 Web


Applications
Scenario

Your manager wants to ensure that the photos and information stored in the
Photo Sharing application can be integrated with other data in web mash-ups,
mobile applications, and other locations. To re-use such data, while maintaining
security, you need to implement a RESTful Web API for the application. You
will use this Web API to display the locations of photos on a Bing Maps page.

Objectives

After completing this lab, you will be able to:

o Create a Web API by using the new features of ASP.NET MVC 4.


o Add routes and controllers to an application to handle REST requests.
o Call a REST Web API from jQuery client-side code.

Lab Setup

Estimated Time: 60 minutes

Virtual Machine: 20486B-SEA-DEV11


User name: Admin

Password: Pa$$w0rd

Note: In Hyper-V Manager, start the MSL-TMG1 virtual machine if it is not


already running.

Before initiating this lab, perform the following steps:

Apply the Snapshot of the virtual machine, 20486B-SEA-DEV11, that was


a.
taken after completing the lab in module 13.
Navigate to Allfiles (D):\Labfiles\Mod
b.
13\Starter\PhotoSharingApplication\PhotoSharingApplication, and then
copy the web.config file.
Navigate to Allfiles (D):\Labfiles\Mod
c.
14\Starter\PhotoSharingApplication\PhotoSharingApplication, and then
paste the web.config file.
Enable the Allow NuGet to download missing packages during build
option, by performing the following steps:

On the TOOLS menu of the Microsoft Visual Studio window, click


d. i. Options.
ii. In the navigation pane of the Options dialog box, click Package Manager.
Under the Package Restore section, select the Allow NuGet to download
iii.
missing packages during build checkbox, and then click OK.

Exercise 1: Adding a Web API to the Photo Sharing Application

Scenario

You have been asked to implement a Web API for the Photo Sharing application
to ensure that photos can be used in third-party websites, mobile device
applications, and other applications.
In this exercise, you will

o Add a Web API controller for the Photo model class.


o Configure formatters and routes to support the Web API.
o Test the API by using Internet Explorer.

The main tasks for this exercise are as follows:

1. Add a Photo API controller.


2. Configure API routes.
3. Configure media-type formatters.
4. Test the Web API with Internet Explorer.

Task 1: Add a Photo API controller.

Start the virtual machine and log on with the following credentials:

1. o Virtual machine: 20486B-SEA-DEV11


o User name: Admin
o Password: Pa$$w0rd
Open the PhotoSharingApplication solution from the following location:

2.
File location: Allfiles
o
(D):\Labfiles\Mod14\Starter\PhotoSharingApplication
Add a new API controller to the PhotoSharingApplication project by using
the following information:
3.
o Name: PhotoApiController
o Template: Empty API controller
Add a using statement for the following namespace to
PhotoApiController.cs:
4.
o PhotoSharingApplication.Models
Add a new variable to the PhotoApiController class by using the following
information:

5. o Scope: private
o Type: IPhotoSharingContext
o Name: context
o Initial value: a new PhotoSharingContext object
Add a new action to the PhotoApiController by using the following
information:

6. o Scope: public
o Return type: IEnumerable<Photo>
o Name: GetAllPhotos
o Parameters: none
In the GetAllPhotos action, return the context.Photos collection as an
7.
enumerable object.
Add a new action to the PhotoApiController by using the following
information:

8. o Scope: public
o Return type: Photo
o Name: GetPhotoById
o Parameters: an integer named id
In the GetPhotoById action, pass the id parameter to the
9. context.FindPhotoById() method. Store the returned Photo object in a
variable named photo.
If the photo variable is null, throw a new HttpResponseException and pass
10.
the HttpStatusCode.NotFound value.
11. At the end of the GetPhotoById action, return the photo object.
Add a new action to the PhotoApiController by using the following
information:
12.
o Scope: public
o Return type: Photo
o Name: GetPhotoByTitle
o Parameters: a string named title
In the GetPhotoByTitle action, pass the title parameter to the
13. context.FindPhotoByTitle() method. Store the returned Photo object in a
variable named photo.
If the photo variable is null, throw a new HttpResponseException and pass
14.
the HttpStatusCode.NotFound value.
15. At the end of the GetPhotoByTitle action, return the photo object.
16. Save all the changes.

Task 2: Configure API routes.

In the WebApiConfig.cs code file, in the Register method, remove all existing
1.
route registrations.
Add a new route to the Register method by using the following information:

o Name: PhotoApi
2. o Route template: api/photos/{id}
o Default controller: PhotoApi
o Default action: GetPhotoById
o Constraint: id= "[0-9]+"
After the PhotoApi route, add a new route to the Register method by using the
following information:

3. o Name: PhotoTitleApi
o Route template: api/photos/{title}
o Default controller: PhotoApi
o Default action: GetPhotoByTitle
After the PhotoTitleApi route, add a new route to the Register method by
4. using the following information:
o Name: PhotosApi
o Route template: api/photos
o Default controller: PhotoApi
o Default action: GetAllPhotos
5. Save all the changes.

Task 3: Configure media-type formatters.


In the WebApiConfig.cs code file, at the end of the Register method, create a
1. new variable named json. Set this variable to
config.Formatters.JsonFormatter.
Set the json.SerializerSettings.PreserveReferencesHandling property to
2.
Newtonsoft.Json.PreserveReferencesHandling.Objects.
3. Remove the XmlFormatter object from the config.Formatters collection.
4. Save all the changes.

Task 4: Test the Web API with Internet Explorer.

1. Start that web application in debugging mode.


Request the photo with ID 4 by using the Web API. Display the returned JSON
2. file by using Visual Studio and check that the Title property is Sample Photo
4.
Request the photo with title Sample Photo 5 by using the Web API. Display
3. the returned JSON file by using Visual Studio and check that the Title
property is Sample Photo 5.
Request all photos by using the Web API. Display the returned JSON file by
4. using Visual Studio, and check that both Sample Photo 9 and Sample Photo
13 are present.
5. Close Visual Studio and stop debugging.

Results: At the end of this exercise, you will be able to create a simple Web API
for an ASP.NET MVC 4 web application.

Exercise 2: Using the Web API for a Bing Maps Display


Scenario

You need to use the new Web API to obtain the photos in the client-side jQuery
code. You will use latitude and longitude properties to display these photos as
pins on a Bing API map.

To create the map display in the Photo Sharing application, you must add a new
view and action for the photo controller. You must also add a new template view
because the Bing Maps AJAX control requires a different <!DOCTYPE>
directive to the one in use elsewhere in the Photo Sharing application. You will
import a JavaScript file with basic Bing Maps code in place. To this JavaScript
file, you will add code to call the Web API, obtain photo details, and display
them on the map.

In this exercise, you will:

o Create a new template view.


o Create a map action, view, and script file.
o Obtain and display photos.
o Test the Bing Maps control.

The main tasks for this exercise are as follows:

1. Create a new template view.


2. Create a map action, view, and script file.
3. Obtain and display photos.
4. Test the Bing Maps control.

Task 1: Create a new template view.


In the Views/Shared folder, create a copy of the _MainLayout.cshtml view
1.
file and name the copy as _MapLayout.cshtml.
In the _MapLayout.cshtml file, replace the <!DOCTYPE html> declaration
with <!DOCTYPE html PUBLIC "-//W3C/DTD XHTML 1.0
2.
Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-
transitional.dtd">.
In the onload event of the BODY element, call the GetMap() JavaScript
3.
function.
4. Remove the links to jQueryUI and unobtrusive AJAX.
Add a new link to the Bing Maps AJAX control in the HEAD element by
using the following information:

5. o Charset: UTF-8
o Type: text/javascript
o SRC: http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0
6. Save all the changes.

Task 2: Create a map action, view, and script file.

Add a new action to the PhotoController class by using the following


information:

1. o Scope: public
o Return type: ViewResult
o Name: Map
o Parameters: none
2. In the new Map action, return a View named Map.
Add a new view for the Map action by using the following information:

3. o View name: Map


o Type: Do not create a strongly-typed view
o Layout: _MapLayout.cshtml
4. Remove the H2 element from the Map.cshmtl view.
5. Add a new JavaScript block to the Map.cshtml view.
In the new JavaScript block, create a new variable named webApiUrl by
6. using the Url.Content() helper to set the webApiUrl variable to
~/api/photos.
Create a new variable named pictureUrl by using the Url.Action() helper to
7. set the pictureUrl variable to the URL of the GetImage action of the Photo
controller. Include a forward slash at the end of the URL.
Create a new variable named displayUrl by using the Url.Action() helper to
8. set the displayUrl variable to the URL of the Display action of the Photo
controller. Include a forward slash at the end of the URL.
Add a new JavaScript script, with an empty src attribute, to the Map.cshtml
9.
view.
Use the Url.Content() helper to set the src attribute in the new JavaScript
10.
code to ~/Scripts/MapDisplay.js.
Create a new DIV element by using the following information:

o ID: mapDiv
11. o Style position: absolute

o Style width: 650px


o Style height: 400px
Add the MapDisplay.js JavaScript file to the Scripts folder from the
following location:
12.
o Allfiles (D):\Labfiles\Mod14\Bing Maps Script
Add a new node to the site map by using the following information:

o Title: Map
13. o Visibility: *

o Controller: Photo
o Action: Map
14. Save all the changes.
15. Start the web application in debugging mode and browse to the Map page.
16. Stop debugging.

Task 3: Obtain and display photos.


In the MapDisplay.js script file, add a new function by using the following
information:
1.
o Name: GetPhotos
o Parameter: serviceUrl
2. Set the $.support.cors value to true.
Use the $.ajax() jQuery function to call the GetPhotos Web API by using the
following information:

o URL: serviceUrl
3. o Type: GET
o Data type: json
o Success: DisplayPics
o Error: OnError
Add a new function by using the following information:

4. o Name: DisplayPics

o Parameter: response
5. In the DisplayPics function, create two variables named location and pin.
Use the jQuery $.each function to loop through all the photo objects in the
6.
response collection.
For each photo object in the response collection, set the location variable to
a new location by using the following information:

7. o Object: Microsoft.Maps.Location
o Latitude: photo.Latitude
o Longitude: photo.Longitude
Set the pin variable to a new push pin by using the following information:

8. o Object: Microsoft.Maps.Pushpin

o Location: location
Set the pin.Title property to photo.Title and the pin.ID property to
9.
photo.PhotoID.
Ensure that the DisplayInfoBox method handles the click event for pushpins
by using the following information:

10. o Method: Microsoft.Maps.Events.addHandler


o Object: pin
o Event: 'click'
o Handler method: DisplayInfoBox
Add the pin object to the dataLayer object by using the dataLayer.push
11.
function.
Add a new function by using the following information:

12. o Name: OnError

o Parameter: response
In the OnError function, use the alert function to inform the user that the
13.
picture coordinates could not be obtained.
At the end of the GetMap function, call the GetPhotos function and pass the
14.
webApiUrl variable.
15. Save all the changes.

Task 4: Test the Bing Maps control.

Start the web application in debugging mode and browse to the Map page to
1.
check the map control.
2. Click a pin of your choice.
3. Click the thumbnail.
4. Stop debugging and close Visual Studio.

Results: After completing this exercise, you will be able to create a template
view to display a Bing Map AJAX control, and create a view and script file to
display a Bing Map. You will also use jQuery to call a Web API and obtain
details of photos. You will then mash up the data from a web API with Bing
Maps data.
Question: How do the API actions you added to the PhotoApiController
controller in Exercise 1 differ from other actions in MVC controllers?

Module Review and Takeaways


You can use the Web API framework to facilitate creating REST-style Web API
calls in applications. REST-style Web API is recommended for mobile
applications because of the light weight design of REST services.

REST services use HTTP methods such as GET, POST, and PUT to notify the
API of the action that it needs to perform. Web APIs use the media formatter and
the JSON.NET library to serialize and deserialize information, respectively. You
can call Web API services by using server-side code, jQuery code, and the
JSON.NET library.

Real-world Issues and Scenarios

Consider that you develop a mobile application by using Web APIs and the
application needs to use currency rate services. For this application, you cannot
use WCF, because WCF can impede the performance of the application by using
XML for data exchanges. Therefore, you should use REST and JSON in the
application to reduce the data that is transmitted between the client system and
the server.

Review Question(s)

Question: We are developing a mobile application, which requires to access


business data via internet. You are proposing to use Web API but your colleague
is proposing to use WCF. What would be the key point for using Web API in this
scenario?

 Module 15:
Aspecto destacadoNotaExpandir aspecto destacadoExpandir nota

Handling Requests in ASP.NET MVC 4 Web


Applications
Contents:
Module Overview

Lesson Using HTTP Modules and HTTP Handlers


1:

Lesson Using Web Sockets


2:

Lab: Handling Requests in ASP.NET MVC 4 Web Applications

Module Review and Takeaways

Module Overview
ASP.NET MVC provides functionalities that help develop web applications.
However, ASP.NET MVC does not include functionalities that help change the
encoding of the output. In such cases, you need to know how to use an HTTP
module or HTTP handler, to facilitate such specific requests. Most web
applications require two-way communication between the client and server
systems. The web sockets protocol facilitates two-way communications in a
robust manner.

Objectives
After completing this module, you will be able to:

o Use HTTP modules and HTTP handlers.


o Use web sockets.

Lesson 1 : Using HTTP Modules and HTTP


Handlers
Applications perform actions on a request in the HTTP pipeline, before rendering
a webpage. You need to know how to use an HTTP module to implement custom
authentication mechanism for a webpage, before rendering the webpage. You can
also use an HTTP module to create code that renders content in a non-default
encoding format that fits application needs. Sometimes, you may need the
application to handle requests by using application logic that differs from the
built-in ASP.NET page rendering logic. In such cases, you should know how to
use the HTTP handler to process such specific requests.

Lesson Objectives
After completing this lesson, you will be able to:

o Describe how HTTP modules intercept web requests.


o Create HTTP modules.
o Describe how HTTP handlers intercept web requests.
o Create HTTP handlers.
o Determine when to use HTTP modules and HTTP handlers.

What Is an HTTP Module?


An HTTP module is a program that runs application logic on a webpage, before
ASP.NET renders the webpage. To understand the relevance of an HTTP
module, you need to know about the HTTP request pipeline. The IIS HTTP
request pipeline is a sequence of programs that run on requests, to help the
application perform tasks. When the application receives a request, it passes the
request to the isapi_aspnet.dll ISAPI library and starts the ASP.NET execution
pipeline, to process the request.

Then, the request passes through the

HttpApplication instance of the application and the HttpModule library.

HTTP modules provide the following features to an application:

Security. Provide support for the custom authentication and authorization logic
o
of your application
Logging and statistics. Gather low-level information about the web application
o
execution cycle, for monitoring and logging purposes
Custom headers and footers. Allow insertion of custom header information in
o
the response of each request

The following is a list of HTTP modules in ASP.NET:

o OutputCache
o Session
o WindowsAuthentication
o FormsAuthentication
o PassportAuthentication
o UrlAuthorization
o FileAuthorization
o DefaultAuthentication

If you configure HTTP modules in an application, HTTP modules apply to all the
HTTP requests that the application receives. You cannot configure an HTTP
module for a specific page.

Question: What are the benefits of using HTTP modules in web applications?

Creating HTTP Modules

You can create an HTTP module by adding the CustomModule class to your
project; this class implements the IHttpModule interface in your application.

The following code shows how to create the CustomModule class in a project.

Coding a Custom Module

public class CustomModule : IHttpModule

public CustomModule ()
{

public String ModuleName

get { return "CustomModule"; }

public void Init(HttpApplication application)

context.Response.Write("<h1>Demo<h1>");

In the CustomModule class, you need to implement the following two methods:

ModuleName property. Provides a display name that enables other application


o
code to identify the HTTP module.
Init function. Provides the location to implement all logic for an HTTP module.
o The HttpApplication class triggers this function when the application receives
a request.

After you complete the development of an HTTP module, you need to register
the HTTP module in the Web.config file. The following code shows how to
register an HTTP module for an application running in IIS 6.0 or later versions,
configured in the Classic mode.

Registering an HTTP Module for IIS 6.0


<configuration>

<system.web>

<httpModules>

<add name="CustomModule" type="CustomModule "/>

</httpModules>

</system.web>

</configuration>

The following code shows how to register an HTTP module for an application
running in IIS 7.0 or later versions, configured in the Integrated mode.

Registering an HTTP Module for IIS 7.0 or Later

<configuration>

<system.webServer>

<modules>

<add name="CustomModule" type="CustomModule"/>

</modules>

</system.webServer>

</configuration>

Question: You have developed a custom HttpModule. What must you do to


ensure that your ASP.NET application uses the custom module developed?
What Is an HTTP Handler?

HTTP modules help apply logic to all HTTP requests that an application
receives. The HttpHandler function is a processing engine that processes
specific HTTP requests. For example, you can configure an HttpHandler
function to handle *.ashx files. You can map an HttpHandler function to a URL
based on the file extension of the requested server-side page, such as *.aspx.

The following list describes some common HttpHandler functions:

ASP.NET page handler (*.aspx). This is the default HTTP handler for
o
ASP.NET pages.
Web service handler (*.asmx). This is the default HTTP handler for web
o
service pages.
Generic web handler (*.ashx). This is the default HTTP handler for all web
o handlers that do not have a user interface and include the @WebHandler
directive.
Trace handler (trace.axd). This is a handler that helps display page trace
o
information.

You can use the *.ashx file extension with the Http handler because:

o The extension does not include any page-rendering logic.


The extension allows developers to write logic to send responses to the client
o
systems.
You can use a custom HTTP handler with the *.rss extension, to generate Real
Simple Syndication (RSS) feed content for user requests. You can also use a
custom handler to request images from the database and send the images to the
client systems.

Question: What is the primary use of the HTTP generic handler (*.ashx)?

Discussion: Scenarios for HTTP Modules and Handlers

Consider the following scenarios. In each case, discuss with the rest of the class
to determine whether an HttpModule or HttpHandler best suits the case.

You are creating a photo sharing application, and you want to enable each user
to discuss photos and cycling trips with their friends. You need to ensure that
o
the application renders photos to users, from the database table, without
requiring users to first save the file on their system.
You are creating a Representational State Transfer (REST)-based business
o application programming interface (API) that requires a custom HTTP header,
before accepting a request.
o You are creating a business API to provide content in custom XML format.
You developing an application that requires saving diagnostic information
o
about the header of an HTTP request.

Lesson 2: Using Web Sockets


AJAX technologies are constantly evolving. The HTTP protocol does not cater to
crucial requirements such as real-time information updates from the server. You
need to know how to use web sockets to create two-way communication between
the client and server systems. You also need to know when to use the traditional
HTTP model and the web sockets protocol, based on the needs of your
application.

Lesson Objectives
After completing this lesson, you will be able to:

o Describe the WebSocket protocol.


o Describe how to create web sockets connections.
o Determine when to use web sockets.
o Add a web sockets-based application to an ASP.NET MVC 4 web application.

What Is the WebSocket Protocol?

The WebSocket protocol is a standard from the World Wide Web Consortium
(W3C). The HTML 5 specification includes support for web sockets.

Additional Reading: For more information about the WebSocket protocol, go


to:

http://go.microsoft.com/fwlink/?LinkID=288994&clcid=0x423
The protocol facilitates two-way communication between web browsers and web
servers. The

protocol helps overcome the issue of HTTP not providing two-way


communication.

Developers often build two-way communication applications by using inefficient


techniques such as long running loops and polling. These techniques consume
large amounts of memory and other resources of both the server and client
systems. The WebSocket protocol resolves the problems that arise with using
such techniques by creating a constant socket connection between the client and
server. All communication between the client and server systems then occurs
through the socket. This socket eliminates the need to re-create a request multiple
times, during real-time communications between the client and server systems.
Remember that all browsers may not support web sockets. Microsoft Internet
Explorer 10 and Windows 8 applications, which use JScript and HTML5, do
support web sockets. Latest versions of Chrome, Safari, and Firefox also support
web sockets.

The web sockets work in a similar manner as traditional network sockets. The
only difference is that during the initial handshake, web sockets use the Upgrade
HTTP request that includes the Upgrade HTTP header. If the server accepts web
sockets, the server returns a response with the status code, 101. Then, the client
and server systems send the payload by using the socket. When the client system
no longer requires communication with the server, the application sends a close
connection payload, to notify the server to close the web socket.

Question: What is the key difference between traditional HTTP and web
sockets?

Coding Web Sockets Connections


To use web sockets, you need to implement server-side services that can handle
the two-way communication between the server and the client systems. To
simplify the programming work, Microsoft provides the Microsoft.WebSockets
NuGet package. This package includes a library that helps handle web socket
operations on the server. While coding web sockets, you can:

Use the Web API framework to create a REST service that handles the initial
o
handshake.
Use the WebSocket library to promote
o
communication between the client and server systems.

The following code shows how to create a REST service and use the WebSocket
library, to handle the operations of web sockets on the server.

Using the Web Sockets Library

public class ChatController : ApiController

public HttpResponseMessage Get(string username)

{
HttpContext.Current.AcceptWebSocketRequest(new

ChatWebSocketHandler());

return Request.CreateResponse(HttpStatusCode.SwitchingProtocols);

class ChatWebSocketHandler : WebSocketHandler

public ChatWebSocketHandler()

public override void OnOpen()

public override void OnMessage(string message)

Observe the Get function in the preceding code sample. The ASP.NET engine
maps this function to a URL and the controller with a GET request. After the
initial handshake:
o The WebSocket library establishes the web socket at the client and server end.
The application passes the handling of communications to the
o
ChatWebSocketHandler class inherited from the WebSocketHandler class.

Whenever the client system sends a message to the service application hosted on
the web server, the message triggers the OnMessage function. The OnMessage
function enables you to respond to the message.

To ensure that a message triggers the OnMessage function, you need to add the
following code to the Web.config file.

Configuring Web Sockets

<configuration>

<appSettings>

<add key="aspnet:UseTaskFriendlySynchronizationContext"

value="true" />

</appSettings>

</configuration>

On the client side, you can use the WebSocket object to establish two-way
communication between the client and server systems. The following code shows
how to use the WebSocket object in JavaScript.

Calling Web Sockets from the Browser

$(document).ready(function () {

websocket = new WebSocket('ws://localhost/api/service1');

websocket.onopen = function () {
};

websocket.onerror = function (event) {

};

websocket.onmessage = function (event) {

};

websocket.send('Hello');

websocket.close();

});

The preceding code sample shows how to add JavaScript functions to respond to
events. The following list describes some common JavaScript functions.

onmessage. You can use this function when the client system receives a
o
message from the server.
onopen. You can use this function when the WebSocket library establishes the
o
web socket.
o onerror. You can use this function when an error occurs.

To send a message in JavaScript, you can use the WebSocket.send() function.


After all communications between the client and server systems end and you no
longer need the web socket connection, you can use the WebSocket.close()
function. This function helps close the web socket communication channel
between the client and server systems.

Question: What is the purpose of using Web APIs to create a service for
handling web sockets?

What Is SignalR?
SignalR is a set of components that simplifies the development of bidirectional
real-time web applications, such as chat rooms in websites.

SignalR uses WebSockets wherever possible to connect. This means that it


supports all HTML5 compatible browsers. A key advantage of using SignalR is
that it supports remote procedure calls (RPCs) with HTML or even .NET
applications and can automatically switch to periodic polling for older browsers.

To install the package to your application, you can use NuGet to find the
package,

Microsoft.AspNet.SignalR.

After installation, you can implement the server-side code for the server logic.

To use SignalR, you need to implement a class that inherits from SignalR library.
The following example broadcasts a message to all clients when a message is
received from one client.

Coding SignalR Connections

using System.Threading.Tasks;

using Microsoft.AspNet.SignalR;

public class DemoConnection : PersistentConnection


{

protected override Task OnReceived(IRequest request, string

connectionId, string

data)

return Connection.Broadcast(data);

After the server code is implemented, you need to add ASP.NET routing to map
the URL back to the SignalR library. The following code maps the /demo URL to
the DemoConnection library for handling the message communication by using
SignalR.

Mapping SignalR URLs

public class Global : System.Web.HttpApplication

protected void Application_Start(object sender, EventArgs e)

RouteTable.Routes.MapConnection<DemoConnection>("demo", "/demo");

}
SignalR also includes a JavaScript library that can be used by clients to help
perform communications between client and server. The SignalR library depends
on the jQuery library.

The following JavaScript code sends a message to the server, receives a message
back, and displays the received message.

Client-Side SignalR Code

<script src="http://code.jquery.com/jquery-1.7.min.js"

type="text/javascript"></script>

<script src="Scripts/jquery.signalR-1.0.1.min.js"

type="text/javascript"></script>

<script type="text/javascript">

$(function () {

var connection = $.connection('/demo);

connection.received(function (data) {

alert(data);

});

connection.start().done(function() {

$("#broadcast").click(function () {

connection.send('Hello');

});

});
});

</script>

Question: What is the key benefit of using SignalR, instead of WebSockets


directly?

Demonstration: How to Add a Chat Room to a Web


Application by using SignalR
In this demonstration, you will see how to add a simple chat room to a web
application by using SignalR.

Demonstration Steps
In the Solution Explorer pane of the OperasWebsite – Microsoft Visual
1. Studio window, right-click OperasWebSite, point to Add, and then click
Class.
In the Name box of the Add New Item – OperasWebSite dialog box, type
2.
ChatHub, and then click Add.
In the ChatHub.cs code window, locate the following code.
3.
using System.Web;

Place the mouse cursor at the end of the located code, press Enter, and then
type the following code.
4.

using Microsoft.AspNet.SignalR;
In the ChatHub.cs code window, locate the following code.
5.
public class ChatHub

Replace the located code with the following code.


6.
public class ChatHub : Hub
In the ChatHub class code block, type the following code.

public void Send(string name, string message)

7.
{

In the Send method code block, type the following code.

Clients.All.broadcastMessage(name, message);

8.
Note: The Send() method sends any message received, back to all the clients
that are connected to the hub. You need to define the broadcastMessage()
method in the client-side code to receive messages. The client-side code must
also call the Send() method to broadcast messages.
In the Solution Explorer pane, expand Views, expand Home, and then click
9.
Chat.cshtml.
In the Chat.cshtml code window, within the final <script> element, type the
following code.

10. $(function() {

});

Within the anonymous function you just created, type the following code.
11.
var chat = $.connection.chatHub;

Place the mouse cursor at the end of the variable you just created, press Enter,
and then type the following code.

12. chat.client.broadcastMessage = function (name, message) {

};
Note: This function is the implementation of the broadcastMessage()
function that you called in the Hub code.
Within the anonymous function you just created, type the following code.
13.
var listItem = '<li>' + name + ': ' + message + '</li>';

Place the mouse cursor at the end of the variable you just created, press Enter,
and then type the following code.
14.
$('#discussion').append(listItem);

Place the mouse cursor at the end of the broadcastMessage function code
block, press Enter, and then type the following code.
15.
var displayname = prompt('Enter your name:', '');

Place the mouse cursor at the end of the displayname variable code block
you just created, press Enter, and then type the following code.
16.
$('#chat-message').focus();

Place the mouse cursor at the end of the code block you just created, press
Enter, and then type the following code.

17. $.connection.hub.start().done(function () {

});

Within the anonymous function code block you just created, type the
following code.

18. $('#sendmessage').click(function () {

});
Within the new anonymous function code block you just created, type the
following code.
19.
chat.server.send(displayname, $('#chat-message').val());

Place the mouse cursor at the end of the code block you just created, press
Enter, and then type the following code.
20.
$('#chat-message').val('').focus();

On the DEBUG menu of the OperasWebSite – Microsoft Visual Studio


21.
window, click Start Debugging.
On the Operas I Have Seen page, click the Enter the Operas Chat Room
22.
link.
In the Enter your name box of the localhost needs some information
23.
dialog box, type Rebecca Laszlo, and then click OK.
In the Message box of the Operas I Have Seen page, type a message of your
choice, and then click Send.
24.
Note: SignalR sends the message you typed to the hub. The hub broadcasts
the message to all connected clients.
On the taskbar, right-click the Internet Explorer icon, and then click
25.
Internet Explorer.
In the Address bar of the Internet Explorer window, type
26.
http://localhost:<portnumber>, and then press Enter.
On the Operas I Have Seen page, click the Enter the Operas Chat Room
27.
link.
In the Enter your name box of the localhost needs some information
28.
dialog box, type Elisa Graceffo, and then click OK.
In the Message box of the Operas I Have Seen page, type a message of your
29.
choice, and then click Send.
On the taskbar, click the first instance of the Internet Explorer window. Note
30. that the message from Elisa Graceffo is displayed because both users are
connected to the same hub.
31. Close all the Internet Explorer windows.
In the OperasWebSite – Microsoft Visual Studio window, click the Close
32.
button.

Lab: Handling Requests in ASP.NET MVC 4 Web


Applications
Scenario

The Adventures Works board and managers are pleased with the Photo Sharing
application, but have requested that interactivity should be maximized to
encourage users to register and participate fully in the community. Therefore,
you have been asked to add chat functionality to the application. Authenticated
members should be able to start a chat on a particular photo from the Display
view. Chat rooms for each photo should be separated from each other. Users in
the chat room should be able to send a message to all other users in that chat
room, and they should be able to see all the messages that have been sent since
they joined the chat room.

You have decided to use SignalR to implement the chat room over Web Sockets.

Objectives

After completing this lab, you will be able to:

o Install SignalR in an ASP.NET MVC 4 web application.


o Configure SignalR on the server and create a SignalR hub.
o Link to the required script files for SignalR in an MVC view.
o Create the script for SignalR connections and send messages to groups.

Lab Setup

Estimated Time:

60 minutes
Virtual Machine: 20486B-SEA-DEV11

User Name: Admin

Password: Pa$$w0rd

Note: In Hyper-V Manager, start the MSL-TMG1 virtual machine if it is not


already running.

Before initiating this lab, perform the following steps:

Apply the Snapshot of the virtual machine, 20486B-SEA-DEV11, that was


a.
taken after completing the lab in module 13.
Navigate to Allfiles (D):\Labfiles\Mod
b.
13\Starter\PhotoSharingApplication\PhotoSharingApplication, and then
copy the Web.config file.
Navigate to Allfiles (D):\Labfiles\Mod
c.
15\Starter\PhotoSharingApplication\PhotoSharingApplication, and then
paste the Web.config file.
Enable the Allow NuGet to download missing packages during build
option, by performing the following steps:

On the TOOLS menu of the Microsoft Visual Studio window, click


d. i. Options.
ii. In the navigation pane of the Options dialog box, click Package Manager.
Under the Package Restore section, select the Allow NuGet to download
iii.
missing packages during build checkbox, and then click OK.

Exercise 1: Creating a SignalR Hub

Scenario
Before you can write JScript code on the client to connect to SignalR, you must
configure and code a SignalR Hub on the web server.

In this exercise, you will:

o Install SignalR in the Photo Sharing application.


o Configure routing.
Create a SignalR hub to accept messages from clients and forward those
o
messages to other clients who are chatting about the same photo.

The main tasks for this exercise are as follows:

1. Install SignalR.
2. Create a Hub class.
3. Configure SignalR routes.

Task 1: Install SignalR.

Start the virtual machine, and log on with the following credentials:

1. o Virtual machine: 20486B-SEA-DEV11


o User name: Admin
o Password: Pa$$w0rd
Open the PhotoSharingApplication.sln file from the following location:
2.
File location: Allfiles
o
(D):\Labfiles\Mod15\Starter\PhotoSharingApplication
In the NuGet Package Manager, search for the following pre-release
package:
3.
o Microsoft.aspnet.signalr
Install the Microsoft ASP.NET SignalR package in the
4.
PhotoSharingApplication project.
Notice the additions that the NuGet package has made to the project references
5.
and the Scripts folder.

Task 2: Create a Hub class.

1. Add a new class file named ChatHub.cs to the PhotoSharingApplication.


Remove the following namespace references from the ChatHub.cs class file:

2. o System.Collections.Generic;

o System.Linq;
Add the following namespace references to the ChatHub.cs class file:

3. o System.Threading.Tasks

o Microsoft.AspNet.SignalR
Ensure that the ChatHub class inherits from the
4.
Microsoft.AspNet.SignalR.Hub class.
In the ChatHub class, create a new method by using the following
information:

5. o Scope: public
o Return type: Task
o Name: Join
o Parameter: an integer named photoId
In the Join method, return the result of the Groups.Add() method by using
the following information:
6.
o Connection ID: Context.ConnectionId
o Group name: "Photo" + photoId
In the ChatHub class, create a new method by using following information:

7. o Scope: public
o Return type: Task
o Name: Send
o First parameter: a string named username
o Second parameter: an integer named photoId
o Third parameter: a string named message
In the Send method, create a new string variable named groupName and set
8.
the value to "Photo" + photoId.
In the Send method, return the result of the addMessage method for the
groupName group by using the following information:

9. o Method: Clients.Group(groupName).addMessage()
o User name: username
o Message: message
10. Save all the changes.

Task 3: Configure SignalR routes.

In the Global.asax code-behind file, add a reference to the


1.
Microsoft.AspNet.SignalR namespace.
In the Application_Start() method, immediately after the RegisterAllAreas()
2.
code, call the RouteTable.Routes.MapHubs() method.
3. Save all the changes.

Results: After completing this exercise, you will be able to install SignalR in an
MVC 4 web application, configure routes for SignalR, and create a hub to
receive and forward simple text messages.

Exercise 2: Creating a Photo Chat View

Scenario

Now that you have set up and configured SignalR and a SignalR hub on the
server side, you must use JScript and the SignalR JScript library to send and
receive messages on the client side.

In this exercise, you will:


Create a new MVC controller action and Razor view to display the chat user
o
interface for a particular photo.
Link to the JScript libraries that SignalR requires and write client-side script to
o
call the Join() and Send() methods on the hub.
o Test the chat functionality.

The main tasks for this exercise are as follows:

1. Create a chat action and view.


2. Link to the chat view.
3. Link to JScript files.
4. Script SignalR connections.
5. Script SignalR messages.
6. Test the chat room.

Task 1: Create a chat action and view.

Add a new action to the PhotoController class by using the following


information:

o Annotation: [Authorize]
1. o Scope: public
o Return type: ActionResult
o Name: Chat
o Parameter: an integer named id
Create a new Photo object named photo and get the photo value by passing
2.
the id parameter to the context.FindPhotoById() method.
3. If the photo object is null, return an HTTP Not Found status code.
At the end of the action, return the Chat view and pass the photo object as the
4.
model class.
Add the following view file to the Views/Photo folder:
5.
o Allfiles (D):\Labfiles\Mod15\Chat View\Chat.cshtml
6. Save all the changes.

Task 2: Link to the chat view.

In the Display.cshtml view file, after the DIV element with ID


1.
addtofavorites, add a new DIV element, with ID chataboutthisphoto.
In the new DIV element, render a link to the Chat view by using the following
information:

2. o Helper: Html.ActionLink()
o Text: Chat about this photo
o View: Chat
o Route values: pass the Model.PhotoID value to the id parameter.
Start the web application in the debugging mode, display a photo of your
3.
choice, and then click Chat.
Log on with the following credentials:

4. o User name: David Johnson

o Password: Pa$$w0rd2
5. Attempt to send a chat message.
6. Stop debugging.

Task 3: Link to JScript files.

Add a new SCRIPT element at the end of the Chat.cshtml view file, with
1.
type text/javascript.
In the new SCRIPT element, create a new variable named username. In a
2. new Razor code block, use the User.Identity.Name property to set the value
for the variable.
Create a second new variable named photoid and use the Model.PhotoID
3.
property to set the value for the variable.
Add a new SCRIPT element, with type text/javascript, and an empty src
4.
attribute.
In the new script element, use the Url.Content() helper to set the src attribute
to the following path:

5. ~/Scripts/jquery.signalR-1.0.0.js
o
Note: NuGet installs the latest version of SignalR. Ensure that the name of
the script file you enter matches the name of the file in the Scripts folder.
Add a new SCRIPT element, with type text/javascript, and an empty src
6.
attribute.
In the new script element, use the Url.Content() helper to set the src attribute
to the following path:
7.
o ~/signalr/hubs
Add a new SCRIPT element, with type text/javascript, and an empty src
8.
attribute.
In the new script element, use the Url.Content() helper to set the src attribute
to the following path:
9.
o ~/Scripts/ChatRoom.js
10. Save all the changes.

Task 4: Script SignalR connections.

1. Add a new JScript file named ChatRoom.js to the Scripts folder.


In the new JavaScript file, use jQuery to create an anonymous function that
2.
runs when the page loads.
Use the $.connection.chatHub property to obtain the ChatHub you already
3.
created, and then store the hub in a variable named chat.
4. Use jQuery to set the initial focus on the element with ID chat-message.
Create an anonymous function that runs when the $.connection.hub.start()
5.
method is done.
Call the chat.server.join() function on the SignalR hub, pass the photoid
6. value as a parameter, and then create an anonymous function that runs when
the function is done.
7. Save all the changes.

Task 5: Script SignalR messages.

In the ChatRoom.js JScript file, after creating and instantiating the chat
1. variable, set the chat.client.addMessage property to be a new anonymous
function with two parameters, name and message.
In the new function, create a variable named encodedName, and use jQuery to
2. set this variable to a new <div> with the name parameter as its HTML
content.
In the new function, create a variable named encodedMessage, and use jQuery
3. to set this variable to a new <div> with the message parameter as its HTML
content.
Create a new variable named listItem. Set the value of this variable to an
4. HTML LI element that includes the encodedName and encodedMessage
variables.
5. Append the listItem element to the page element with ID discussion.
In the function that runs when the client.server.join() method is done, create
6. an anonymous function that runs when the button with ID sendmessage is
clicked.
In the new anonymous function, call the chat.server.send() method by using
the following information:

7. o User name: username


o Photo ID: photoid
o Message: use the value of the element with ID chat-message
Use jQuery to obtain the element with ID chat-message, set its value to an
8.
empty string, and give it the focus.
9. Save all the changes.
Task 6: Test the chat room.

Start the web application in debugging mode and log on with the following
credentials:
1.
o User name: David Johnson
o Password: Pa$$w0rd2
2. Browse to the chat page for Sample Photo 1.
3. Send a message of your choice and observe the results.
Start a new instance of Windows Internet Explorer, and browse to the Photo
4.
Sharing application home page.
Register a new user account with the following credentials:

5. o User name: Mark Steele


o Password: Pa$$w0rd
Browse to the chat page for Sample Photo 1, and then send a message of your
6.
choice.
Switch to the first instance of Internet Explorer, and then send a second
7.
message of your choice. Observe the messages sent between the two users.
8. Stop debugging and close Visual Studio.

Results: After completing this exercise, you will be able to create MVC
controller actions and views to display a user interface for SignalR functionality,
link to the JScript libraries that SignalR requires, and use JScript to connect to a
SignalR hub and send messages.

Question: In the chat functionality that you created, each photo in the Photo
Sharing application has a separate chat room. How is this separation possible
with one SignalR hub?

Question: In Exercise 2, you wrote JScript code that called the


chat.server.join() and chat.server.send() functions. In which script file are these
functions defined?
Module Review and Takeaways
Most web applications do not limit themselves to rendering HTML content. They
require functionalities that support custom logic such as custom authentication.
To suit such cases, you can use HTTP modules and HTTP handlers to run custom
logic before or after rendering a webpage. The web socket technology in MVC 4
provides support for two-way communication between client and server systems.
This technology is useful for web applications that require constant updates
between the client and server systems.

Real-world Issues and Scenarios

You create an application that obtains the latest product pricing information from
the internal database. The pricing is constantly updated every time business users
feel the need for updates. Therefore, you need to ensure that the application
updates pricing information every five minutes. In such cases, you can to use the
web socket technology to implement price update. You can also add code to
download the product image stored in the product database by using a generic
handler (*.ashx file).

Review Question(s)

Question: You want to select technology that could be used for developing a
web based chatting applications for your client. Which technology would you
prefer in this scenario?

 Module 16:
Aspecto destacadoNotaExpandir aspecto destacadoExpandir nota

Deploying ASP.NET MVC 4 Web Applications


Contents:
Module Overview
Lesson Deploying a Web Application
1:

Lesson Deploying an ASP.NET MVC 4 Web Application


2:

Lab: Deploying ASP.NET MVC 4 Web Applications

Module Review and Takeaways

Module Overview
After developing an application, you need to deploy the application to the
production environment to make the application available to users. The
configuration or deployment method of each application varies based on the
setup of the production environment. ASP.NET MVC applications have some
special considerations such as the configuration needed for IIS.

Objectives

After completing this module, you will be able to:

o Configure and deploy an ASP.NET web application.


o Deploy an ASP.NET MVC 4 web application.

Lesson 1 : Deploying a Web Application


The considerations for deploying a web application to a web farm are different
for single and multi-server configurations. For example, in multi-server web
farms, you need to ensure that the state information is available on all web
servers. You also need to ensure that the dependencies needed for hosting
ASP.NET MVC 4 web applications are present in the web farm. If any of the
application dependencies are missing on the production web servers, some or all
of your applications may not function and users may encounter errors. You need
to apply special considerations while deploying web applications on Windows
Azure. Deploying a web application on Windows Azure provides advantages
such as high availability and flexibility.

Lesson Objectives
After completing this lesson, you will be able to:

Ensure that dependencies are present for hosting ASP.NET MVC4


o
applications.
o Deploy an ASP.NET MVC4 web application to a single-server web farm.
o Deploy an ASP.NET MVC4 web application to a multi-server web farm.
o Deploy an ASP.NET MVC 4 web application on Windows Azure.

ASP.NET MVC 4 Dependencies


ASP.NET MVC 4 is built on the ASP.NET Framework 4.0. Each web
application requires a range of different components to be present on the web
server, to function appropriately.

Examples of common requirements include:

The ASP.NET Framework 4.0 Common Language Runtime (CLR). The CLR
runs any managed code such as C# classes. All ASP.NET web applications
o
require the CLR, and you can install the CLR with Internet Information
Services (IIS).
The ASP.NET MVC 4 runtime. The

ASP.NET MVC 4 runtime locates controllers and actions to handle each


o request that the web application receives, and it returns the compiled webpages
to users. You can install the MVC runtime in your web application by installing
the MVC 4 NuGet package. All MVC web applications require the MVC
runtime.
A Database server. Most web applications use a database to store information
such as product details, customer details, images, and other entities. You need
to ensure that the production environment supports the database that you used
o during development. For example, if you use SQL Compact during
development, you need to ensure that Microsoft SQL Compact is installed on
the production server. Alternatively, you can migrate the database to Microsoft
SQL Server.
Entity Framework. If you use Entity Framework to model data in your web
o application, you need to ensure that you deploy the framework with your
application.
Membership Providers. If your application uses membership providers to store
user accounts and roles, you need to ensure that these providers are available on
the server. The .NET Framework includes the SQL Server Membership
o
Provider. If you use the Universal Membership Providers by installing the
NuGet package, you need to ensure that you include the NuGet package with
your deployed application.
Question: Which of the common requirements in the above list is required to
support forms authentication?

Deploying Web Applications to Web Servers

Before you deploy a web application to a production IIS web server, you must
create and configure the IIS application and the folder that hosts the application.

Creating an IIS Web Application

You need to host ASP.NET MVC 4 web applications in an IIS web folder that is
marked as a web application starting point. You can use the Internet Service
Manager tool to configure this setting on the top-level folder of the web
application. When you mark a web folder as a web

application, you enable IIS to recognize that the

content of the folder is ASP.NET and requires the ASP.NET runtime engine to
process each request.

After creating an application, you need to configure the application to use .NET
4.0 or above. This practice enables ASP.NET MVC 4 to run, because the MVC
runtime components are part of the .NET framework.

IIS Application Pools


In IIS, web applications are run within a context known as an application pool.
You can run many applications in the same application pool or install an
application in its own isolated pool. Applications that run in the same application
pool share the following resources:

Worker Process. The worker process uses a single execution process to run all
o
the applications in a pool.
Memory. The applications share a single memory range, because the
o
applications in a pool share a single worker process.
o Identity. The applications within a single pool share a user account.

You can place two or more applications in an application pool, and thereby
reduce the total memory usage, because the applications share memory.
However, this arrangement can reduce the reliability of each application, because
a malfunctioning application can affect all the applications in the pool. To
maximize the reliability of an application, you should install the application in an
isolated pool that runs only one specific application.

The shared identity within an application pool affects the way the applications
authenticate resources such as database servers when using integrated
authentication. Each application within a pool shares a single user account. If
each application has a separate database, you need to set permissions, to enable
the user accounts to access all the databases. If you separate applications into
isolated pools, you can use a different user account for each application. This
practice can enhance the security of the application, because each account can
access only one database.

Deploying the Application

When the IIS web application is ready, you need to copy the web application
files to IIS. These files include all the model classes, controllers, views, script
files, style sheets, images, and any other content in the Microsoft Visual Studio
ASP.NET MVC 4 project. You can use the deployment tools available in
Microsoft Visual Studio, or other technologies such as FTP, to copy these files.
When the copy operation is complete, the web application is ready for
deployment.

Question: What is the purpose of configuring additional application pools?

Deploying Web Applications to Multi-Server Farms

You can deploy a web application to a multi-server web farm to increase


performance, resilience, and reliability. In a multi-server web farm, a group of
two or more web servers host a single web application. All the servers in the farm
share a single server name, such as www.contoso.com. Windows Network Load
Balancing or dedicated hardware load balancers distribute browser requests to the
servers.

A multi-server farm usually has greater capacity than a single web server,
because the multi-server farm almost equally shares the load amongst

several servers. Multi-server farms also increase reliability. When a server fails
for any reason, the load balancing mechanism automatically directs requests to
another server that remains online.

If you decide to deploy your web application to a multi-server farm, you need to
perform the following steps. To complete these steps, you may need to work with
the web server administrator who is responsible for the server farm:
Create IIS applications and application pools on each server. This step is the
same as configuring the applications and application pools in a single-server
1. scenario. However, you need to perform this step on every server in the farm.
You also need to ensure that applications and application pools have the same
configuration, throughout the farm.
Create a matching IIS configuration on each server. IIS configuration options,
2. such as any encryption certificates, file extensions, and optional components,
should be identical on every server in the farm.
Use external hosted session state or session affinity. You can configure
ASP.NET web applications to store session state in the Windows State Service
or a database. You should use this technique in a multi-server farm, because
each request from a single user session might be directed to a different web
server. Alternatively, by configuring session affinity, you can ensure that all
3. requests from a user session are always sent to the same web server. If you do
not use external hosted session state or session affinity, the user preference on
one web server may get lost when a request is sent to another web server.
Session affinity is supported by some but not all load balancing solutions.
Work with your web server administrator to determine if affinity is available
on your farm.
Configure the machineKey element in the Web.config file. If you are using
external hosted session state, you can encrypt the connection between the web
servers and the State Service server or database server. This technique
improves security by protecting session state during network transmissions.
4. You can configure this encryption by setting up the machineKey element in
the Windows registry.

Additional Reading: For more information about configuring the


machineKey element, go to:
http://go.microsoft.com/fwlink/?LinkID=288995&clcid=0x424

Question: What is the purpose of configuring the machineKey element in the


Web.config file?

Deploying Web Applications on Windows Azure


You can deploy any ASP.NET web application, including ASP.NET MVC 4 web
applications, on Windows Azure. By choosing Windows Azure as a platform,
you can use a highly-available and flexible infrastructure that you can optimize to
cope with intense load. You have a choice of subscriptions, which can help you
to pay only for the traffic that your web application uses.

Deploying a web application on Windows Azure is different from deploying the


application on on-premise versions of IIS. To deploy an application on Windows
Azure, you perform the following

steps:

1. Create a new web application in the Windows Azure management portal.


2. Download and save a publishing profile for the new web application.
In Microsoft Visual Studio, open your web application solution. Then, start the
3.
Publish wizard and import the publishing profile.
Ensure that you select the correct connection strings for Entity Framework
4.
connections, service database connections, and any other database connections.
5. Complete the Publish wizard.
Observe that Microsoft Visual Studio publishes the web application to
6.
Windows Azure.

When the process is complete, you can access the Windows Azure-hosted web
application from any Internet-connected browser.
Note: At the time of writing, Windows Azure web applications are still in
preview, within the Windows Azure platform.

Windows Azure Web Applications and Windows Azure Cloud


Services

Instead of publishing an ASP.NET MVC web application as a web application in


Windows Azure, you can choose to build and publish a Windows Azure cloud
service. A cloud service is a Windows Azure component that you can use to
build a flexible multi-tiered application, with a discrete architecture. A cloud
service consists of one or more web roles and worker roles, each with its own
application files and configuration.

In a Windows Azure web application, all components of your web application


run in a single process. You can administer the web application as a single object.

Windows Azure cloud services help separate user interface logic that you build in
a web-role project, from business logic that you build in a worker process
project. This separation provides greater flexibility, and it enables calling the
business logic from other processes, such as mobile applications. You can
separately administer web roles and worker processes, and run them in separate
processes. However, to publish a web application as a cloud service with separate
web roles and worker roles, you need to download and install the Windows
Azure SDK. You can download and install the Windows Azure SDK by using
the Web Platform Installer. You can use the Windows Azure cloud service
templates as the starting point for your application.

Question: How does Windows Azure cloud services help enhance the flexibility
of the application?

Demonstration: How to Create a Windows Azure


Website
In this demonstration, you will see how to create a new database and a new
website in Windows Azure.
Demonstration Steps
1. On the taskbar, click the Internet Explorer icon.
In the Address bar of the Internet Explorer window, type
2.
http://www.windowsazure.com, and then click the Go to button.
In the upper-right corner of the Windows Azure: Microsoft’s Cloud Platform
3.
| Cloud Hosting | Cloud Services page, click PORTAL.
On the Sign in to your Microsoft account page, in the Microsoft account
4. box, type <your username>, in the Password box, type Pa$$w0rd, and then
click Sign in.
5. In the left pane of the Windows Azure page, click WEB SITES.
In the lower-left pane of the Windows Azure page, click NEW, and then
6.
click CUSTOM CREATE.
In the URL box of the Create Web Site page, type <your username>operas,
7.
and then, in the REGION box, click <A region near you>.
In the DATABASE box of the Create Web Site page, click Create a new
8. SQL database, in the DB CONNECTION STRING NAME box, type
OperasDB, and then click the Next button.
In the NAME box of the Specify database settings page, type OperasDB, in
9. the SERVER box, click New SQL database server, and then, in the
LOGIN NAME box, type <your first name>.
In the PASSWORD box of the Specify database settings page, type
Pa$$w0rd, in the PASSWORD CONFIRMATION box, type Pa$$w0rd,
10. and then click the Complete button.
Note: Windows Azure creates the new website and database to support the
Operas website.
11. In the Internet Explorer window, click the Close button.

Lesson 2: Deploying an ASP.NET MVC 4 Web


Application
Deploying ASP.NET MVC applications is similar to deploying other ASP.NET
applications. This process is simple and straightforward. However, you need to
update the configuration of the application for use in the production environment.
Microsoft Visual Studio includes features that simplify updating the
configuration of the application. You can also automate the deployment process
by using deployment tools available in Microsoft Visual Studio.

Lesson Objectives
After completing this lesson, you will be able to:

Reconfigure an ASP.NET MVC application to deploy it on a production web


o
server.
Use the Bin Deploy method to deploy the .NET Framework libraries along with
o
your web application.
o Use the deployment tools in Visual Studio.

Reviewing Configuration for Production

Each ASP.NET MVC web application includes a Web.config file. In addition to


this file, Microsoft Visual Studio creates two variance files to specify deployment
transformations to the Web.config file. You can use these variance files for
different build configurations. The variance files include:

The Web.release.config file. This file stores the changes that Microsoft Visual
o Studio applies to the Web.config file, when you compile the application in the
Release mode.
The Web.debug.config file. This file stores
o
the changes that Microsoft Visual Studio applies to the Web.config file, when
you compile the application in the Debug mode.

Microsoft Visual Studio can automatically transform the Web.config file for use
in different environments. Before you publish the application, you can remove
the debug attribute from the Web.config file.

The following code shows how to remove the debug attribute from the
Web.config file by using a deployment transformation.

Removing the Debug Attribute for Deployment

<system.web>

<compilation xdt:Transform="RemoveAttributes(debug)" />

</system.web>

The following code shows how to remove the debug attribute from the
Web.config file by using a deployment transformation.

Removing the Debug Attribute by Using a Deployment Transformation

<system.web>

<compilation xdt:Transform="RemoveAttributes(debug)" />

</system.web>

The preceding code sample uses the xdt:Transform attribute to modify the
existing Web.config file and produce the published Web.config file. You can also
use the Insert value to add additional elements to the resultant Web.config file.
For example, the following code shows how to insert a new connection string
setting in the resultant Web.config file.

Inserting a Connection String

<connectionStrings>

<add name="DemoConnStr" connectionString="Data

Source=|DataDirectory|demo.sdf"

providerName="System.Data.SqlServerCe.4.0" xdt:Transform="Insert"/>

</connectionStrings>

Question: How can you configure the Web.config file for publishing to a
production environment without using the Web.release.config configuration file?

Using Bin Deploy

ASP.NET MVC applications depend on a range of .NET assemblies; these


assemblies ensure that the application functions as required. These assemblies are
dynamic-link library (DLL) files available in your project references. The
assembly files are usually already present on the web server because they are
included as part of the MVC library installation. However, sometimes the web
server administrators do not install all .NET Framework assemblies. Microsoft
Visual Studio provides the Bin Deploy feature to copy all depending assembly
files into a folder within the

deployed web application. This feature helps deploy dependencies on the server.

You can use the Add Deployable Dependencies feature to generate the
_bin_deployableAssemblies folder. This folder includes the following libraries:

o Microsoft.Web.Infrastructure
o System.Web.Helpers
o System.Web.Mvc
o System.Web.Razor
o System.Web.WebPages
o System.Web.WebPages.Deployment
o System.Web.WebPages.Razor

You can choose a specific set of libraries to include in Microsoft Visual Studio.
This practice enables you to ensure that Microsoft Visual Studio deploys the:

o Right assemblies.
o Right versions of the assemblies.

You can then copy the library to the bin folder of the production server, after
adding it to the library of your project.

Question: Why should you use the deployable assembly as part of the
deployment plan?

Using Visual Studio 2012 Deployment Tools


The Publish feature helps generate a copy of the web application when the
application is ready for deployment in the production environment. The feature
includes three methods to deploy the application:

o File Share
o FTP
o Web Deploy

On the Publish web application page, you can publish the application by using
File Share or FTP.

You can use File Share for servers to which you

have direct network access. Alternatively, you can use File Share to publish a
web application first to a local folder. Then, you can manually copy the files to
the web server. File Share also allows you to specify a profile to store all
deployment options. This practice eliminates the need to specify the deployment
options every time you publish the application.

If you select Web Deploy, you can specify database settings, such as connection
strings, in the publishing wizard. These settings will override the settings in the
Web.config file in the target environment. Web Deploy also includes tools to
automatically update the schema of the database. These tools eliminate the need
to manually update the schema. The publishing tool detects all schema changes
and generates scripts to apply those changes to the published database. If your
development and production web servers are isolated from each other, you can
run these generated scripts on the production environment. This practice
replicates schema changes on a server where Microsoft Visual Studio is not
installed.

The following image shows the Publish web application page.

FIGURE 16.1:THE PUBLISH WEB APPLICATION PAGE

Question: What is the benefit of using the Web Deploy publish tool?

Demonstration: How to Deploy a Website to Windows


Azure
In this demonstration, you will see how to obtain a publish profile from Windows
Azure and use it to publish a website from Visual Studio.

Demonstration Steps
1. On the taskbar, click the Internet Explorer icon.
In the Address bar of the Internet Explorer window, type
2.
http://www.windowsazure.com, and then click the Go to button.
In the upper-right corner of the Windows Azure: Microsoft’s Cloud Platform
3.
| Cloud Hosting | Cloud Services page, click PORTAL.
On the Sign in to your Microsoft account page, in the Microsoft account
4. box, type <your username>, in the Password box, type Pa$$w0rd, and then
click Sign in.
5. In the left pane of the Windows Azure page, click WEB SITES.
In the NAME column of the Web Sites – Windows Azure page, click <your
6.
username>operas.
On the Web Sites – Windows Azure page, click DASHBOARD.
7.
Note: If the quick start page appears, repeat the steps 5 and 6 before
proceeding to the next step.
In the quick glance section of the Web Sites – Windows Azure page, click the
8.
Download publish profile link.
9. In the Navigation bar, click Save, and then click the Close button.
10. On the taskbar, click the Microsoft Visual Studio icon.
In the Solution Explorer pane of the OperasWebSite - Microsoft Visual
11.
Studio window, right-click OperasWebSite, and then click Publish.
12. On the Profile page of the Publish Web wizard, click Import.
In the Import Publish Settings dialog box, click <your
13.
username>operas.azurewebsites.net.PublishSettings, and then click Open.
On the Connection page of the Publish Web wizard, click Validate
14.
Connection.
15. If the Certificate Error dialog box appears, click Accept.
16. On the Connection page, click Next.
17. On the Settings page, click Next.
18. On the Preview page, click Start Preview.
On the Preview page, click Publish.
19.
Note: Visual Studio publishes the website. This process can take several
minutes. When the publish operation is complete, the website is displayed in
the Internet Explorer window.
20. If the Certificate Error dialog box appears, click Accept.
In the Internet Explorer window, if the Server Error in ‘/’ Application error
is displayed, click the Refresh button.
21.
Note: If the Operas I Have Seen page does not appear, you need to re-publish
the OperasWebSite project.
22. On the Operas I Have Seen page, click All Operas.
In the Navigation bar, if the message Intranet settings are turned off by
23.
default. is displayed, click Turn on Intranet settings.
If the message Are you sure you want to turn on intranet-level security
24.
settings? appears, click Yes.
On the Index of Operas page, click the Details link corresponding to Cosi
25.
Fan Tutte.
26. On the Opera: Cosi Fan Tutte page, click the Back to List link.
On the Index of Operas page, click the Details link corresponding to Nixon
27.
in China.
28. In the Internet Explorer window, click the Close button.
In the OperasWebSite - Microsoft Visual Studio window, click the Close
29.
button.

Lab: Deploying ASP.NET MVC 4 Web Applications


Scenario

You have completed the development and testing of the photo sharing
application. Your managers and senior developers have signed off the project,
and have requested you to deploy the application to the Adventure Works
Windows Azure account.

Objectives

After completing this lab, you will be able to:


o Prepare an MVC web application for deployment.
o Deploy an MVC web application to Windows Azure.

Lab Setup

Estimated Time: 45 minutes

Virtual Machine: 20486B-SEA-DEV11

User name: Admin

Password: Pa$$w0rd

Note: In Hyper-V Manager, start the MSL-TMG1 virtual machine if it is not


already running.

In this lab, you will create a web application in Windows Azure that runs in Free
mode. Free mode is an excellent tool for testing and running small, non-intensive
web applications. However, there is a limit of 165 megabytes (MB) of data
transfer per day on the Free mode tool. After completing Exercise 2, you are
encouraged to further test the deployed web application. However, if you do a lot
of extra testing, you may encounter the limit and the application may become
unavailable.

Also, before initiating this lab, perform the following steps:

Apply the Snapshot of the virtual machine, 20486B-SEA-DEV11, that was


1.
taken after completing the lab in module 13.
Enable the Allow NuGet to download missing packages during build
2.
option, by performing the following steps:
1. On the TOOLS menu of the Microsoft Visual Studio window, click Options.
2. In the navigation pane of the Options dialog box, click Package Manager.
Under the Package Restore section, select the Allow NuGet to download
3.
missing packages during build checkbox, and then click OK.
Exercise 1: Deploying a Web Application to Windows Azure

Scenario

In this exercise, you will:

o Reconfigure the Photo Sharing application for release deployment.


Configure the Entity Framework initializer class, which fills the database
o with initial data, and ensure that the build configuration and connection strings
are correct.
Create a new web application in Windows Azure and deploy the Photo Sharing
o
application to the new site.

The main tasks for this exercise are as follows:

1. Prepare the Photo Sharing application project for deployment.


2. Create a new website in Windows Azure.
3. Deploy the Photo Sharing application.

Task 1: Prepare the Photo Sharing application project for deployment.

Start the virtual machine, and log on with the following credentials:

1. o Virtual machine: 20486B-SEA-DEV11


o User name: Admin
o Password: Pa$$w0rd
Open the Photo Sharing application solution from the following location:

2.
File location: Allfiles
o
(D):\Labfiles\Mod16\Starter\PhotoSharingApplication.
In the Build properties of the PhotoSharingApplication project, select the
3.
Release configuration.
Log on to the Windows Azure portal by using the following information:
4.
o URL: http://www.windowsazure.com
o User name: <Your Windows Live account name>
o Password: <your password>
Copy the ADO.NET connection string for the PhotoSharingDB to the
5.
clipboard.
In the Web.config file, paste the connection string into the connectionString
6. attribute of the PhotoSharingDB connection string. Set the password in the
pasted connection string to Pa$$w0rd.
Log on to the Bing Maps Account Center web application by using the
following information:

7. o URL: https://www.bingmapsportal.com
o User name: <Your Windows Live account name>
o Password: <Your Windows Live account password>
8. Copy the Bing Maps key.
Replace the text, {Your Bing Key}, in the MapDisplay.js file, with the
9.
copied key.
10. Save all the changes.

Task 2: Create a new website in Windows Azure.

In Windows Azure, create a new website by using the following information:

o URL: <your username>PhotoSharing


o Region: <a region near you>
1. o Database: PhotoSharingDB

o Database connection string name: PhotoSharingDB.


o Database user: <Your first name>
o Password: Pa$$w0rd

Task 3: Deploy the Photo Sharing application.


In Windows Internet Explorer, download the publish profile for the <your
1.
username>PhotoSharing web application.
In Microsoft Visual Studio, start the Publish Web wizard and import the
2.
publish profile you just downloaded.
For the Photo Sharing Context database connection, select the
3.
PhotoSharingDB connection string.
For the Photo Sharing DB database connection, select the PhotoSharingDB
4.
connection string.
For the UsersContext database connection, select the PhotoSharingDB
5.
connection string.
6. Preview the files that require changes, and then publish the web application.

Results: After completing this exercise, you will be able to prepare an ASP.NET
MVC web application for production deployment, create a web application in
Windows Azure, and deploy an MVC web application to Windows Azure.

Exercise 2: Testing the Completed Application

Scenario

You have completed and fully deployed the Photo Sharing web application in
Windows Azure. Now, you want to perform some final functionality tests before
you confirm the completion of the application to your manager.

The main tasks for this exercise are as follows:

1. Add a photo and a comment.


2. Use the slideshow and favorites options.
3. Test the chat room.

Task 1: Add a photo and a comment.


Log on to the Adventure Works Photo Sharing web application by using the
following information:
1.
o User name: David Johnson
o Password: Pa$$w0rd2
Add a new photo to the web application by using the following information:

2. o Title: Test New Photo


o Photo: Allfiles (D):\Labfiles\Mod16\Sample Photos\track.JPG
o Description: This is the first photo added to the deployed web application
3. Display the new photo and check if the data is displayed correctly.
Add a new comment to the new photo by using the following information:

4. o Subject: Functionality Check

o Body: The photo metadata is displayed correctly

Task 2: Use the slideshow and favorites options.

Examine the Slideshow webpage and check that the display of all photos
1.
functions as designed.
2. Add three photos to your favorites list.
3. View the Favorites slideshow.

Task 3: Test the chat room.


1. Enter the chat room for Sample Photo 1.
2. Send a message.
Start a new instance of Internet Explorer and browse to the Photo Sharing
application by using the following information:

3. o URL: http://<yourusername>PhotoSharing.azurewebsites.net
o User name: Mark Steele
o Password: Pa$$w0rd
4. Enter the chat room for Sample Photo 1.
Send a second message and switch to the first instance of Internet Explorer.
5.
Send a third message.
6. Close Internet Explorer and Visual Studio.

Results: After completing this exercise, you will be able to confirm that all the
functionalities that you built in the Photo Sharing application run correctly in the
Windows Azure deployment.

Question: Why is it unnecessary to use bin deployment in this lab?

Question: In the labs for this course, you used the same Windows Azure SQL
Database for both development and production. If you wanted to use separate
databases for development and production, but did not want to reconfigure the
web application every time you deployed to the development and production web
servers, how would you configure the web application?

Module Review and Takeaways


Deployment is usually the last task that developers perform; however, this is the
task that developers do not spend much time on. The target environment usually
impacts the deployment procedure. In the case of Windows Azure, service
packages allow the management portal to deploy the package to the virtual
machine that hosts the workload.

To simplify the deployment process, Microsoft Visual Studio consists of a


number of tools that help developers generate files for deployment. These tools
also help handle the database during deployment. You can also generate the
Web.config file based on the environment that it deploys to.

Review Question(s)

Question: You need to create two packages for deployment-for testing and for
production environment. This is because of the difference in server name and
other environment settings. What should you do?
Course Evaluation
Keep this evaluation topic page if this is the final module in this course. Insert the
Product_Evaluation.ppt on this page.

If this is not the final module in the course, delete this page

Your evaluation of this course will help Microsoft understand the quality of your
learning experience.

Please work with your training provider to access the course evaluation form.

Microsoft will keep your answers to this survey private and confidential and will
use your responses to improve your future learning experience. Your open and
honest feedback is valuable and appreciated.

You might also like