Developing ASP - Net MVC 4 Web Applications
Developing ASP - Net MVC 4 Web Applications
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
Lesson Objectives
After completing this lesson, you will be able to:
Developing Models
Every website presents information about various types of objects. In your web
application, you need to define model classes for these objects.
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.
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.
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.
newPhoto.Owner = User.Identity.Name;
newPhoto.CreatedDate = DateTime.Today;
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.
<div id="photo-title">
@Model.Title
</div>
The model classes usually specify three attributes for each property:
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.
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.
[DisplayName("Created Date")]
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.
[DataType(DataType.DateTime)]
true)]
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?
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.
[Required]
[Range(0, 400)]
[Required]
[RegularExpression(".+\\@.+\\..+")]
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.
Note: You will see how to ensure that the validation error message is displayed
in a view.
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?
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.
To understand the default model binding process, consider the following request
from a web browser:
http://www.adventureworks.com/product/display/45
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.
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
Two ways in which you can extend the MVC handling of MVC models are to
create custom data annotations and custom model binders.
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.
[AttributeUsage(AttributeTargets.Field)]
//Constructor
MinimumValue = minimum;
}
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.
[LargerThanValidationAttribute(18)]
public VoterAge { get; set; }
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.
ModelBindingContext
bindingContext)
//Get the color for the car from the request form
//Get the brand for the car from the request form
string brand= controllerContext.HttpContext.Request.Form["brand"];
newCar.color = color;
newCar.brand = brand;
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.
12. [Required]
[StringLength(200)]
Place the mouse cursor at the end of the Opera class, press Enter, and then
type the following code.
16.
int year = (int)value;
{
return false;
else
return true;
public CheckValidYear()
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:
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.
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.
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.
To use ADO.NET and connect to a database, you need to add two items to your
application:
<connectionStrings>
<add name="PhotoSharingDB"
connectionString="Data Source=.\SQLEXPRESS;Initial
Catalog=PhotoSharingDB;" +
"Integrated Security=SSPI"
providerName="System.Data.SqlClient"/>
</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.
tables and columns found in a database to objects and their properties that you
can call from .NET code.
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.
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.
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?
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.
//This action gets all the photos in the database and passes them to
Details view
if (photo == null)
return HttpNotFound();
}
}
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.
<PhotoSharingDB>
new Photo {
Title = "My First Photo",
UserName = "Fred"
},
new Photo {
UserName = "Sue"
};
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.
//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?
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?
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.
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.
List<Photo> photos;
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
select p).Take(number).ToList();
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>
Place the mouse cursor at the end of the located code, press Enter, and then
type the following code.
11.
using System.Data.Entity;
{ 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;
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.
new Opera {
Composer = "Mozart"
};
operas.ForEach(s =>
context.Operas.Add(s));
context.SaveChanges();
@section Scripts {
29.
@Script.Render("~/bundles/jqueryval")
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
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.
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.
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
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.
ICollection<Comments> comments =
commentRepository.GetComments(PhotoID);
}
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.
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
Username: Admin
Password: Pa$$w0rd
Scenario
Start the virtual machine, and log on with the following credentials:
o Name: PhotoSharingApplication
2. o Location: Allfiles (D):\Labfiles\Mod03
o Solution name: PhotoSharingApplication
o Create directory for solution: True
o Project template: Empty
Results: After completing this exercise, you will be able to create an MVC 4 web
application and add model classes to the web application.
Scenario
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
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
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.
Scenario
Add data annotations to the properties to help MVC web application render
o
them in views and validate user input.
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.
Scenario
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.
Results: After completing this exercise, you will be able to create an MVC
application that uses Windows Azure SQL Database as its data store.
Scenario
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)
Create a new top-level folder, and copy an image to the new folder by using
the following information:
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?
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.
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
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
Lesson Objectives
After completing this lesson, you will be able to:
When an MVC web application receives a request from a web browser, the
following events happen in sequence:
Note: The routing engine determines which controller and action receives a
request. Routing is not covered in this section.
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:
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 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.
Question: What is the convention that you should follow while creating
controllers?
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.
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
if (firstPhoto != null)
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.
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.
[HttpPost]
if (ModelState.IsValid)
context.Photos.Add(photo);
context.SaveChanges();
return RedirectToAction("Index");
else
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.
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.
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.
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.
select p;
if (requestedPhoto != null)
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.
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.
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.
ViewBag.ServerTime = DateTime.Now;
To obtain and use the same properties in a view, you can use the following Razor
code.
<p>
</p>
<p>
</p>
In action methods, you can add data to the ViewData dictionary by using
key/value pairs as the following lines of code illustrate.
ViewData["ServerTime"] = DateTime.Now;
To obtain and use the same values in a view, you can use the following Razor
code.
<p>
</p>
<p>
</p>
In the examples, note that you can cast any ViewData values other than strings.
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.
new OperasDB();
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.
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.
}
In the Create action code block, type the following code.
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
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.
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.
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.
string
ControllerName)
targetType = typeof(PhotoController);
else
targetType = typeof(GeneralPurposeController);
(IController)Activator.CreateInstance(targetType);
public SessionStateBehavior
GetControllerSessionBehavior(RequestContext
requestContext,
string controllerName)
return SessionStateBehavior.Default;
if (disposable != null)
disposable.Dispose();
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.
Even if you create a custom controller factory in your application, MVC will still
use the DefaultControllerFactory class, unless you register your custom
factory.
ControllerBuilder.Current.SetControllerFactory(new
AdWorksControllerFactory());
Question: Can you create a controller that does not end with “Controller”?
Lesson Objectives
After completing this lesson, you will be able to:
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
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
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.
filterContext)
filterContext)
filterContext)
}
public override void OnResultExecuted(ResultExecutedContext
filterContext)
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.
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.
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.
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
Password: Pa$$w0rd
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.
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.
Start the virtual machine, and log on with the following credentials:
o Scope: private
6.
o Class: PhotoSharingContext
o Name: context
Edit the code in the Index action by using the following information:
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:
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:
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.
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.
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.
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.
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.
Scenario
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.
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
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.
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?
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 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
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 Objectives
After completing this lesson, you will be able to:
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.
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.
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.
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?
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.
<p>Razor will not interpret any character in this line as code, because
there is no “at”
symbol</p>
<p>
</p>
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.
@(
)
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.
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.
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.
A Razor Comment
@* This text will not be rendered by the Razor view engine, because this
is a comment. *@
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”.
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”.
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.
@ {
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)
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:
<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?
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.
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.
@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.
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.
@model IEnumerable<MyWebSite.Models.Product>
<h1>Product Catalog</h1>
<div>Name: @Product.Name</div>
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 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?
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.
The following table describes and compares four popular view engines.
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.
developers
<ul>
with
experience in
<% foreach(var p in model){%>
ASP.NET
View Description Code Example
Engin
e
Web Forms
View
Engine. It
includes
good
IntelliSense
feedback.
</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.
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.
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 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.
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.
actions.
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 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:
new { id = 1 })"
/>
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?
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 .
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?
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.
<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.
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.
"multipart/form-data" }))
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?
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">
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 following code example renders a label for the CreatedDate property.
Using the Html.LabelFor() 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.
name="Title">
rows="20"
set;}
cols="80">
name="ContactMe">
public bool ContactMe { get; set;
}
Control Model Class Property HTML Rendered by
EditorFor()
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.
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?
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 following code example renders a validation message for the LastName
property of the model class.
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))
<p>
@Html.LabelFor(model =>
11.
model.Title):
@Html.EditorFor(model =>
model.Title)
@Html.ValidationMessageFor(
</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):
model.Year)
@Html.ValidationMessageFor(
</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>
model.Composer):
@Html.EditorFor(model =>
model.Composer)
@Html.ValidationMessageFor(
</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")
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 Objectives
After completing this lesson, you will be able to:
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:
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.
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.
@model IEnumerable<Adworks.Models.Comment>
<ul>
<li>
</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?
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.
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.
@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.
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.
})
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?
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
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
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
Password: Pa$$w0rd
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.
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.
Start the virtual machine, and log on with the following credentials:
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.
Scenario
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.
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
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:
Results: After completing this exercise, you will be able to create a web
application with a Razor view to display new photos.
Scenario
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.
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.
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.
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:
Add a new Controller to the home page by using the following information:
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
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?
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.
Review Question(s)
Verify the correctness of the statement by placing a mark in the column to the
right.
Statement Answer
Objectives
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.
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
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.
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.
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.
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:
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?
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.
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?
data, such as data from a database, can be easily be replaced with classes that
deal with test data.
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.
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.
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:
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.
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.
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.
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.
[TestMethod]
//Arrange phase
testProduct.Type = "CompleteBike";
//Act phase
//Assert phase
Assert.AreEqual(typeof(IEnumerable(BikeAccessory)), result.GetType());
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.
A Repository Interface
}
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:
The following code example shows how to implement the repository interface in
your MVC project for use in production and development.
T IWebStoreContext.Add<T>(T entity)
return Set<T>().Add(entity);
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().
The following code example shows how to implement a repository class for tests.
{
//This object is a keyed collection we use to mock an
set { _map.Use<Product>(value); }
_map.Get<T>().Add(entity);
return entity;
where p.ProductID == ID
select p).First();
return item;
}
_map.Get<T>().Remove(entity);
return entity;
if (Contains(typeof(T)))
Remove(typeof(T));
Add(set);
return set;
}
public HashSet<T> Get<T>() { return (HashSet<T>) this[typeof(T)];
return item.GetType().GetGenericArguments().Single();
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.
[TestMethod]
new Product(),
new Product ()
}.AsQueryable();
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?
Scenario Context
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.
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.
controller factory
public ProductController()
context
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 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()
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();
as ViewResult;
Assert.AreEqual("WrongName",
result.ViewName);
23. Assert.AreEqual("WrongName",
result.ViewName);
24. Assert.AreEqual("Index",
result.ViewName);.
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.
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.
Lesson Objectives
After completing this lesson, you will be able to:
Unhandled Exceptions
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.
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.
try
ex.Message);
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.
if (filterContext.Exception is InvalidOperationException)
actionName);
ViewName = "Error",
//Save pass the current Temp Data to the Error view, because
it often
contains
//diagnostic information
TempData = context.Controller.TempData
};
context.Result = result;
[HandleError(ExceptionType=typeof(NotImplementedException),
View="NotImplemented")]
[HandleError]
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
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.
▪ 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.
<system.web>
</system.web>
In the following example, the <error> element is used for specific HTML files
to respond to HTTP 500 errors.
</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?
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
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.
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.
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.
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.
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.
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.
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.
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.
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.
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 records. Each event is within one of the five following
categories.
Audit Events Audit events include logons, logoffs, and logon failures.
Event Category Description
You can also customize the location where health monitoring stores event details
by configuring health monitoring providers. You can choose from the following
providers.
The following code example shows how to configure health monitoring to record
application life cycle events to a SQL Server database.
<system.web>
<connectionStrings>
/>
</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"
</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.
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?
Objectives
After completing this lab, you will be able to:
Lab Setup
Password: Pa$$w0rd
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.
Scenario
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.
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
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.
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.
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.
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.
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
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?
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.
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.
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
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
Lesson Objectives
After completing this lesson, you will be able to:
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.
Category
▪ Furnace
o ▪ FAQ
▪ User Manual
▪ Installation Manual
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.
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.
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:
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.
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.
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.
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 Objectives
After completing this module, you will be able to:
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.
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 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.
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:
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:
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?
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:
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.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{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.
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}",
);
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.
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.
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:
return View(PhotoID);
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
In the following example, the route added includes an optional color 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 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.
In the DetailsByTitle action code block, type the following code, and then
press Enter.
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();
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}",
);
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.
The following code shows how to create a fake HTTP context object to use as a
test double.
An HTTP Context Test Double
FakeHttpRequestForRouting _request;
FakeHttpResponseForRouting _response;
Application path in
the test
requestUrl = "~/")
requestUrl);
string _appPath;
string _requestUrl;
requestUrl)
_appPath = appPath;
_requestUrl = requestUrl;
{
public override string ApplyAppPathModifier(string virtualPath)
return virtualPath;
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.
[TestMethod]
{
//This test checks the default route when only the controller is
specified
//Arrange
"~/ControllerName");
MyMVCApplication.RouteConfig.RegisterRoutes(routes);
// Act
// 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 Objectives
After completing this lesson, you will be able to:
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.
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 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?
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.
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
<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
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.
<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">
action="Index"
key="AllProducts">
action="Display">
</mvcSiteMapNode>
</mvcSiteMapNode>
action="DisplayLatest" >
/>
</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?
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.
@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.
@Html.MvcSiteMap().SiteMapPath()
The Html.MvcSiteMap() helper also includes functions that you can use to
render node titles and complete site maps.
Additional Reading:
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.
/>
Place the mouse cursor at the end of the site map menu code block, press
Enter, and then type the following code.
16.
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:
You have also been asked to implement the following navigation controls in the
Photo Sharing application:
These navigation controls will be added to the menu after the completion of the
main site areas.
Objectives
Lab Setup
Username: Admin
Password: Pa$$w0rd
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.
Scenario
Start the virtual machine, and log on with the following credentials:
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:
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:
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.
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.
Scenario
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.
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
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?
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.
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 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
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.
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.
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
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.
<!DOCTYPE html>
<html>
<head>
<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.
Additional Reading: For more information about layouts and sections, you can
see: http://go.microsoft.com/fwlink/?LinkID=288965&clcid=0x409
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.
@{
ViewBag.Title = "Details";
Layout = "~/Views/Shared/SiteLayout.cshtml";
<h2>Details</h2>
@section MenuBar {
}
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.
@{
Layout = "~/Views/Shared/SiteLayout.cshtml";
Lesson Objectives
After completing this lesson, you will be able to:
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?
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.
<!DOCTYPE html>
<html>
<head>
<title>@ViewBag.Title</title>
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.
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 {
The following CSS snippet shows how to create the class selector.
.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.
ViewBag.Title = "Details";
Layout = "~/Views/Shared/SiteLayout.cshtml";
<h2>Details</h2>
@section MenuBar {
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?
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>
<div class="topmenu">
</div>
<div class="breadcrumb">
@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 Index.cshtml code window, locate the following code, select the code,
and then press Delete.
<!DOCTYPE html>
<html>
24. <head>
</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;
Lesson Objectives
After completing this lesson, you will be able 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.
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?
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.
screen and
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.
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.
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?
Additional Reading: For more information about creating webpages for mobile
device browsers, go to
http://go.microsoft.com/fwlink/?LinkID=288966&clcid=0x409
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.
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.
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
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?
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
Username: Admin
Password: Pa$$w0rd
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.
Scenario
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.
Start the virtual machine, and log on with the following credentials:
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.
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.
Add a new view to the web application by using the following information:
▪ <!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.
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.
Scenario
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.
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.
3. o Type: text/css
o Relation: stylesheet
o Href: ~/content/PhotoSharingStyles.css
4. Save the _MainLayout.cshtml file.
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.
Scenario
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?
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)
Module 09:
Aspecto destacadoNotaExpandir aspecto destacadoExpandir nota
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
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 Objectives
After completing this lesson, you will be able to:
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:
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
An Example View
@{
Layout = null;
<!DOCTYPE html>
<html>
<head>
<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.
@{
Layout = null;
<!DOCTYPE html>
<html>
<head>
<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.
//
// GET: /Default1/
{
ViewBag.Message = "Hello";
return View();
[HttpGet]
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?
@{
Layout = null;
<!DOCTYPE html>
<html>
<head>
<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>
HttpMethod = "POST",
</div>
</body>
</html>
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.
Lesson Objectives
After completing this lesson, you will be able to:
Caching:
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?
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.
[OutputCache(Duration = 60)]
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.
return PartialView();
The following code shows how to add the VaryByCustom property to the
OutputCache attribute.
Using VaryByCustom
{
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?
System.Data.DataTable dtCustomer =
System.Runtime.Caching.MemoryCache.Default.
AddOrGetExisting("CustomerData", this.GetCustomerData(),
System.DateTime.Now.AddHours(1));
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?
You can implement HTTP caching in the Browser Cache and the Proxy 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
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
Additional Reading: For more information about setting this header, go to:
http://go.microsoft.com/fwlink/?LinkID=288972&clcid=0x409
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 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;
VaryByParam="none")]
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.
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
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
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.
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.
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:
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 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.
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.
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.
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.
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.
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.
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"?
Review Question(s)
Module 10:
Aspecto destacadoNotaExpandir aspecto destacadoExpandir nota
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
Lesson Objectives
After completing this lesson, you will be able to:
<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.
The following example shows how to reference the new JavaScript file in HTML
pages.
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.
<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.
<body>
<div>
Hello
</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
You can reduce the time taken to develop applications by using JavaScript
libraries.
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.
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.
<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.8.0.js"
type="text/javascript"></script>
Question: How can CDN help improve the performance of a web 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 Steps
Note: There is no folder named Scripts at the top level of the project.
Place the mouse cursor before the located code, type the following code, and
then press Enter.
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.
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 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 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?
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 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.
To use bundling and minification in your web application, you should perform
the following steps:
{
bundles.Add(new
System.Web.Optimization.ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-
{version}.js","~/Scripts/JavaScript1.js"));
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.
Question: What are the benefits of using the minified version of jQuery in the
production environment?
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:
The following example adds an event handler to the click event of the
HelloButton HTML element.
$("#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.
$(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
</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?
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”.
$('#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.
$('#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.
Question: If querying HTML DOM returns multiple HTML elements, how will
jQuery functions handle these elements?
type: "POST",
dataType: "json",
url: "Customer.asmx/GetCustomerInfo",
data: "{'ID': '123'}",
},
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
Introduction to jQueryUI
jQuery Widgets
You can add different types of widgets to your pages by using the following
jQuery functions:
jQuery Effects
You can add various effects by using the following jQuery functions:
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.
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 Steps
Place the mouse cursor immediately before the located code, type the
following code, and then press Enter.
<script>
8.
$(function() {
$("#reviews-tool").accordion();
});
</script>
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
Lab Setup
Password: Pa$$w0rd
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.
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.
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.
Start the virtual machine, and log on with the following credentials:
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.
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.
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
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.
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.
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.
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?
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
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
Lesson Objectives
After completing this lesson, you will be able to:
ActiveDirectoryMembershipProvider, SqlMembershipProvider,
SimpleMembershipProvider, and UniversalProviders. The
SimpleMembershipProvider and
Claims-Based Authentication
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.
Federated Authentication
Federations rely on claims-based authentication to allow external parties such as
trusted companies to access their applications.
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.
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.
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.
The following code shows how to add the Authorize attribute to your controller
class.
[Authorize()]
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.
[AllowAnonymous()]
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 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]
[HttpPost]
8.
Place the mouse cursor before the located code, type the following code, and
then press Enter.
9.
[Authorize]
Lesson Objectives
After completing this lesson, you will be able to:
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.
AddUsersToRoles function.
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.
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.
RoleProvider
The following code shows how to apply the custom role provider to the
application.
Configuring a Site to Use a Custom Role Provider
cacheRolesInCookie="false">
<providers>
<clear />
</providers>
</roleManager>
<membership
defaultProvider="SimpleMembershipProvider"
>
<providers>
<clear/>
<add name="SimpleMembershipProvider"
</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.
[Table("UserProfile")]
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
The following code shows how the membership provider connects to the User
table, by using the DBConn connection string.
WebSecurity.InitializeDatabaseConnection(“DBConn”,”User”,”id”,”Username”,
false)
[Authorize]
[InitializeSimpleMembership]
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.
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.
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.
<membership defaultProvider="CustomMemberProvider">
<providers>
<clear/>
</providers>
</membership>
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
catch (Exception)
changePasswordSucceeded =
4. Membership.Provider.ChangePassword(User.Identity.Name,
model.OldPassword, model.NewPassword);
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:
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
Lab Setup
Password: Pa$$w0rd
Before starting the lab, you need to enable the Allow NuGet to download
missing packages during build option, by performing the following steps:
Scenario
You want to use a Windows Azure SQL database to store user accounts and
membership information.
In this exercise, you will:
Start the virtual machine, and log on with the following credentials:
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.
Scenario
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.
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:
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:
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.
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.
Scenario
Now that you have enabled and tested authentication, you can authorize access to
resources for both anonymous and authenticated users.
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:
Results: At the end of this exercise, you will have authorized anonymous and
authenticated users to access resources in your web application.
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.
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.
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:
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?
Review Question(s)
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
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
Lesson Objectives
After completing this lesson, you will be able to:
Cross-Site Scripting
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
ViewBag.Msg = msg;
return View();
The following code shows how to display the value of the querystring parameter
in a view.
<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.
<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.
After importing the AntiXSS library in your MVC application, you can use the
library to encode any output content in HTML.
@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.
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:
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.
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.
@using (Html.BeginForm())
@Html.AntiForgeryToken();
@Html.EditorForModel();
[HttpPost]
[ValidateAntiForgeryToken()]
Return View();
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.
Request.QueryString["user"] + "'";
select userID from Users where userID = '1' AND 1=1 GO SELECT * from
0=''
In this case, SQL returns everything from the Users table.
Question: What is the best way to prevent SQL injection attacks if you cannot
avoid dynamic SQL?
Potentially dangerous content can include any HTML markup or JavaScript code
in the body, header, query string, or cookies of the request.
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.
<system.web>
</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.
[HttpPost]
[ValidateInput(false)]
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]
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.
[RequireHttps]
[RequireHttps]
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 Objectives
After completing this lesson, you will be able to:
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.
o Hidden fields
o Cookies
o Query strings
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.
o Application state
o Session state
o TempData
o Profile properties
o Database support
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:
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?
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:
ber \aspnet_state.exe
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.
<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.
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:
Consider that a session state is stored on the SampleSqlServer SQL Server. The
following code shows how to configure the SQLServer mode.
<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.
Question: Which tool should you install before using the SQLServer mode?
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.
<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.
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.
{
return View();
Place the mouse cursor at the end of the located code, press Enter twice, and
then type the following code.
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.
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"})
The senior developer has asked you to implement the following functionality in
your Photo Sharing web application.
Objectives
Lab Setup
Password: Pa$$w0rd
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:
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:
Start the virtual machine, and log on with the following credentials:
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.
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.
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.
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.
Create the user interface components for the favorite photos functionality.
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?
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
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.
Objectives
After completing this module, you will be able to:
Lesson Objectives
After completing this lesson, you will be able to:
Microsoft hosts Windows Azure in multiple data centers, across the United
States, Europe, and Asia.
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?
Question: What are the key benefits of using Windows Azure web applications?
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
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?
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:
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]
[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.
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 RoleEntryPoint class helps define the following three life-cycle methods:
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.
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.
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.
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:
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
The following code shows how to include the Diagnostic module in the
ServiceDefinition.csdef file.
<ServiceDefinition name="MyHostedService"
xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinit
ion">
<WebRole name="WebRole1">
<Imports>
</Imports>
</WebRole>
</ServiceDefinition>
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
config.WindowsEventLog.DataSources.Add("System!*");
DiagnosticMonitor.Start("Microsoft.WindowsAzure.Plugins.Diagnostics.Conne
ctionString",
config);
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
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.
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.
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.
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:
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:
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()
ViewBag.Response = response.GetHelloWorldResult;
return View();
}
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.
[ServiceContract]
[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.
function CallService() {
$.ajax({
type: 'POST',
url: 'http://<guid>.cloudapp.net/service1.svc/GetHelloWorld',
data: '{}',
dataType: “json”,
processdata: true,
success: function(msg) {
ServiceSucceeded(msg);
},
});
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 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.
</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>
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.
$.ajax({
type: "POST",
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");
Objectives
Lab Setup
Password: Pa$$w0rd
Before initiating this lab, you need to perform the following steps:
Scenario
Start the virtual machine, and log on with the following credentials:
Create a new Bing Maps key in the Photo Sharing application by using the
following information:
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.
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.
Task 1: Add a new Windows Azure Cloud Service project to the web
application.
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 Annotation: [OperationContract]
o Return type: string
o Name: GetLocation
o Parameter: a string named address
3. Save all the changes.
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.
.
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.
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.
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.
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.
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.
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.
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?
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
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
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:
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.
[{"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?
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.
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.
routes.MapHttpRoute(
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.
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.
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.
HttpGet GET
HttpPut PUT
HttpPost POST
HttpDelete DELETE
The following code illustrates the use of the HttpGet attribute on the FindProduct
action.
[HttpGet]
}
In the preceding code sample, observe that the HTTP attributes only allow
mapping of one HTTP verb to an action in the controller.
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.
[AcceptVerbs("GET", "HEAD")]
[AcceptVerbs("MKCOL")]
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")]
[HttpPost]
[ActionName("Thumbnail")]
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.
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.
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
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
Web API can return this data in one of two formats: JavaScript Object Notation
(JSON) or XML.
Both JSON and XML are text formats that represent information as strings. You
can also use
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
</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.
{
}
Question: Why should you use a media formatter for Web API REST services?
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.
routes.MapHttpRoute(
"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.
routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
);
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]
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.
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.
}
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.
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. {
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 Objectives
After completing this lesson, you will be able to:
After installing the NuGet package, you need to initialize the HttpClient class.
The following code illustrates how to initialize the HttpClient class.
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.
if (response.IsSuccessStatusCode)
var products =
response.Content.ReadAsAsync<IEnumerable<Customer>>().Result;
else
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:
Then, you can use the GetAsync and ReadAsAsync methods to:
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.
$.ajax({
url:
'http://localhost/api/customers/,
type: 'GET',
dataType: 'json',
success: function (data) {
},
});
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.
var customer = {
ID:'1',
};
$.ajax({
url: 'http://localhost/api/customer',
type: 'POST',
data:JSON.stringify(customer),
contentType: "application/json;charset=utf-8",
},
});
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.
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.
using Newtonsoft.Json;
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.
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
Lab Setup
Password: Pa$$w0rd
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
Start the virtual machine and log on with the following credentials:
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.
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.
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.
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.
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.
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:
o ID: mapDiv
11. o Style position: absolute
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.
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:
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.
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?
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.
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)
Module 15:
Aspecto destacadoNotaExpandir aspecto destacadoExpandir nota
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:
Lesson Objectives
After completing this lesson, you will be able to:
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
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?
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.
public CustomModule ()
{
context.Response.Write("<h1>Demo<h1>");
In the CustomModule class, you need to implement the following two methods:
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.
<system.web>
<httpModules>
</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.
<configuration>
<system.webServer>
<modules>
</modules>
</system.webServer>
</configuration>
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.
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:
Question: What is the primary use of the HTTP generic handler (*.ashx)?
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 Objectives
After completing this lesson, you will be able to:
The WebSocket protocol is a standard from the World Wide Web Consortium
(W3C). The HTML 5 specification includes support for web sockets.
http://go.microsoft.com/fwlink/?LinkID=288994&clcid=0x423
The protocol facilitates two-way communication between web browsers and web
servers. The
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?
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.
{
HttpContext.Current.AcceptWebSocketRequest(new
ChatWebSocketHandler());
return Request.CreateResponse(HttpStatusCode.SwitchingProtocols);
public ChatWebSocketHandler()
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.
<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.
$(document).ready(function () {
websocket.onopen = function () {
};
};
};
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.
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.
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.
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR;
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.
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.
<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 () {
connection.received(function (data) {
alert(data);
});
connection.start().done(function() {
$("#broadcast").click(function () {
connection.send('Hello');
});
});
});
</script>
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
7.
{
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.
};
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();
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
Lab Setup
Estimated Time:
60 minutes
Virtual Machine: 20486B-SEA-DEV11
Password: Pa$$w0rd
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.
1. Install SignalR.
2. Create a Hub class.
3. Configure SignalR routes.
Start the virtual machine, and log on with the following credentials:
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.
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.
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.
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.
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:
o Password: Pa$$w0rd2
5. Attempt to send a chat message.
6. Stop debugging.
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.
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:
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:
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?
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
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
Lesson Objectives
After completing this lesson, you will be able to:
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
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.
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
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.
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.
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.
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.
steps:
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 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?
Lesson Objectives
After completing this lesson, you will be able to:
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.
<system.web>
</system.web>
The following code shows how to remove the debug attribute from the
Web.config file by using a deployment transformation.
<system.web>
</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.
<connectionStrings>
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?
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?
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.
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.
Question: What is the benefit of using the Web Deploy publish tool?
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.
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
Lab Setup
Password: Pa$$w0rd
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.
Scenario
Start the virtual machine, and log on with the following credentials:
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.
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.
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.
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.
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: 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?
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.