Professional Documents
Culture Documents
10264A
Lab Instructions and Lab Answer Key:
Developing Web Applications with
Microsoft Visual Studio 2010
Information in this document, including URL and other Internet Web site references, is subject to change without notice.
Unless otherwise noted, the example companies, organizations, products, domain names, e-mail addresses, logos, people,
places, and events depicted herein are fictitious, and no association with any real company, organization, product, domain
name, e-mail address, logo, person, place or event is intended or should be inferred. Complying with all applicable copyright
laws is the responsibility of the user. Without limiting the rights under copyright, no part of this document may be
reproduced, stored in or introduced into a retrieval system, or transmitted in any form or by any means (electronic,
mechanical, photocopying, recording, or otherwise), or for any purpose, without the express written permission of Microsoft
Corporation.
Microsoft may have patents, patent applications, trademarks, copyrights, or other intellectual property rights covering subject
matter in this document. Except as expressly provided in any written license agreement from Microsoft, the furnishing of this
document does not give you any license to these patents, trademarks, copyrights, or other intellectual property.
The names of manufacturers, products, or URLs are provided for informational purposes only and Microsoft makes no
representations and warranties, either expressed, implied, or statutory, regarding these manufacturers or the use of the
products with any Microsoft technologies. The inclusion of a manufacturer or product does not imply endorsement of
Microsoft of the manufacturer or product. Links may be provided to third party sites. Such sites are not under the control of
Microsoft and Microsoft is not responsible for the contents of any linked site or any link contained in a linked site, or any
changes or updates to such sites. Microsoft is not responsible for webcasting or any other form of transmission received from
any linked site. Microsoft is providing these links to you only as a convenience, and the inclusion of any link does not imply
endorsement of Microsoft of the site or the products contained therein.
Module 1
Lab Instructions: Overview of Web Application Architecture
and Design
Contents:
Exercise 1: Exploring the Adventure Works Website 4
Exercise 2: Comparing Web Forms and MVC 7
Exercise 3: Working with the Request Life Cycle 8
2 Lab Instructions: Overvieew of Web Applicatioon Architecture and Design
Lab 1: Ex
xploring
g the Adventure Works Web
bsite
O
Objectives:
Describe th
he Adventure Works
W website
e.
Explain cod
de differences between Web
b Forms and MVC.
Describe th
he request life cycle for both Web Forms and MVC.
In
ntroduction
n
In
n this lab, you will
w review thee existing Adve
enture Works website
w and be
ecome familiar with its desig
gn.
Fu
urthermore, yo ou will comparre how applica ment by using Web Forms differs from
ation developm
ap
pplication devvelopment by using
u the MVCC framework.
L Scen
Lab nario
As a web develo oper at Adventure Works, yo ed extensively with ASP.NET 2.0. However, you
ou have worke
haave limited experience with ASP.NET 4.0. You
Y need to fuurther explore the features of
o ASP.NET 4.0 to
acccomplish the goals set by management
m for the new Ad
dventure Workks website. As a first step tow
ward this
ennd, you want to
t examine thee MVC framew work and undeerstand how it compares withh the Web Forrms
prrogramming model.
m
4 Lab Instructions: Overview of Web Application Architecture and Design
6. Step through the web application startup until you reach the end of Page_Load method.
7. Continue the web application.
Note: The URL displayed in the address bar of Internet Explorer includes the name of the Web Form or
page (Default.aspx) displayed.
Note: The URL displayed in the address bar of Internet Explorer does not include the name of the page
(Index.aspx) displayed.
Results: After completing this exercise, you should have reviewed the Adventure Works website by
adding products to your shopping cart and checking out. You should also have reviewed the Page and
MVC request life cycles by placing breakpoints in methods that execute during the life cycle.
Lab Instructions: Overview of Web Application Architecture and Design 7
f Task 2: Examine the markup and code found in the Default.aspx Web Forms page
1. Examine the code in the Default.aspx.cs or Default.aspx.vb code file.
2. Examine the markup in the Default.aspx Web Form.
f Task 4: Examine the markup and code used for rendering the default MVC page
1. Open the Adventure Works MVC project at the following location:
Language Location
f Task 5: Discuss as a group the differences in the way Web Forms and MVC responds and
delivers content to a request
In the classroom, discuss the differences between the page life cycles of the two different web
application models, Web Forms and MVC, including the page-centric Web Forms request vs. the MVC
routing, the use of server controls in Web Forms vs. HTML controls, and MVC helper methods.
Results: After completing this exercise, you should have reviewed the code in a Web Forms and MVC
page, and discussed the differences as a class.
8 Lab Instructions: Overview of Web Application Architecture and Design
[Visual Basic]
lblAdvertisement.Text = "My advertisement here"
7. Run the web application and view the rendered Default.aspx page.
Note: During the pages Load event, the text is added to the lblAdvertisement Label control.
[Visual Basic]
<p><%: ViewData("Advertisement") %></p>
[Visual Basic]
ViewData("Advertisement") = "My advertisement here"
8. Run the web application and view the rendered Index.aspx view.
Note: During the controllers Index action method, the text is added to Index view by using the
ViewData.
f Task 3: Turn off the virtual machine and revert the changes
1. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and
then click Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Results: After completing this exercise, you should have explored the life cycle of both a Web Form and
an MVC page, by adding code to write to the page during the page request.
Lab Instructions: Designing a Web Application 1
Module 2
Lab Instructions: Designing a Web Application
Contents:
Exercise 1: Reviewing the Adventure Works Website Structure 4
Exercise 2: Redesigning the Adventure Works Website 5
Exercise 3: Adding MVC Capabilities to the Adventure Works Website 7
2 Lab Instructions: Designiing a Web Applicatioon
Lab 2: Redesign
ning the
e Adven
nture Works Website
N
Note: Tasks in this
t lab will be
e the same regardless of the programming
g language you
ur solution is using.
O
Objectives:
After completin
ng this lab, you
u will be able to:
t
Draw diagrrams showing the
t overall arcchitecture and page flow of the
t Adventure
e Works websitte.
Identify wh
hich pages of the website will use Web Forrms, and which
h pages will use MVC, based on
business requirements.
Add MVC capabilities
c to the existing website.
In
ntroduction
n
In w first capture your understanding of the current Adve
n this lab, you will enture Works website by
diiagramming itts overall architecture and pa ew the business requirementts set by
age flow. You will then revie
m
management, and
a recommen nd which pagees of the website will use Weeb Forms, and which pages willw use
M
MVC. You will also
a do the gro oundwork nece essary for adding MVC capa abilities to the existing website so
th
hat you can ge et started as so
oon as Manageement approva al comes throu ugh.
Lab Instructions: Designingg a Web Application 3
L Scen
Lab nario
Results: After completing this exercise, you should have created two diagrams describing the existing
architecture and page flow of the AdventureWorks web application.
Lab Instructions: Designing a Web Application 5
f Task 2: Determine which pages will use Web Forms and which will use MVC
Based on the requirements given, determine and document which pages will remain Web Forms
pages and which will be implemented in MVC.
f Task 3: Discuss your recommendations and their rationale with the class
Discuss the recommendations created with the class.
Results: After completing this exercise, you should have reviewed the requirements document for the
Adventure Works website, determined which pages will remain Web Forms pages and which will use
MVC, and discussed your recommendations and their rationale with the class.
Lab Instructions: Designing a Web Application 7
f Task 3: Add the MVC Assembly references and namespaces to the Web.config file
1. Open the Web.config file in the root AdventureWorks folder.
2. Add the following text to your Web.config file in their proper sections as shown, this adds the
appropriate assemblies to your project and configures special MVC handlers:
<system.web>
<compilation debug="true" targetFramework="4.0">
<assemblies>
...
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35"/>
</assemblies>
</compilation>
...
<pages>
<namespaces>
<add namespace="System.Web.Mvc"/>
<add namespace="System.Web.Mvc.Ajax"/>
<add namespace="System.Web.Mvc.Html"/>
<add namespace="System.Web.Routing"/>
</namespaces>
</pages>
<httpHandlers>
<add verb="*" path="*.mvc" validate="false" type="System.Web.Mvc.MvcHttpHandler"/>
</httpHandlers>
</system.web>
<system.webServer>
...
8 Lab Instructions: Designing a Web Application
<handlers>
<remove name="MvcHttpHandler"/>
<add name="MvcHttpHandler" preCondition="integratedMode" verb="*" path="*.mvc"
type="System.Web.Mvc.MvcHttpHandler"/>
</handlers>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31BF3856AD364E35"/>
<bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
<providers>
<clear />
<add name="AspNetSqlProfileProvider"
type="System.Web.Profile.SqlProfileProvider"
connectionStringName="ApplicationServices" applicationName="/" />
</providers>
</profile>
<roleManager enabled="false">
<providers>
<clear />
<add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider"
connectionStringName="ApplicationServices" applicationName="/" />
<add name="AspNetWindowsTokenRoleProvider"
type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" />
</providers>
</roleManager>
<pages>
<namespaces>
<add namespace="System.Web.Mvc"/>
<add namespace="System.Web.Mvc.Ajax"/>
<add namespace="System.Web.Mvc.Html"/>
<add namespace="System.Web.Routing"/>
</namespaces>
</pages>
<httpHandlers>
<add verb="*" path="*.mvc" validate="false"
type="System.Web.Mvc.MvcHttpHandler"/>
</httpHandlers>
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<handlers>
<remove name="MvcHttpHandler"/>
<add name="MvcHttpHandler" preCondition="integratedMode" verb="*" path="*.mvc"
type="System.Web.Mvc.MvcHttpHandler"/>
</handlers>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31BF3856AD364E35"/>
<bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
[Visual Basic]
<?xml version="1.0" encoding="utf-8"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<connectionStrings>
<add name="ApplicationServices" connectionString="data
source=.\SQLEXPRESS;Integrated
Security=SSPI;AttachDBFilename=|DataDirectory|\aspnetdb.mdf;User Instance=true"
providerName="System.Data.SqlClient" />
<add name="AdventureWorksEntities"
connectionString="metadata=res://*/mdlAdventureWorks.csdl|res://*/mdlAdventureWorks.ss
dl|res://*/mdlAdventureWorks.msl;provider=System.Data.SqlClient;provider connection
string="Data Source=.\sqlexpress;Initial
Catalog=AdventureWorksLT2008R2;Integrated
10 Lab Instructions: Designing a Web Application
Security=True;MultipleActiveResultSets=True""
providerName="System.Data.EntityClient" />
</connectionStrings>
<system.web>
<compilation debug="true" strict="false" explicit="true" targetFramework="4.0">
<assemblies>
<add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089" />
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35"/>
</assemblies>
</compilation>
<authentication mode="Forms">
<forms loginUrl="~/Account/Login.aspx" timeout="2880" />
</authentication>
<membership>
<providers>
<clear />
<add name="AspNetSqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider"
connectionStringName="ApplicationServices" enablePasswordRetrieval="false"
enablePasswordReset="true" requiresQuestionAndAnswer="false"
requiresUniqueEmail="false" maxInvalidPasswordAttempts="5"
minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0"
passwordAttemptWindow="10" applicationName="/" />
</providers>
</membership>
<profile>
<providers>
<clear />
<add name="AspNetSqlProfileProvider"
type="System.Web.Profile.SqlProfileProvider"
connectionStringName="ApplicationServices" applicationName="/" />
</providers>
</profile>
<roleManager enabled="false">
<providers>
<clear />
<add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider"
connectionStringName="ApplicationServices" applicationName="/" />
<add name="AspNetWindowsTokenRoleProvider"
type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" />
</providers>
</roleManager>
<pages>
<namespaces>
<add namespace="System.Web.Mvc"/>
<add namespace="System.Web.Mvc.Ajax"/>
<add namespace="System.Web.Mvc.Html"/>
<add namespace="System.Web.Routing"/>
</namespaces>
</pages>
<httpHandlers>
<add verb="*" path=".mvc" validate="false"
type="System.Web.Mvc.MvcHttpHandler"/>
</httpHandlers>
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<handlers>
Lab Instructions: Designing a Web Application 11
<remove name="MvcHttpHandler"/>
<add name="MvcHttpHandler" preCondition="integratedMode" verb="*" path=".mvc"
type="System.Web.Mvc.MvcHttpHandler"/>
</handlers>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" PublicKeyToken="31BF3856AD364E35"/>
<bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
[Visual Basic]
Imports System.Web.Mvc
Imports System.Web.Routing
2. Create a method named RegisterRoutes to register the MVC routes and exclude routes for existing
Web Form pages, handlers, and WCF services.
[Visual C#]
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{resource}.aspx/{*pathInfo}");
routes.IgnoreRoute("{resource}.svc/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
}
[Visual Basic]
Shared Sub RegisterRoutes(ByVal routes As RouteCollection)
routes.IgnoreRoute("{resource}.axd/{*pathInfo}")
routes.IgnoreRoute("{resource}.aspx/{*pathInfo}")
routes.IgnoreRoute("{resource}.svc/{*pathInfo}")
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
New With {.controller = "Home", .action = "Index", .id = ""}
)
End Sub
RegisterRoutes(RouteTable.Routes);
}
[Visual Basic]
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
RegisterRoutes(RouteTable.Routes)
End Sub
[Visual Basic]
<ProjectTypeGuids{349c5851-65df-11da-9384-00065b846f21};{F184B08F-C81C-45F6-A57F-
5ABD9991F28F}</ProjectTypeGuids>
Note: The top of the project file should look like this.
[Visual C#]
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
...
<ProjectGuid>{A8D6241C-680E-42BA-884B-501CC08D3FA9}</ProjectGuid>
<ProjectTypeGuids>{F85E285D-A4E0-4152-9332-AB1D724D3325};{349c5851-65df-11da-9384-
00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
...
[Visual Basic]
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
...
<ProjectGuid>{F9BE0786-D923-4DF0-9483-CE13D5D26A1F}</ProjectGuid>
<ProjectTypeGuids>{F85E285D-A4E0-4152-9332-AB1D724D3325{349c5851-65df-11da-9384-
00065b846f21};{F184B08F-C81C-45F6-A57F-5ABD9991F28F}</ProjectTypeGuids>
...
f Task 6: Turn off the virtual machine and revert the changes
1. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and
then click Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Results: After completing this exercise, you should have reviewed and documented the existing
AdventureWorks Web Forms application architecture and page flow, reviewed requirements
documentation and created a plan for redesigning the AdventureWorks application using MVC where it
made sense, and added MVC functionality to the existing AdventureWorks application.
Lab Instructions: Developing MVC Models 1
Module 3
Lab Instructions: Developing MVC Models
Contents:
Exercise 1: Exploring the AdventureWorks Database 4
Exercise 2: Adding an ADO.NET Entity Data Model 7
Exercise 3: Model Data Validation 12
2 Lab Instructions: Developping MVC Models
Lab 3: Creating
g MVC Models
O
Objectives:
After completin
ng this lab, you
u will be able to:
t
Work with the Adventure
eWorks databa
ase.
Use Entity Framework
F data model.
Implement data validatio
on for the MVC
C models.
In
ntroduction
n
In
n this lab, you will
w create rela
ationships betwween database e tables by using the Databa
ase Designer, create
c
an
n Entity Frame ework data moodel, add a datta repository, and
a implemen nt data model validation.
v
Laab Instructions: Developing MVC Models 3
LLab Scen
nario
4 Lab Instructions: Developing MVC Models
Note: The relationship between the Customer and CustomerAddress table is one-to-many, which
means a single customer can have multiple addresses.
6 Lab Instructions: Developing MVC Models
Result: After completing this exercise, you should have learned how to use Server Explorer to examine
the database schema and view relationships between the tables using database diagrams.
Lab Instructions: Developing MVC Models 7
3. Select the Blog and Blogger tables from the database and name the model namespace
AdventureWorksModel.
Lab Instructions: Developing MVC Models 9
[Visual Basic]
Private db As New AdventureWorksEntities
2. Add the following method to the BlogRepository class to return a list of all of the blogs.
[Visual C#]
public IQueryable<Blog> GetAllBlogs()
{
return db.Blogs;
}
[Visual Basic]
Public Function GetAllBlogs() As IQueryable(Of Blog)
Return db.Blogs
End Function
10 Lab Instructions: Developing MVC Models
3. Add the following method to the BlogRepository class to return a list of all of the blogs for a specific
blogger.
[Visual C#]
public IQueryable<Blog> GetAllBlogs(int id)
{
return from blog in db.Blogs
where blog.BloggerID == id
select blog;
}
[Visual Basic]
Public Function GetAllBlogs(ByVal id As Integer) As IQueryable(Of Blog)
Return From blog In db.Blogs
Where blog.BloggerID = id
Select blog
End Function
4. Add the following method to the BlogRepository class to return a specific blog.
[Visual C#]
public Blog GetBlog(int id)
{
return (from blog in db.Blogs
where blog.BlogID == id
select blog).SingleOrDefault();
}
[Visual Basic]
Public Function GetBlog(ByVal id As Integer) As Blog
Return (From blog In db.Blogs
Where blog.BlogID = id
Select blog).SingleOrDefault()
End Function
5. Add the following method to the BlogRepository class to return the name of the blogger.
[Visual C#]
public string GetBloggerName(int id)
{
var bloggerName = (from blogger in db.Bloggers
where blogger.BloggerID == id
select blogger.Name).FirstOrDefault();
return bloggerName;
}
[Visual Basic]
Public Function GetBloggerName(ByVal id As Integer) As String
Dim bloggerName = (From blogger In db.Bloggers
Where blogger.BloggerID = id
Select blogger.Name).FirstOrDefault
Return bloggerName
End Function
6. Add the following methods to the BlogRepository class to add, update, delete, and save individual
blogs.
[Visual C#]
public void AddBlog(Blog blog)
{
db.Blogs.AddObject(blog);
}
Lab Instructions: Developing MVC Models 11
[Visual Basic]
Public Sub AddBlog(ByVal blg As Blog)
db.Blogs.ApplyCurrentValues(blg)
End Sub
Result: In this exercise, you added an Entity data model to the web application, connecting it to the
existing AdventureWorks database. You also added a repository class and implemented list, select,
insert, update, and delete operations in the class.
12 Lab Instructions: Developing MVC Models
[Visual Basic]
Partial Public Class Blog
[Visual Basic]
Imports System.ComponentModel.DataAnnotations
Imports System.ComponentModel
Note: In the next section, you will add business rules validation to the partial class.
[DisplayName("Date Posted")]
[DisplayFormat(DataFormatString = "{0:d}")]
public object DatePosted { get; set; }
[Required]
public object Title { get; set; }
Lab Instructions: Developing MVC Models 13
[Required]
[DisplayName("Blog Entry")]
public object BlogEntry { get; set; }
}
[Visual Basic]
Public Class Blog_MetaData
<DisplayName("Blog ID")> _
Public Property BlogID As Object
<DisplayName("Date Posted")> _
<DisplayFormat(DataFormatString:="{0:d}")> _
Public Property DatePosted As Object
<Required()> _
Public Property Title As Object
2. Apply the MetadataType attribute to the Blog class, and reference the Blog_Metadata type as the
metadata type.
[Visual C#]
[MetadataType(typeof(Blog_MetaData))]
public partial class Blog
[Visual Basic]
<MetadataType(GetType(Blog_MetaData))>
Partial Public Class Blog
f Task 4: Turn off the virtual machine and revert the changes
1. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and
then click Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Result: After completing this exercise you should have learned how to add a partial class to the model
and extend the behavior of the existing class using partial classes and add validation logic in the partial
class.
Lab Instructions: Developing MVC Controllers 1
Module 4
Lab Instructions: Developing MVC Controllers
Contents:
Exercise 1: Creating an MVC Controller 4
Exercise 2: Adding code to list the existing blog entries 6
Exercise 3: Adding code to create a new blog entry 9
Exercise 4: Adding code to edit a blog entry 12
Exercise 5: Adding code to delete a blog entry 16
2 Lab Instructions: Developping MVC Controllerrs
Lab 4: Developing MV
VC Controllers
O
Objectives
After completin
ng this lab, you
u will be able to:
t
Create an MVC
M controller.
List the exissting blog entrries.
Create a ne
ew blog entry.
Edit a blog entry.
og entry.
Delete a blo
In
ntroduction
n
In
n this lab, you will
w create an MVC controlle
er and add cod
de to it to perfform create, re
ead, update, an
nd
deelete (CRUD) operations.
o
Lab Innstructions: Developing MVC Controllers 3
L Scen
Lab nario
Ba
ased on your recommendat
r ions for redesigning the AdvventureWorks website, the blog
b pages neeed to be
de
eveloped by using
u MVC. Youu have alreadyy built your MVVC model classes by leverag
ging an existing
g
ADO.NET Entityy Data Model. Next, you neeed to develop an
a MVC contro oller to handle
e the databasee
op
perations.
4 Lab Instructions: Developing MVC Controllers
[Visual Basic]
<HandleError()>
3. Verify that the code in the BlogController code file matches the following code.
[Visual C#]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace AdventureWorksMvc.Controllers
{
[HandleError]
public class BlogController : Controller
{
//
// GET: /Blog/
public ActionResult Index()
{
return View();
}
}
}
[Visual Basic]
Namespace AdventureWorksMvc
<HandleError()>
Public Class BlogController
Inherits System.Web.Mvc.Controller
'
Lab Instructions: Developing MVC Controllers 5
Results: After this exercise, you should have created a new controller named BlogController that is
decorated with the HandleErrorAttribute attribute.
6 Lab Instructions: Developing MVC Controllers
[Visual Basic]
Not applicable
2. Declare and instantiate a private BlogRepository object at the top of the BlogController class.
[Visual C#]
private BlogRepository blogRepository = new BlogRepository();
[Visual Basic]
Private blogRepository As New BlogRepository()
return View(blogs);
[Visual Basic]
Dim blogs = blogRepository.GetAllBlogs()
Return View(blogs)
2. Verify that the final Index action method matches the following code:
[Visual C#]
public ActionResult Index()
{
var blogs = blogRepository.GetAllBlogs();
Lab Instructions: Developing MVC Controllers 7
return View(blogs);
}
[Visual Basic]
Function Index() As ActionResult
Dim blogs = blogRepository.GetAllBlogs()
Return View(blogs)
End Function
[Visual Basic]
Function Blogger(ByVal id As Integer) As ActionResult
End Function
2. Add code to the Blogger action method to return only the blog entries for the indicated blogger to
the view.
[Visual C#]
var blogs = blogRepository.GetAllBlogs(id);
return View(blogs);
[Visual Basic]
Dim blogs = blogRepository.GetAllBlogs(id)
Return View(blogs)
3. Verify that the final Blogger action method matches the following code.
[Visual C#]
public ActionResult Blogger(int id)
{
var blogs = blogRepository.GetAllBlogs(id);
return View(blogs);
}
[Visual Basic]
Function Blogger(ByVal id As Integer) As ActionResult
Dim blogs = blogRepository.GetAllBlogs(id)
Return View(blogs)
End Function
[Visual Basic]
Function Details(ByVal id As Integer) As ActionResult
8 Lab Instructions: Developing MVC Controllers
End Function
2. Add code to the Details action method to return only the indicated blog entry, to the view. However,
if the blog entry no longer exists, redirect the user to the Index view.
[Visual C#]
var blogEntry = blogRepository.GetBlog(id);
if (blogEntry == null)
return RedirectToAction("Index");
return View(blogEntry);
[Visual Basic]
Dim blogEntry = blogRepository.GetBlog(id)
Return View(blogEntry)
3. Verify that the final Details action method matches the following code.
[Visual C#]
public ActionResult Details(int id)
{
var blogEntry = blogRepository.GetBlog(id);
if (blogEntry == null)
return RedirectToAction("Index");
return View(blogEntry);
}
[Visual Basic]
Function Details(ByVal id As Integer) As ActionResult
Dim blogEntry = blogRepository.GetBlog(id)
Return View(blogEntry)
End Function
Results: After this exercise, you should have created a BlogRepository and action methods that allow
you to view all of the blog entries, to view just the blog entries for a particular blogger, and to view a
particular blog entry.
Lab Instructions: Developing MVC Controllers 9
[Visual Basic]
Function Create() As ActionResult
End Function
2. Add code to the Create action method to return an empty ActionResult to the view.
[Visual C#]
return View();
[Visual Basic]
Return View()
3. Verify that the final Create action method matches the following code:
[Visual C#]
public ActionResult Create()
{
return View();
}
[Visual Basic]
Function Create() As ActionResult
Return View()
End Function
[Visual Basic]
<HttpPost()>
Function Create(ByVal blg As Blog) As ActionResult
End Function
2. Add code to the Create action method to save the new Blog object and redirect the user to the
Index view. However, if the call to the Save method fails, return the user to the Create view.
[Visual C#]
if (!ModelState.IsValid)
return View(blog);
try
{
blog.DatePosted = DateTime.Now;
blogRepository.AddBlog(blog);
blogRepository.Save();
return RedirectToAction("Index");
}
catch (Exception)
{
return View(blog);
};
[Visual Basic]
If ModelState.IsValid Then
Try
blg.DatePosted = DateTime.Now
blogRepository.AddBlog(blg)
blogRepository.Save()
Return RedirectToAction("Index")
Catch
Return View(blg)
End Try
End If
Return View(blg)
3. Verify that the final Create action method that for the HTTP Post request matches the following code.
[Visual C#]
[HttpPost]
public ActionResult Create(Blog blog)
{
if (!ModelState.IsValid)
return View(blog);
try
{
blog.DatePosted = DateTime.Now;
blogRepository.AddBlog(blog);
blogRepository.Save();
Lab Instructions: Developing MVC Controllers 11
return RedirectToAction("Index");
}
catch (Exception)
{
return View(blog);
};
}
[Visual Basic]
<HttpPost()>
Function Create(ByVal blg As Blog) As ActionResult
If ModelState.IsValid Then
Try
blg.DatePosted = DateTime.Now
blogRepository.AddBlog(blg)
blogRepository.Save()
Return RedirectToAction("Index")
Catch
Return View(blg)
End Try
End If
Return View(blg)
End Function
Results: After this exercise, you should have created two action methods for creating new blog entries.
One of the action methods accepts HTTP Get requests and the other action method accepts HTTP Post
requests.
12 Lab Instructions: Developing MVC Controllers
[Visual Basic]
Function Edit(ByVal id As Integer) As ActionResult
End Function
2. Add code to the Edit action method to return the indicated Blog entry, to the view. However, if the
blog entry no longer exists, redirect the user to the Index view.
[Visual C#]
var blog = blogRepository.GetBlog(id);
if (blog == null)
return RedirectToAction("Index");
return View(blog);
[Visual Basic]
Dim blogEntry = blogRepository.GetBlog(id)
Return View(blogEntry)
3. Verify that the final Edit action method matches the following code.
[Visual C#]
public ActionResult Edit(int id)
{
var blog = blogRepository.GetBlog(id);
Lab Instructions: Developing MVC Controllers 13
if (blog == null)
return RedirectToAction("Index");
return View(blog);
}
[Visual Basic]
Function Edit(ByVal id As Integer) As ActionResult
Dim blogEntry = blogRepository.GetBlog(id)
Return View(blogEntry)
End Function
[Visual Basic]
<HttpPost()>
Function Edit(ByVal id As Integer, ByVal collection As FormCollection) As ActionResult
End Function
2. Add code to the Edit action method to save the blog entry and redirect the user to the Index view.
However, if the call to the Save method fails, return the user to the Edit view. Also, if the blog entry
no longer exists, redirect the user to the Index view.
[Visual C#]
var blog = blogRepository.GetBlog(id);
if (blog == null)
return RedirectToAction("Index");
try
{
UpdateModel(blog, collection.ToValueProvider());
blogRepository.UpdateBlog(blog);
blogRepository.Save();
return RedirectToAction("Index");
}
catch (Exception)
{
return View(blog);
};
[Visual Basic]
Dim blogEntry = blogRepository.GetBlog(id)
14 Lab Instructions: Developing MVC Controllers
Try
UpdateModel(blogEntry, collection.ToValueProvider())
blogRepository.UpdateBlog(CType(blogEntry, Blog))
blogRepository.Save()
Return RedirectToAction("Index")
Catch
Return View(blogEntry)
End Try
3. Verify that the final Edit action method for an HTTP Post request matches the following code.
[Visual C#]
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
var blog = blogRepository.GetBlog(id);
if (blog == null)
return RedirectToAction("Index");
try
{
UpdateModel(blog, collection.ToValueProvider());
blogRepository.UpdateBlog(blog);
blogRepository.Save();
return RedirectToAction("Index");
}
catch (Exception)
{
return View(blog);
};
}
[Visual Basic]
<HttpPost()>
Function Edit(ByVal id As Integer, ByVal collection As FormCollection) As ActionResult
Dim blogEntry = blogRepository.GetBlog(id)
Try
UpdateModel(blogEntry, collection.ToValueProvider())
blogRepository.UpdateBlog(CType(blogEntry, Blog))
blogRepository.Save()
Return RedirectToAction("Index")
Catch
Return View(blogEntry)
End Try
End Function
Lab Instructions: Developing MVC Controllers 15
Results: After this exercise, you should have created two action methods for editing blog entries. One
of the action methods accepts HTTP Get requests and the other action method accepts HTTP Post
requests.
16 Lab Instructions: Developing MVC Controllers
[Visual Basic]
Function Delete(ByVal id As Integer) As ActionResult
End Function
2. Add code to the Delete action method to redirect to the Index view.
[Visual C#]
var blog = blogRepository.GetBlog(id);
if (blog == null)
return RedirectToAction("Index");
return View(blog);
[Visual Basic]
Dim blogEntry = blogRepository.GetBlog(id)
Return View(blogEntry)
3. Verify that the final Delete action method matches the following code.
[Visual C#]
public ActionResult Delete(int id)
{
var blog = blogRepository.GetBlog(id);
Lab Instructions: Developing MVC Controllers 17
if (blog == null)
return RedirectToAction("Index");
return View(blog);
}
[Visual Basic]
Function Delete(ByVal id As Integer) As ActionResult
Dim blogEntry = blogRepository.GetBlog(id)
Return View(blogEntry)
End Function
[Visual Basic]
<HttpPost()>
Function Delete(ByVal id As Integer, ByVal confirmation As String) As ActionResult
End Function
2. Add code to the Delete action method to delete the blog entry and redirect the user to the Index
view.
[Visual C#]
var blog = blogRepository.GetBlog(id);
if (blog == null)
return RedirectToAction("Index");
blogRepository.DeleteBlog((Blog) blog);
blogRepository.Save();
return RedirectToAction("Index");
[Visual Basic]
Dim blogEntry = blogRepository.GetBlog(id)
blogRepository.DeleteBlog(CType(blogEntry, Blog))
blogRepository.Save()
Return RedirectToAction("Index")
18 Lab Instructions: Developing MVC Controllers
3. Verify that the final Delete action method for an HTTP Post request matches the following code.
[Visual C#]
[HttpPost]
public ActionResult Delete(int id, string confirmation)
{
var blog = blogRepository.GetBlog(id);
if (blog == null)
return RedirectToAction("Index");
blogRepository.DeleteBlog((Blog) blog);
blogRepository.Save();
return RedirectToAction("Index");
}
[Visual Basic]
<HttpPost()>
Function Delete(ByVal id As Integer, ByVal confirmation As String) As ActionResult
Dim blogEntry = blogRepository.GetBlog(id)
blogRepository.DeleteBlog(CType(blogEntry, Blog))
blogRepository.Save()
Return RedirectToAction("Index")
End Function
f Task 4: Turn off the virtual machine and revert the changes
1. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and
then click Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Results: After this exercise, you should have created two action methods for deleting blog entries. One
of the action methods accepts HTTP Gets and the other action method accepts HTTP Posts.
Lab Instructions: Developing MVC Views 1
Module 5
Lab Instructions: Developing MVC Views
Contents:
Exercise 1: Develop a List MVC View 4
Exercise 2: Develop a Details MVC view 7
Exercise 3: Develop a Create MVC view 9
Exercise 4: Develop an Edit MVC view 15
Exercise 5: Develop a Delete MVC view 19
2 Lab Instructions: Developing MVC Views
Note: You can perform the tasks in this lab by using either Microsoft Visual C# or Microsoft Visual
Basic as your programming language.
Objectives
After completing this lab, you will be able to:
Create a List MVC view.
Create a Details MVC view.
Create a Create MVC view.
Create an Edit MVC view.
Create a Delete MVC view.
Introduction
In this lab, you create MVC views for listing, adding, editing, and deleting blog entries. You use strongly-
typed views, ViewData and TempData to retrieve the data from the controller. Also, you use partial views
to reuse markup that is used on multiple pages.
Lab Instructions: Developing MVC Views 3
Lab Scenario
Based on your recommendations for redesigning the AdventureWorks website, the blog pages need to be
developed by using MVC. You have already created an ADO.NET Entity Data Model to build your MVC
model classes. You have also developed an MVC controller to handle database operations. With the
database access and application logic in place, you now need to create a set of MVC views to render the
UI based on controller actions.
4 Lab Instructions: Developing MVC Views
[Visual Basic]
<li><%: Html.ActionLink("Blog", "", "Blog")%></li>
[Visual Basic]
<ul id="menu">
<li><%: Html.ActionLink("Home", "Index", "Home")%></li>
<li><%: Html.ActionLink("Blog", "", "Blog")%></li>
<li><%: Html.ActionLink("About", "About", "Home")%></li>
</ul>
4. Add the following markup and code to the Index view in the Content2 Content control, immediately
after the h2 element.
[Visual C#]
<% foreach (var item in Model)
{ %>
<div>
<%: Html.ActionLink("Details", "Details", new { id=item.BlogID })%>
<%: item.DatePosted %>
-
<%: item.Title %>
</div>
<% } %>
[Visual Basic]
<% For Each item As AdventureWorksMvc.Blog In Model%>
<div>
<%: Html.ActionLink("Details", "Details", New With {.id = item.BlogID})%>
<%: item.DatePosted %>
-
<%: item.Title %>
</div>
<% Next%>
5. Verify that the markup and code in the Index view matches the following.
[Visual C#]
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<IEnumerable<AdventureWorksMvc.Models.Blog>>" %>
[Visual Basic]
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage(Of IEnumerable (Of AdventureWorksMvc.Blog))" %>
-
<%: item.Title %>
</div>
<% Next%>
</asp:Content>
Results: After this exercise, you should have created a Blog menu item that opens a list MVC view
named Index, which lists all of the blog entries.
Lab Instructions: Developing MVC Views 7
3. Verify that the markup and code in the Details view matches the following.
[Visual C#]
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<AdventureWorksMvc.Models.Blog>" %>
[Visual Basic]
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage(Of AdventureWorksMvc.Blog)" %>
8 Lab Instructions: Developing MVC Views
Results: After this exercise, you should have created a new MVC view that shows the details about an
individual blog entry.
Lab Instructions: Developing MVC Views 9
Task 2: Add a strongly-typed view named Blogger to list all of the blogs for a particular
blogger
1. Add an empty, strongly-typed view named Blogger based on the Site.Master master page, to the
Blog folder.
2. Update the Blogger view to a strongly-typed view of type IEnumerable of type Blog.
[Visual C#]
System.Web.Mvc.ViewPage<IEnumerable<AdventureWorksMvc.Models.Blog>>
[Visual Basic]
System.Web.Mvc.ViewPage(Of IEnumerable (Of AdventureWorksMvc.Blog))
3. Add the following markup and code to the Blogger view in the Content2 Content control,
immediately after the h2 element.
[Visual C#]
<% foreach (var item in Model)
{ %>
<div>
<%: Html.ActionLink("Edit", "Edit", new { id=item.BlogID })%>
<%: Html.ActionLink("Delete", "Delete", new { id=item.BlogID })%>
<%: item.DatePosted %>
-
<%: item.Title %>
</div>
<% } %>
<p>
<%: Html.ActionLink("Create New", "Create") %>
</p>
[Visual Basic]
<% For Each item As AdventureWorksMvc.Blog In Model%>
<div>
<%: Html.ActionLink("Edit", "Edit", New With {.id = item.BlogID})%>
<%: Html.ActionLink("Delete", "Delete", New With {.id = item.BlogID})%>
<%: item.DatePosted %>
-
<%: item.Title %>
10 Lab Instructions: Developing MVC Views
</div>
<% Next%>
<p>
<%: Html.ActionLink("Create New", "Create") %>
</p>
Verify that the markup and code in the Blogger view matches the following.
[Visual C#]
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<IEnumerable<AdventureWorksMvc.Models.Blog>>" %>
[Visual Basic]
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage(Of IEnumerable (Of AdventureWorksMvc.Blog))" %>
2. Add the following markup and code to the Create view in the Content2 Content control,
immediately after the h2 element.
[Visual C#]
<% using (Html.BeginForm())
{%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.Title) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Title) %>
<%: Html.ValidationMessageFor(model => model.Title) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.BlogEntry) %>
</div>
<div class="editor-field">
<%: Html.TextAreaFor(model => model.BlogEntry, new { cols = "85" })%>
<%: Html.ValidationMessageFor(model => model.BlogEntry) %>
</div>
</fieldset>
<input type="submit" value="Submit" />
<% } %>
<div>
<%: Html.ActionLink("Back to List", "Blogger") %>
</div>
[Visual Basic]
<% Using (Html.BeginForm())%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(Function(m) m.Title)%>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(Function(m) m.Title)%>
<%: Html.ValidationMessageFor(Function(m) m.Title)%>
</div>
<div class="editor-label">
<%: Html.LabelFor(Function(m) m.BlogEntry)%>
</div>
<div class="editor-field">
<%: Html.TextAreaFor(Function(m) m.BlogEntry, New With {.cols = "85"})%>
<%: Html.ValidationMessageFor(Function(m) m.BlogEntry)%>
</div>
</fieldset>
<input type="submit" value="Submit" />
<% End Using%>
<div>
<%: Html.ActionLink("Back to List", "Blogger") %>
</div>
3. Verify that the markup and code in the Create view matches the following.
[Visual C#]
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<AdventureWorksMvc.Models.Blog>" %>
Create
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>
Create</h2>
<% using (Html.BeginForm())
{%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.Title) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Title) %>
<%: Html.ValidationMessageFor(model => model.Title) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.BlogEntry) %>
</div>
<div class="editor-field">
<%: Html.TextAreaFor(model => model.BlogEntry, new { cols = "85" })%>
<%: Html.ValidationMessageFor(model => model.BlogEntry) %>
</div>
</fieldset>
<input type="submit" value="Submit" />
<% } %>
<div>
<%: Html.ActionLink("Back to List", "Blogger") %>
</div>
</asp:Content>
[Visual Basic]
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage(Of AdventureWorksMvc.Blog)" %>
[Visual Basic]
<% If Not TempData("ConfirmationMessage") Is Nothing Then%>
<div class="message">
<%: TempData("ConfirmationMessage")%>
</div>
<% End If%>
3. Verify that the markup and code in the Index view matches the following.
[Visual C#]
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<IEnumerable<AdventureWorksMvc.Models.Blog>>" %>
Results: After this exercise, you should have created two new MVC views. The first new view lists all of
the blog entries for a particular blogger and the second new view allows you to create new blog
entries.
Lab Instructions: Developing MVC Views 15
[Visual Basic]
<% Using (Html.BeginForm())%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
16 Lab Instructions: Developing MVC Views
3. Verify that the markup and code in the partial Blog view matches the following.
[Visual C#]
<%@ Control Language="C#"
Inherits="System.Web.Mvc.ViewUserControl<AdventureWorksMvc.Models.Blog>" %>
<% using (Html.BeginForm())
{%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.Title) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Title) %>
<%: Html.ValidationMessageFor(model => model.Title) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.BlogEntry) %>
</div>
<div class="editor-field">
<%: Html.TextAreaFor(model => model.BlogEntry, new { cols = "85" })%>
<%: Html.ValidationMessageFor(model => model.BlogEntry) %>
</div>
</fieldset>
<input type="submit" value="Submit" />
<% } %>
<div>
<%: Html.ActionLink("Back to List", "Blogger") %>
</div>
[Visual Basic]
<%@ Control Language="VB" Inherits="System.Web.Mvc.ViewUserControl(Of
AdventureWorksMvc.Blog)" %>
<% Using (Html.BeginForm())%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(Function(m) m.Title)%>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(Function(m) m.Title)%>
<%: Html.ValidationMessageFor(Function(m) m.Title)%>
Lab Instructions: Developing MVC Views 17
</div>
<div class="editor-label">
<%: Html.LabelFor(Function(m) m.BlogEntry)%>
</div>
<div class="editor-field">
<%: Html.TextAreaFor(Function(m) m.BlogEntry, New With {.cols = "85"})%>
<%: Html.ValidationMessageFor(Function(m) m.BlogEntry)%>
</div>
</fieldset>
<input type="submit" value="Submit" />
<% End Using%>
<div>
<%: Html.ActionLink("Back to List", "Blogger") %>
</div>
Task 3: Create an edit view, named Edit, that uses the Blog partial view
1. Add an empty, strongly-typed view of type Blog, named Edit, based on the Site.Master master page,
to the Blog folder.
2. Add the following markup and code to the Edit view in the Content2 Content control, immediately
after the h2 element.
[Visual C#]
<% Html.RenderPartial("Blog"); %>
[Visual Basic]
<% Html.RenderPartial("Blog") %>
3. Verify that the markup and code in the Edit view matches the following.
[Visual C#]
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<AdventureWorksMvc.Models.Blog>" %>
[Visual Basic]
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage(Of AdventureWorksMvc.Blog)" %>
blog/blogger/1
Task 5: Update the Create view to use the Blog partial view.
1. Replace the markup and code after the h2 element in the Content2 Content element in the Create
view with the following.
[Visual C#]
<% Html.RenderPartial("Blog"); %>
[Visual Basic]
<% Html.RenderPartial("Blog") %>
2. Verify that the markup and code in the Create view matches the following.
[Visual C#]
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<AdventureWorksMvc.Models.Blog>" %>
[Visual Basic]
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage(Of AdventureWorksMvc.Blog)" %>
Results: After this exercise, you should have created a partial view that is used by both the Edit view
and the Create view.
Lab Instructions: Developing MVC Views 19
Task 2: Add a strongly-typed view named Delete that uses the default markup provided
by the Add View dialog box
1. Build the solution.
2. Add a delete, strongly-typed view of type Blog, named Delete, based on the Site.Master master
page, to the Blog folder. The view should use the default content supplied for a Delete operation.
3. Update the markup and code that renders the Back to List link to match the following.
<%: Html.ActionLink("Back to List", "Blogger") %>
4. Verify that the markup and code in the Delete view matches the following.
[Visual C#]
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<AdventureWorksMvc.Models.Blog>" %>
[Visual Basic]
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage(Of AdventureWorksMvc.Blog)" %>
Task 4: Turn off the virtual machine and revert the changes
1. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and
then click Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Results: After this exercise, you should have created an MVC view to delete blog entries.
Lab Instructions: Designing for Discoverability 1
Module 6
Lab Instructions: Designing for Discoverability
Contents:
Exercise 1: Mapping URLs of Web Forms Pages 4
Exercise 2: Creating a Sitemap File 8
Exercise 3: Building the Application Infrastructure 9
2 Lab Instructions: Designiing for Discoverabilitty
Lab 6: Designin
ng for Discover
D rability
O
Objectives
After completin
ng this lab, you
u will be able to:
t
Map URLs of
o Web Forms pages.
Create a sittemap file.
Build an ap
pplication infra
astructure.
In
ntroduction
n
In
n this lab, you map URLs of Web
W Forms pages to use ASP P.NET URL mapping for listin ng products byy
ca
ategory, and details
d ecific product ID. You also create a sitemap, as well as a robots.txt file
for a spe e with
an
n inclusion to the
t newly crea ated sitemap file
f for the Deffault Web Site dd navigation controls
e in IIS, and ad
to
o the applicatioon.
Lab Innstructions: Designingg for Discoverability 3
L Scen
Lab nario
[Visual Basic]
Private Sub RegisterRoutes(ByVal routes As RouteCollection)
' Route name
' URL with parameters
' Web forms page to handle it
routes.MapPageRoute("products-browse", "products/{category}", "~/Products.aspx")
End Sub
Lab Instructions: Designing for Discoverability 5
[Visual Basic]
Private Sub Application_Start()
RegisterRoutes(RouteTable.Routes)
End Sub
categoryName =
DataAccessLayer.Products.GetCategoryName(int.Parse(categoryId));
lblCategory.Text = categoryName;
var data =
DataAccessLayer.Products.GetProductsByCategory(int.Parse(categoryId));
gvProducts.DataSource = data;
gvProducts.DataBind();
}
}
[Visual Basic]
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
Dim categoryName As String = Nothing
Dim categoryId As String
categoryName =
AdventureWorks.DataAccessLayer.Products.GetCategoryName(Integer.Parse(categoryId))
lblCategory.Text = categoryName
Dim data =
AdventureWorks.DataAccessLayer.Products.GetProductsByCategory(Integer.Parse(categoryId
))
gvProducts.DataSource = data
gvProducts.DataBind()
End If
End Sub
6 Lab Instructions: Designing for Discoverability
products/1
Note: A grid should render with a single row containing products for the product category with an ID
value of 1.
routes.MapPageRoute(
"product-browse", // Route name
"product/{id}", // URL with parameters
"~/ProductDetail.aspx" // Web forms page to handle it
);
}
[Visual Basic]
Private Sub RegisterRoutes(ByVal routes As RouteCollection)
' Route name
' URL with parameters
' Web forms page to handle it
routes.MapPageRoute("products-browse", "products/{category}", "~/Products.aspx")
productId = Page.RouteData.Values["id"].ToString();
lblName.Text = data.Name;
lblId.Text = data.ProductID.ToString();
lblColor.Text = data.Color;
lblSize.Text = data.Size;
lblWeight.Text = data.Weight.ToString();
lblListPrice.Text = data.ListPrice.ToString();
hdnProductId.Value = data.ProductID.ToString();
hdnProductName.Value = data.Name;
hdnListPrice.Value = data.ListPrice.ToString();
}
}
[Visual Basic]
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles
Me.Load
If Not Page.IsPostBack Then
Dim productID As String = Nothing
lblName.Text = data.Name
lblId.Text = data.ProductID.ToString()
lblColor.Text = data.Color
lblSize.Text = data.Size
lblWeight.Text = data.Weight.ToString()
lblListPrice.Text = data.ListPrice.ToString()
hdnProductId.Value = data.ProductID.ToString()
hdnProductName.Value = data.Name
hdnListPrice.Value = data.ListPrice.ToString()
End If
End Sub
product/680
Note: A grid should render with a single row containing details of the product with an ID value of 680.
Results: After completing this exercise, you should have added a reference to the
System.Web.Routing assembly, and modified the Global.asax file to use ASP.NET URL mapping to
list products by category and details for a specific product ID.
8 Lab Instructions: Designing for Discoverability
Results: After completing this exercise, you should have created a sitemap as well as a robots.txt file
with an inclusion to the newly created sitemap file for the default website in IIS.
Lab Instructions: Designing for Discoverability 9
6. Replace the content of the div element with a class attribute value of clear hideSkiplink, with the
following markup.
<div class="clear hideSkiplink">
<asp:SiteMapDataSource runat="server" ID="siteMapDataSource"
ShowStartingNode="false" />
<asp:Menu runat="server" ID="NavigationMenu" Orientation="Horizontal"
DataSourceID="siteMapDataSource" />
</div>
[Visual Basic]
Note: IntelliSense will show you details about the Menu control. You can expand the different levels
by clicking the +-sign.
7. Stop debugging.
8. Close Visual Studio 2010.
f Task 4: Turn off the virtual machine and revert the changes
1. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and
then click Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Results: After this exercise, you should have added navigation controls to the web application.
Lab Instructions: Writing Server-Side Code for Web Forms 1
Module 7
Lab Instructions: Writing Server-Side Code for Web Forms
Contents:
Exercise 1: Modifying a Web Forms Page to Display Localized Content 4
Exercise 2: Persisting Data on Web Forms Pages 8
Exercise 3: Utilizing View State Effectively 12
Exercise 4: Adding Validation to Web Forms Pages 15
2 Lab Instructions: Writing Server-Side Code foor Web Forms
O
Objectives:
After completin
ng this lab, stud
dents will be able
a to:
Modify a Web
W Forms pag
ge to display lo
ocalized conte
ent.
Utilize view
w state effective
ely.
Add validattion to Web Fo
orms pages.
In
ntroduction
n
In
n this lab, you modify a Web b Forms page and a the master page to display localized content,
c locate
ed in
okies, application state, and session state, and you
diifferent resourrce files. You persist user datta by using coo
earn how to utilize view state
le alidation to Web Forms page
e effectively. You also add va es, using validation
co
ontrols.
Lab Instructions: Writing Server-Side Code for Web Forms 3
L Scen
Lab nario
Too improve the customer exp perience, existing Web Formss pages of the AdventureWo orks website need to
bee updated to display
d localize
ed informationn. Because purrchases by inte
ernational custtomers make upu a
la
arge percentagge of online sales, management has decide essages, units, dates, and so on,
ed that the me
sh
hould be displaayed in either English or oth
her languages based on a cu ustomers languuage preference.
Thherefore, you need to edit th
he home page e to detect the
e default browsser language.
4 Lab Instructions: Writing Server-Side Code for Web Forms
Note: This automatically creates the App_LocalResources folder in the root of your web
application, if one does not already exist. The process also creates a resource file called
Default.aspx.resx, in the App_LocalResources folder.
Note: The values of these attributes are used to find the localized values for the properties of the
localizable controls in the Default.aspx.resx file.
5. Notice that the Page directive at the top of the page now contains the following information.
<%@ Page ... culture="auto" meta:resourcekey="PageResource1" uiculture="auto" %>
6. Open Default.aspx.resx.
Note: In the Resource Editor, you will see a list with all the localizable properties of the localizable
controls from the Default.aspx page.
8. Notice that the text strings Welcome to AdventureWorks! and Product Categories were not
modified, and they were not added to the .resx file either. This is because they were hard-coded in
the Web Forms page.
9. Localize the hard-coded Welcome to AdventureWorks! text implicitly, by adding a Localize server
control within the h2 element, with the following attributes.
Attribute Value
ID lclWelcome
meta:resourcekey LocalizeResource1
Note: Make sure that you do not delete the text Welcome to AdventureWorks! from the
Localize server control.
11. Add a resource string named lclWelcomeResource1.Text to the Default.aspx.resx resource file. The
string must have the value of Welcome to AdventureWorks!.
12. Localize the hard-coded Product Categories text explicitly, by adding a Literal server control within
the p element, with the following attributes.
Attribute Value
ID ProductCategoriesLiteral
Note: Make sure that you do not delete the text Product Categories from the Literal server
control.
14. Add a resource string named ProductCategoriesLiteral.Text to the Default.aspx.resx resource file.
The string must have the value of Product Categories.
15. Run the application.
16. Verify that Default.aspx Web Form looks the same as it did before you modified it.
17. Close Windows Internet Explorer.
18. Add an existing German resource file for the Default.aspx Web Form to the App_LocalResources
folder. The file is named Default.aspx.de.resx and it is located in the D:\Lab Files\CS\Lab
07\Starter\Exercise 01 or D:\Lab Files\VB\Lab 07\Starter\Exercise 01 folder.
Attribute Value
ID LoginLiteral
Text Log In
3. Delete the text Log In from the a element.
Note: Make sure that you do not delete the text Log In from the Literal server control.
4. Localize the hard-coded Welcome text, by adding a Literal server control within the
LoggedInTemplate element, with the following attributes.
Attribute Value
ID WelcomeLiteral
Text Welcome
5. Delete the text Welcome from the LoggedInTemplate element.
Note: Make sure that you do not delete the text Welcome from the Literal server control.
Note: This generates a new file called Site.Master.resx in the App_LocalResources folder.
8. Add an existing German resource file for the Site.Master master page to the App_LocalResources
folder. The file is named Site.Master.de.resx and it is located in the D:\Lab Files\CS\Lab
07\Starter\Exercise 01 or D:\Lab Files\VB\Lab 07\Starter\Exercise 01 folder.
Results: After this exercise, you should have a web application that supports different languages, and
shows the site in the users preferred language.
8 Lab Instructions: Writing Server-Side Code for Web Forms
Programming
Language Location
f Task 2: Use a cookie collection to persist user information and set scope and lifetime to
save the last chosen category
1. Open the Default.aspx Web Form in Code view.
2. On postback, create a cookie object called Preferences that holds the current product category,
saved as a value named LastCategory. Make sure that the cookie will expire after one minute. The
cookie must be appended to the response.
[Visual C#]
else
{
if (lbCategories.SelectedIndex != -1)
{
string category = lbCategories.SelectedValue;
Response.Redirect("/Products.aspx?id=" + category);
}
}
[Visual Basic]
Else
If lbCategories.SelectedIndex <> -1 Then
Dim category = lbCategories.SelectedValue
3. If the page is rendered for the first time, add code to check that a cookie named Preferences exists in
the request cookie collection, and if there is, read the LastCategory value from the cookie, and assign
it to the SelectedValue property of the ListBox control.
[Visual C#]
if (!Page.IsPostBack)
{
List<ProductCategory> data = DataAccessLayer.Products.GetCategories();
lbCategories.DataSource = data;
lbCategories.DataBind();
[Visual Basic]
If Not Page.IsPostBack Then
Dim data As List(Of ProductCategory) =
AdventureWorks.DataAccessLayer.Products.GetCategories
lbCategories.DataSource = data
lbCategories.DataBind()
[Visual Basic]
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
Application("OnlineVisitors") = 0
End Sub
3. In the Session_Start method increment the value of the OnlineVisitors application variable by 1.
Make sure you prevent multiple threads from writing to the application variable, by locking the
Application object before writing, and unlocking once you have finished writing to it.
[Visual C#]
10 Lab Instructions: Writing Server-Side Code for Web Forms
[Visual Basic]
Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)
Application.Lock()
Dim visitors As Integer = Integer.Parse(Application("OnlineVisitors"))
visitors += 1
Application("OnlineVisitors") = visitors
Application.UnLock()
End Sub
4. In the Session_End decrement the value of the OnlineVisitors application variable by 1, if the
current value is not 0. Make sure you prevent multiple threads from writing to the application
variable, by locking the Application object before writing, and unlocking once you have finished
writing to it.
[Visual C#]
void Session_End(object sender, EventArgs e)
{
Application.Lock();
int visitors = (int)Application["OnlineVisitors"];
if (visitors > 0)
{
visitors++;
Application["OnlineVisitors"] = visitors;
}
Application.UnLock();
}
[Visual Basic]
Sub Session_End(ByVal sender As Object, ByVal e As EventArgs)
Application.Lock()
Dim visitors As Integer = Integer.Parse(Application("OnlineVisitors"))
Application.UnLock()
End Sub
3. Configure the local SQL Server instance SQLExpress to host the state database, by running the
following command from the Visual Studio Command Prompt (2010). The Visual Studio Command
Prompt (2010) must be run as an administrator.
aspnet_regsql -E -S .\SQLExpress -ssadd
4. Open the SQL Server Command Line Tool, by running the following command from the Visual
Studio Command Prompt (2010).
sqlcmd E S .\SQLExpress
5. Add permissions for the user Student to access the tempdb and ASPState database to use the new
SQL Server Session state, by running commands from the SQL Server Command Line Tool within
the Visual Studio Command Prompt (2010). The commands are saved in the D:\Lab Files\CS\Lab
07\Starter\Exercise 02\ASPState.txt or D:\Lab Files\VB\Lab 07\Starter\Exercise 02\ASPState.txt
file, from where you can copy them and paste them into the SQL Server Command Line Tool.
6. Close the SQL Server Command Line Tool, by running the following command from the Visual
Studio Command Prompt (2010).
quit
Results: After this exercise, you should have implemented state using different techniques, including
Application and Session state.
12 Lab Instructions: Writing Server-Side Code for Web Forms
Note: The lbCategories server control is now empty because it is not being populated by the
server code on a postback.
Note: The lbCategories server control is now empty because it is not being populated by the
server code on a postback.
Note: The lbCategories server control is now empty, even if you enabled view state for the control.
This is because disabling view state for a control or page will disable the view state for all child
controls.
12. Enable view state for the lbCategories server control by setting the ViewStateMode property to
Enabled.
<asp:ListBox ID="lbCategories" runat="server" DataTextField="Name"
DataValueField="ProductCategoryID"
Height="270px" Width="186px" ViewStateMode="Enabled"></asp:ListBox>
Note: The lbCategories server control is still populated because view state has been enabled for
the server control.
Results: After this exercise, you should have examined and implemented the view state in different
ways.
Lab Instructions: Writing Server-Side Code for Web Forms 15
f Task 3: Add and configure a RequiredFieldValidator control for the txtCreditCard control
1. Add a RequiredFieldValidator control named CreditCardRequiredFieldValidator to the
ShoppingCart Web Form, and place it immediately after the txtCreditCard control.
<asp:TextBox runat="server" ID="txtCreditCard" />
<asp:RequiredFieldValidator ID="CreditCardRequiredFieldValidator" runat="server">
</asp:RequiredFieldValidator>
f Task 4: Add and configure a RegularExpressionValidator control for the credit card field
1. Add a RegularExpressionValidator control named CreditCardRegularExpressionValidator to the
ShoppingCart Web Form, and place it immediately after the CreditCardRequiredFieldValidator
control. Add a self-closing HTML br element after the RegularExpressionValidator control.
</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator ID="CreditCardRegularExpressionValidator"
runat="server">
</asp:RegularExpressionValidator>
<br />
16 Lab Instructions: Writing Server-Side Code for Web Forms
[Visual C#]
protected void btnPlaceOrder_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
Session["_cart"] = null;
Response.Redirect("~/ThankYou.aspx", true);
}
}
[Visual Basic]
Protected Sub btnPlaceOrder_Click(ByVal sender As Object, ByVal e As
System.EventArgs) Handles btnPlaceOrder.Click
If Page.IsValid Then
Session("_cart") = Nothing
Response.Redirect("~/ThankYou.aspx", True)
End If
End Sub
Note: Observe that an asterisk (*) is placed next to txtCreditCard server control because you have
not filled in this field.
10. On the Shopping Cart page, in the Credit card number box, type 1234123412341234, and then
click Place Order.
Note: Observe that an asterisk (*) is placed next to txtCreditCard server control because you have
not entered a valid credit card number.
Lab Instructions: Writing Server-Side Code for Web Forms 17
11. On the Shopping Cart page, in the Credit card number box, type 4058340022020047, and then
click Place Order.
Note: Observe that you are redirected to the ThankYou Web Form because you have filled in a
valid credit card number.
Results: After this exercise, you should have implemented validation for the check-out page, by adding
validation controls to the Web Form.
f Task 5: Turn off the virtual machine and revert the changes
1. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and
then click Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Lab Instructions: Optimizing Data Management for Web Forms 1
Module 8
Lab Instructions: Optimizing Data Management for Web
Forms
Contents:
Lab 8A: Optimizing Data Management for Web Forms
Section 1: Visual Basic
Exercise 1: Managing Data by Using LINQ to Entities 4
Exercise 2: Customizing the GridView 5
Exercise 3: Using ListView, DetailsView and Charts 10
Section 2: Visual C#
Exercise 1: Managing Data by Using LINQ to Entities 14
Exercise 2: Customizing the GridView 15
Exercise 3: Using ListView, DetailsView and Charts 21
Lab 8B: Optimizing Data Management for Web Forms
Section 1: Visual Basic
Exercise 4: Managing Data by Using ASP.NET Dynamic Data 27
Section 2: Visual C#
Exercise 4: Managing Data by Using ASP.NET Dynamic Data 29
2 Lab Instructions: Optimizzing Data Managemeent for Web Forms
O
Objectives
After completin
ng this lab, you
u will be able to:
t
Manage da
ata by using th
he LinqDataSo
ource control.
In
ntroduction
n
In
n this lab, you will
w develop th
he administration section of the website by using variou
us ASP.NET datta
so
ource controls.
Labb Instructions: Optim
mizing Data Managem
ment for Web Forms 3
L Scen
Lab nario
Th
he AdventureW Works Sales team has requessted the addition of an administration section to the weebsite so
th
hat they can manage
m a provide a dashboard to se
information, as well as enior management. As a firsst step
to
oward this end
d, you need to create a set off web form pa
ages that will enable
e es team to do the
the Sale
fo
ollowing:
Display sale
es information in a graphical format (dashboard)
In
n this lab, you will
w develop th
he administration section of the website by using variou
us ASP.NET datta
so
ource controls.
4 Lab Instructions: Optimizing Data Management for Web Forms
3. Open the AdventureWorks solution from the D:\Lab Files\VB\Lab 08\Starter\Exercise 01 folder.
2. Open the AdventureWorks solution from the the D:\Lab Files\VB\Lab 08\Starter\Exercise 02
folder.
4. Add a public property named Text to the user control. The property must be of type String, and get
and set the Text property of the QuantityTextBox control.
Public Property Text As String
Get
Return QuantityTextBox.Text
End Get
Set(ByVal value As String)
QuantityTextBox.Text = value
End Set
End Property
Note: Observe the Build succeeded message in the Build pane of the Output window.
2. Add a private member variable named productQuantity of type Integer to the ShoppingCart class.
Private productQuantity As Integer
3. Modify the auto-implemented Quantity property, to get and set the productQuantity member
variable.
Public Property Quantity As Integer
Get
Return productQuantity
End Get
Set
productQuantity = value
End Set
End Property
3. Open the Fields dialog box for the GridView control, by using the Smart Tag.
Note: Observe how the Quantity field/column has been converted into a TemplateField, and the
newly added Total Price TemplateField.
h. Add code to the gvCart_RowEditing method, for setting the edit index and bind the data by
using the BindData method.
Protected Sub gvCart_RowEditing(ByVal sender As Object, ByVal e As
System.Web.UI.WebControls.GridViewEditEventArgs) Handles gvCart.RowEditing
' Set edit index
gvCart.EditIndex = e.NewEditIndex
' Bind data
BindData()
End Sub
i. Add code to the gvCart_RowCancelingEdit method, for resetting the edit index and bind the
data by using the BindData method.
Protected Sub gvCart_RowCancelingEdit(ByVal sender As Object, ByVal e As
System.Web.UI.WebControls.GridViewCancelEditEventArgs) Handles
gvCart.RowCancelingEdit
' Reset edit index
gvCart.EditIndex = -1
' Bind data
BindData()
End Sub
j. Add code to the gvCart_RowUpdating method, for retrieving the existing cart from Session.
' Retrieve existing cart from session
Dim cart As List(Of ShoppingCart) = CType(Session("_cart"), List(Of ShoppingCart))
k. Append code to the gvCart_RowUpdating method, for retrieving the current row from the
GridView control.
' Get current row
Dim row As GridViewRow = gvCart.Rows(e.RowIndex)
l. Append code to the gvCart_RowUpdating method, for finding the matching row in the stored
cart, stored in a new variable named cartToEdit of type ShoppingCart. Use the generic List Find
method with an anonymous Lambda expression.
' Find matching row in stored cart
Dim cartToEdit As ShoppingCart = cart.Find(Function(cartToFind) cartToFind.ProductId
= Integer.Parse(row.Cells(1).Text))
m. Append code to the gvCart_RowUpdating method, for updating the quantity value of the
cartToEdit shopping cart with the value of the Text property of the Quantity user control, located
in the current row of the GridView control.
8 Lab Instructions: Optimizing Data Management for Web Forms
n. Append code to the gvCart_RowUpdating method, to save the updated cart to Session state.
' Save updated cart to session
Session("_cart") = cart
o. Append code to the gvCart_RowUpdating method, for resetting the edit index and bind the
data by using the BindData method.
' Reset edit index
gvCart.EditIndex = -1
' Bind data
BindData()
Note: Observe how the Quantity user control has been registered using the Register directive, and the
user control has been added to the Web Form.
a. Move the markup for the Quantity user control to the top of the EditItemTemplate element.
<EditItemTemplate>
<uc1:Quantity ID="Quantity1" runat="server" />
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("Quantity")
%>'></asp:TextBox>
</EditItemTemplate>
b. Copy the Text attribute and value from the TextBox1 control to the Quantity1 control.
<uc1:Quantity ID="Quantity1" runat="server" Text='<%# Bind("Quantity") %>' />
c. Add code to prevent page index to change, when in edit mode, and display an appropriate error
message in the lblMessage Label control, by using the following code.
' Cancel paging operation if user attempts to navigate
' to another page while in edit mode
If CType(sender, GridView).EditIndex <> -1 Then
' Cancel paging operation
e.Cancel = True
Note: Observe how the Quantity and Total Price columns are updated.
Note: Observe that the customized pager has been added to the GridView, now that more items than
the specified page size have been added to the GridView.
Note: The page index is changed and the content updated appropriately.
10 Lab Instructions: Optimizing Data Management for Web Forms
u. Add an empty HTML th element to the LayoutTemplate element. Make the th element a server
control and place it at the top of the HTML tr element.
<th runat="server">
</th>
v. Add an empty HTML td element to the SelectedItemTemplate element. Place it at the top of
the HTML tr element.
<td>
</td>
x. Add a new LinqDataSource control with the following markup, within the empty HTML p
element.
<asp:LinqDataSource ID="SalesOrderDetailsLinqDataSource" runat="server"
ContextTypeName="AdventureWorks.AdventureWorksLT2008Entities"
EntityTypeName="" TableName="SalesOrderDetails" Where="SalesOrderID ==
@SalesOrderID">
<WhereParameters>
<asp:ControlParameter ControlID="SalesOrdersListView" Name="SalesOrderID"
PropertyName="SelectedValue"
Type="Int32" DefaultValue="0" />
</WhereParameters>
</asp:LinqDataSource>
y. Add a DetailsView control with the following markup, at the top of the new HTML p element.
<asp:DetailsView ID="SalesOrderDetailDetailsView" runat="server"
DataSourceID="SalesOrderDetailsLinqDataSource"
Height="50px" Width="125px" AutoGenerateRows="False">
<Fields>
<asp:BoundField DataField="SalesOrderDetailID"
HeaderText="SalesOrderDetailID" SortExpression="SalesOrderDetailID" />
<asp:BoundField DataField="OrderQty" HeaderText="OrderQty"
SortExpression="OrderQty" />
<asp:BoundField DataField="ProductID" HeaderText="ProductID"
SortExpression="ProductID" />
<asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice"
SortExpression="UnitPrice" />
<asp:BoundField DataField="UnitPriceDiscount" HeaderText="UnitPriceDiscount"
SortExpression="UnitPriceDiscount" />
<asp:BoundField DataField="LineTotal" HeaderText="LineTotal"
SortExpression="LineTotal" />
<asp:BoundField DataField="rowguid" HeaderText="rowguid"
SortExpression="rowguid" />
<asp:BoundField DataField="ModifiedDate" HeaderText="ModifiedDate"
SortExpression="ModifiedDate" />
</Fields>
12 Lab Instructions: Optimizing Data Management for Web Forms
</asp:DetailsView>
Note: Observe how the Chart shows how the number of items per order are shown by order date.
f Task 6: Turn off the virtual machine and revert the changes
In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Turn Off.
a. In the Turn Off Machine dialog box, click Turn Off.
b. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then
click Revert.
Lab Instructions: Optimizing Data Management for Web Forms 13
Note: The answers to the exercises are on the Course Companion CD.
14 Lab Instructions: Optimizing Data Management for Web Forms
Section 2: Visual C#
Exercise 1: Managing Data by Using LINQ to Entities
The main tasks in this exercise are as follows:
c. Add a public property named Text to the user control. The property must be of type string, and
get and set the Text property of the QuantityTextBox control.
public string Text
{
get
{
return QuantityTextBox.Text;
}
set
{
QuantityTextBox.Text = value;
}
}
Note: Observe the Build succeeded message in the Build pane of the Output window.
16 Lab Instructions: Optimizing Data Management for Web Forms
b. Modify the auto-implemented Quantity property, to get and set the productQuantity member
variable.
public int Quantity
{
get
{
return productQuantity;
}
set
{
productQuantity = value;
}
}
Note: Observe how the Quantity field/column has been converted into a TemplateField, and the
newly added Total Price TemplateField.
h. Add code to the gvCart_RowEditing method, for setting the edit index and bind the data by
using the BindData method.
protected void gvCart_RowEditing(object sender, GridViewEditEventArgs e)
{
// Set edit index
gvCart.EditIndex = e.NewEditIndex;
// Bind data
BindData();
}
i. Add code to the gvCart_RowCancelingEdit method, for resetting the edit index and bind the
data by using the BindData method.
protected void gvCart_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
{
// Reset edit index
gvCart.EditIndex = -1;
// Bind data
BindData();
}
j. Add code to the gvCart_RowUpdating method, for retrieving the existing cart from Session.
// Retrieve existing cart from session
List<ShoppingCart> cart = (List<ShoppingCart>) Session["_cart"];
k. Append code to the gvCart_RowUpdating method, for retrieving the current row from the
GridView control.
// Get current row
GridViewRow row = gvCart.Rows[e.RowIndex];
l. Append code to the gvCart_RowUpdating method, for finding the matching row in the stored
cart, stored in a new variable named cartToEdit of type ShoppingCart. Use the generic List Find
method with an anonymous Lambda expression.
// Find matching row in stored cart
ShoppingCart cartToEdit = cart.Find((cartToFind) => cartToFind.ProductId ==
int.Parse(row.Cells[1].Text));
m. Append code to the gvCart_RowUpdating method, for updating the quantity value of the
cartToEdit shopping cart with the value of the Text property of the Quantity user control,
located in the current row of the GridView control.
// Update values
Quantity qty = gvCart.Rows[e.RowIndex].FindControl("Quantity1") as Quantity;
cartToEdit.Quantity = int.Parse(qty.Text);
n. Append code to the gvCart_RowUpdating method, for saving the updated cart to Session state.
18 Lab Instructions: Optimizing Data Management for Web Forms
o. Append code to the gvCart_RowUpdating method, for resetting the edit index and bind the
data by using the BindData method.
// Reset edit index
gvCart.EditIndex = -1;
// Bind data
BindData();
Note: Observe how the Quantity user control has been registered using the Register directive, and
the user control has been added to the web form.
b. Move the markup for the Quantity user control to the top of the EditItemTemplate element.
<EditItemTemplate>
<uc1:Quantity ID="Quantity1" runat="server" />
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("Quantity")
%>'></asp:TextBox>
</EditItemTemplate>
c. Copy the Text attribute and value from the TextBox1 control to the Quantity1 control.
<uc1:Quantity ID="Quantity1" runat="server" Text='<%# Bind("Quantity") %>' />
f. Format the display of the ListPrice BoundField control using the DataFormatString attribute
and a value of {0:c}.
DataFormatString="{0:c}"
g. Modify the format of the TemplateField control with a HeaderText attribute value of Total
Price, to appear as follows.
<asp:TemplateField HeaderText="Total Price">
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Eval("TotalPrice") %>'
DataFormatString="{0:c}"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
Note: Observe how the Quantity and Total Price columns are updated.
Note: Observe that the customized pager has been added to the GridView, now that more items
than the specified page size has been added to the GridView.
Note: Observe that the page index is changed and the content updated appropriately.
20 Lab Instructions: Optimizing Data Management for Web Forms
u. Add an empty HTML th element to the LayoutTemplate element. Make the th element a server
control and place it at the top of the HTML tr element.
<th runat="server">
</th>
v. Add an empty HTML td element to the SelectedItemTemplate element. Place it at the top of
the HTML tr element.
<td>
</td>
x. Add a new LinqDataSource control with the following markup, within the empty HTML p
element.
<asp:LinqDataSource ID="SalesOrderDetailsLinqDataSource" runat="server"
ContextTypeName="AdventureWorks.AdventureWorksLT2008Entities"
EntityTypeName="" TableName="SalesOrderDetails" Where="SalesOrderID ==
@SalesOrderID">
<WhereParameters>
<asp:ControlParameter ControlID="SalesOrdersListView" Name="SalesOrderID"
PropertyName="SelectedValue"
Type="Int32" DefaultValue="0" />
</WhereParameters>
</asp:LinqDataSource>
y. Add a DetailsView control with the following markup, at the top of the new HTML p element.
<asp:DetailsView ID="SalesOrderDetailDetailsView" runat="server"
DataSourceID="SalesOrderDetailsLinqDataSource"
Height="50px" Width="125px" AutoGenerateRows="False">
<Fields>
<asp:BoundField DataField="SalesOrderDetailID"
HeaderText="SalesOrderDetailID" SortExpression="SalesOrderDetailID" />
<asp:BoundField DataField="OrderQty" HeaderText="OrderQty"
SortExpression="OrderQty" />
<asp:BoundField DataField="ProductID" HeaderText="ProductID"
SortExpression="ProductID" />
<asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice"
SortExpression="UnitPrice" />
<asp:BoundField DataField="UnitPriceDiscount" HeaderText="UnitPriceDiscount"
SortExpression="UnitPriceDiscount" />
<asp:BoundField DataField="LineTotal" HeaderText="LineTotal"
SortExpression="LineTotal" />
<asp:BoundField DataField="rowguid" HeaderText="rowguid"
SortExpression="rowguid" />
<asp:BoundField DataField="ModifiedDate" HeaderText="ModifiedDate"
SortExpression="ModifiedDate" />
</Fields>
Lab Instructions: Optimizing Data Management for Web Forms 23
</asp:DetailsView>
Note: Observe how the Chart shows how the number of items per order are shown by order date.
f Task 6: Turn off the virtual machine and revert the changes
In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Turn Off.
a. In the Turn Off Machine dialog box, click Turn Off.
b. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then
click Revert.
24 Lab Instructions: Optimizing Data Management for Web Forms
Note: The answers to the exercises are on the Course Companion CD.
Labb Instructions: Optim
mizing Data Managem
ment for Web Forms 25
L 8B: Optimizzing Da
Lab ata Man
nageme
ent for Web Forms
O
Objectives
After completin
ng this lab, you
u will be able to:
t
Manage da
ata by using ASSP.NET Dynam
mic Data.
In
ntroduction
n
In
n this lab, you will he administration section of the website by using variou
w develop th us ASP.NET datta
ource controls and by using the ASP.NET Dynamic
so D Data framework.
26 Labb Instructions: Optim
mizing Data Managem
ment for Web Forms
Lab Scen
nario
Th
he AdventureW Works Sales team has requessted the addition of an administration section to the weebsite so
th
hat they can manage
m a provide a dashboard to se
information, as well as enior management. As a firsst step
to
oward this end
d, you need to create a set off web form pa
ages that will enable
e es team to do the
the Sale
fo
ollowing:
In
n this lab, you will
w develop th
he administration section of the website by using the ASSP.NET Dynam
mic Data
framework.
Lab Instructions: Optimizing Data Management for Web Forms 27
j. The page displays the List view that contains the data of customer sales order headers.
k. Filter the sales order headers by entries that have the OnlineOrderFlag column set to True.
l. The page now displays no sales order headers, because none of the sales order headers have the
OnlineOrderFlag set to true.
m. View the customers page.
n. Create a new customer, by clicking Insert new item.
o. Save the new customer, with empty fields, and then cancel the new customer.
p. The page displays the List view that contains the data from the Customers table. This is the
default view and the one you are returned to, after cancelling.
q. Edit the last customer displayed.
r. The page displays the Edit view that contains the data for the selected row from the Customers
table.
s. Cancel the edit and close Windows Internet Explorer.
t. Close Microsoft Visual Studio 2010.
f Task 5: Turn off the virtual machine and revert the changes
In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Turn Off.
a. In the Turn Off Machine dialog box, click Turn Off.
b. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then
click Revert.
c. In the Revert Virtual Machine dialog box, click Revert.
Lab Instructions: Optimizing Data Management for Web Forms 29
Section 2: Visual C#
Exercise 4: Managing Data by Using ASP.NET Dynamic Data
The main tasks in this exercise are as follows:
f Task 5: Turn off the virtual machine and revert the changes
In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Turn Off.
a. In the Turn Off Machine dialog box, click Turn Off.
b. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then
click Revert.
c. In the Revert Virtual Machine dialog box, click Revert.
Note: The answers to the exercises are on the Course Companion CD.
Lab Instructions: Ensuring Quality by Debugging, Unit Testing, and Refactoring 1
Module 9
Lab Instructions: Ensuring Quality by Debugging, Unit
Testing, and Refactoring
Contents:
Exercise 1: Configuring Error Handling 4
Exercise 2: Debugging Code 5
Exercise 3: Logging 8
Exercise 4: Creating Unit Tests 12
Exercise 5: Implementing the Test-First/Test-Driven Development
Methodology 15
2 Lab Instructions: Ensurinng Quality by Debuggging, Unit Testing, annd Refactoring
O
Objectives
After completin
ng this lab, you
u will be able to:
t
Configure error
e handling.
Debug code.
Configure logging.
Create unitt tests.
Implement the test-first/ttest-driven devvelopment me
ethodology.
In
ntroduction
n
In
n this lab you will
w configure error
e handlingg in a web application, debug
g code to iden
ntify errors, log
g errors
to
o the event logg, and create and
a run unit te
ests.
Lab Instructions: Ennsuring Quality by Debugging, Unit Testing, and Refactoring 3
L Scen
Lab nario
Adventure Works has requestted that you lo ook into how you
y can improve the quality of the coding. As a
firrst step toward
d this end, you etermined you should look in
ur team has de nto the following functionality and
fe
eatures of Visual Studio 2010 0 and the .NET
T Framework:
Configure error
e handling
Debug code
Log errors
Implement a code-first development methodology
Implement a test-first/tesst-driven deve
elopment meth
hodology
4 Lab Instructions: Ensuring Quality by Debugging, Unit Testing, and Refactoring
f Task 3: Modify Web.config to redirect to the generic error page when an unhandled
error occurs
1. Open the Web.config file.
2. Add the following markup to the system.web element.
<customErrors mode="On" defaultRedirect="~/CustomErrorPage.aspx"/>
Results: After this exercise, you should have created a custom error page for unhandled exceptions.
Lab Instructions: Ensuring Quality by Debugging, Unit Testing, and Refactoring 5
Note: In Visual Studio, in the FormatException was unhandled by user code pane, the error text
Input string was not in a correct format is displayed.
2. Press F5 to continue.
Note: The custom error page is displayed. Do not close Internet Explorer.
[Visual Basic]
Dim category As String = lbCategories.SelectedValue
6. Press F10 to step over the line of code that sets the local variable category to the selected value of
the list.
6 Lab Instructions: Ensuring Quality by Debugging, Unit Testing, and Refactoring
7. Hover the mouse over category and notice it is an empty string, which cannot be parsed by the code
in the Products page.
8. Press SHIFT+F5 to end debugging.
9. In Visual Studio, modify the line of code that sets the local variable category to the selected value of
the list, as follows.
[Visual C#]
string category = lbCategories.SelectedValue == string.Empty ? "5" :
lbCategories.SelectedValue;
[Visual Basic]
Dim category As String = IIf(lbCategories.SelectedValue = String.Empty, "5",
lbCategories.SelectedValue)
Note: If the breakpoint disappears after modifying the line of code, place the cursor on the line of
code, and then press F9.
12. Press F10 to step over the line of code that sets the local variable category to the selected value of
the list.
13. Hover the mouse over category and notice it is a string with the value of 5.
14. Press F5 to continue.
f Task 4: Debug a java script error using breakpoints and single stepping
Run the application in Debug mode.
6. Press F10 to step over the statements of code, until a message box is displayed.
7. In the Message from webpage message box, click OK.
8. Repeat the previous two steps twice.
9. Press F5.
Results: After this exercise, you should have experience debugging Visual C# or Visual Basic, and java
script code.
8 Lab Instructions: Ensuring Quality by Debugging, Unit Testing, and Refactoring
Exercise 3: Logging
The main tasks for this exercise are as follows:
Configure logging to an Error Log.
Set the logging level in the Web.config file to allow for future debugging.
Create a generic error handler.
[Visual Basic]
Imports System.Diagnostics
if (Request["id"] != null)
{
categoryId = Request["id"];
}
try
{
categoryName =
DataAccessLayer.Products.GetCategoryName(int.Parse(categoryId));
}
catch (Exception ex)
{
EventLog Log = new EventLog();
Log.Source = "Application";
Log.WriteEntry(ex.Message, EventLogEntryType.Error);
}
lblCategory.Text = categoryName;
var data =
DataAccessLayer.Products.GetProductsByCategory(int.Parse(categoryId));
gvProducts.DataSource = data;
gvProducts.DataBind();
}
}
[Visual Basic]
Lab Instructions: Ensuring Quality by Debugging, Unit Testing, and Refactoring 9
Try
categoryName =
AdventureWorks.DataAccessLayer.Products.GetCategoryName(Integer.Parse(categoryID))
Catch ex As Exception
Dim Log As New EventLog()
Log.Source = "Application"
Log.WriteEntry(ex.Message, EventLogEntryType.[Error])
End Try
lblCategory.Text = categoryName
Dim data =
AdventureWorks.DataAccessLayer.Products.GetProductsByCategory(Integer.Parse(categoryID
))
gvProducts.DataSource = data
gvProducts.DataBind()
End If
End Sub
5. Open the Event Viewer and show the Application log entry. If necessary, sort the Application log
entries by date and time.
10 Lab Instructions: Ensuring Quality by Debugging, Unit Testing, and Refactoring
f Task 3: Set the logging level in the Web.config file to allow for future debugging
1. Open the Web.config file.
2. In the opening compilation tag, ensure that the value of the debug attribute is set to true.
<compilation debug="true" ...>
[Visual Basic]
Imports System.Diagnostics
log.Source = "Application";
log.WriteEntry(message, EventLogEntryType.Error);
}
[Visual Basic]
Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
Dim message As String =
"Url: " & Request.Path & " Error: " &
Server.GetLastError().ToString()
Dim log As New EventLog()
log.Source = "Application"
log.WriteEntry(message, EventLogEntryType.Error)
End Sub
Close button
Results: After this exercise, you should have experience installing a generic error handler for logging
that can be called by a single method and all modules.
12 Lab Instructions: Ensuring Quality by Debugging, Unit Testing, and Refactoring
[Visual Basic]
Public Function Add(ByVal p1 As Integer, ByVal p2 As Integer) As Integer
Return p1 + p2
End Function
[Visual Basic]
Dim p1 As Integer = 2
[Visual Basic]
Dim p2 As Integer = 3
Lab Instructions: Ensuring Quality by Debugging, Unit Testing, and Refactoring 13
3. In the AddTest method, modify the value assigned to local variable expected to 5.
[Visual C#]
int expected = 5;
[Visual Basic]
Dim expected As Integer = 5
[Visual Basic]
Assert.Inconclusive("Verify the correctness of this test method.")
[Visual Basic]
<TestMethod()> _
Public Sub AddTest()
Dim target As Calculator = New Calculator() ' TODO: Initialize to an appropriate
value
Dim p1 As Integer = 2 ' TODO: Initialize to an appropriate value
Dim p2 As Integer = 3 ' TODO: Initialize to an appropriate value
Dim expected As Integer = 5 ' TODO: Initialize to an appropriate value
Dim actual As Integer
actual = target.Add(p1, p2)
Assert.AreEqual(expected, actual)
End Sub
Note: In the Test Result window, you can see that the AddTest test passed.
[Visual Basic]
Dim expected As Integer = 6
[TestMethod()]
public void AddTest()
{
Calculator target = new Calculator(); // TODO: Initialize to an appropriate value
int p1 = 2; // TODO: Initialize to an appropriate value
int p2 = 3; // TODO: Initialize to an appropriate value
int expected = 6; // TODO: Initialize to an appropriate value
int actual;
actual = target.Add(p1, p2);
Assert.AreEqual(expected, actual);
}
[Visual Basic]
<TestMethod()> _
Public Sub AddTest()
Dim target As Calculator = New Calculator() ' TODO: Initialize to an appropriate
value
Dim p1 As Integer = 2 ' TODO: Initialize to an appropriate value
Dim p2 As Integer = 3 ' TODO: Initialize to an appropriate value
Dim expected As Integer = 6 ' TODO: Initialize to an appropriate value
Dim actual As Integer
actual = target.Add(p1, p2)
Assert.AreEqual(expected, actual)
End Sub
Note: In the Test Result window, you can see that the AddTest test failed.
Results: After this exercise, you should have experience creating unit tests for existing methods.
Lab Instructions: Ensuring Quality by Debugging, Unit Testing, and Refactoring 15
Assert.IsNotNull(target);
int expected = 6;
int unexpected = 5;
int actual = target.Multiply(3, 2);
Assert.AreEqual(expected, actual);
Assert.AreNotEqual(unexpected, actual);
}
[TestMethod()]
public void ClassSubtractMethodTest()
{
Calculator target = new Calculator();
Assert.IsNotNull(target);
int expected = 1;
int unexpected = 6;
int actual = target.Subtract(3, 2);
Assert.AreEqual(expected, actual);
Assert.AreNotEqual(unexpected, actual);
}
[Visual Basic]
<TestMethod()>
Public Sub ClassMultiplyMethodTest()
Dim target As New Calculator()
Assert.IsNotNull(target)
16 Lab Instructions: Ensuring Quality by Debugging, Unit Testing, and Refactoring
Assert.AreEqual(expected, actual)
Assert.AreNotEqual(unexpected, actual)
End Sub
<TestMethod()>
Public Sub ClassSubtractMethodTest()
Dim target As New Calculator()
Assert.IsNotNull(target)
Assert.AreEqual(expected, actual)
Assert.AreNotEqual(unexpected, actual)
End Sub
[Visual Basic]
Public Function Multiply(ByVal p1 As Integer, ByVal p2 As Integer) As Integer
Throw New NotImplementedException()
End Function
Note: In the Test Result window, you can see that the ClassMultiplyMethodTest test failed.
Note: In the Test Result window, you can see that the ClassSubtractMethodTest test failed.
[Visual Basic]
Public Function Multiply (ByVal p1 As Integer, ByVal p2 As Integer) As Integer
Return p1 * p2
End Function
2. Replace the Subtract method in the Calculator class with following code.
[Visual C#]
public int Subtract(int p1, int p2)
{
return p1 - p2;
}
[Visual Basic]
Public Function Subtract(ByVal p1 As Integer, ByVal p2 As Integer) As Integer
Return p1 - p2
End Function
Note: In the Test Result window, you can see that the ClassMultiplyMethodTest test passed.
Note: In the Test Result window, you can see that the ClassSubtractMethodTest test passed.
f Task 7: Turn off the virtual machine and revert the changes
1. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
18 Lab Instructions: Ensuring Quality by Debugging, Unit Testing, and Refactoring
Results: After this exercise, you should have experience creating tests first, and then implementing
methods.
Lab Instructions: Securing a Web Application 1
Module 10
Lab Instructions: Securing a Web Application
Contents:
Exercise 1: Configuring ASP.NET Membership and Roles 4
Exercise 2: Authentication 6
Exercise 3: Authorization 10
2 Lab Instructions: Securinng a Web Application
O
Objectives
After completin
ng this lab, you
u will be able to:
In
ntroduction
n
In w learn how to use the ASP
n this lab you will P.NET Web Site Administration Tool, autheenticate users by
ussing the Login ement custom logic to expire
n control. You will also imple e the password
d in 90 days, and
a
le
earn to create an
a email passw word recovery page. Finally, you will learn how to create
e access rules.
Lab Instructions: Securingg a Web Application 3
L Scen
Lab nario
Th
he Adventure Works Sales te eam has requeested that area
as of the websiite be protecte
ed so that onlyy
au
uthenticated users
u are able to
t access the secure
s areas off the site.
Th
his means you must configure ASP.NET Membership, cre eate users, creeate and assign
n roles, implem
ment
au
uthentication and
a authorizattion, implement Login contrrols, and test th
he web applica
ation.
4 Lab Instructions: Securing a Web Application
User Security
Name Password E-mail Question Security Answer
User Security
Name Password E-mail Question Security Answer
Result: In this exercise, you should have learned how to configure ASP.NET Membership provider by
using the ASP.NET Web Site Administration Tool. You should also have learned how to create users
and role for an ASP.NET web application.
6 Lab Instructions: Securing a Web Application
Exercise 2: Authentication
The main tasks for this exercise are as follows:
Open an existing ASP.NET web application.
Configure an application to use Forms authentication.
Use the Login control.
Set the password options.
Configure password recovery.
Note: When changing the authentication type in the ASP.NET Web Site Administration Tool to
From the internet, the Web.config file is updated automatically.
3. Add a redirect to the existing Login.aspx Web Form in the Account folder, by modifying the self-
closing authentication tag.
<authentication mode="Forms">
<forms loginUrl="~/Account/Login.aspx" timeout="2880" />
</authentication>
ValidationGroup="LoginUserValidationGroup">*</asp:RequiredFieldValidator>
</p>
<p>
<asp:Label ID="PasswordLabel" runat="server"
AssociatedControlID="Password">Password:</asp:Label>
<asp:TextBox ID="Password" runat="server"
CssClass="passwordEntry" TextMode="Password"></asp:TextBox>
<asp:RequiredFieldValidator ID="PasswordRequired" runat="server"
ControlToValidate="Password"
CssClass="failureNotification" ErrorMessage="Password is
required." ToolTip="Password is required."
ValidationGroup="LoginUserValidationGroup">*</asp:RequiredFieldValidator>
</p>
<p>
<asp:CheckBox ID="RememberMe" runat="server"/>
<asp:Label ID="RememberMeLabel" runat="server"
AssociatedControlID="RememberMe" CssClass="inline">Keep me logged in</asp:Label>
</p>
</fieldset>
<p class="submitButton">
<asp:Button ID="LoginButton" runat="server" CommandName="Login"
Text="Log In" ValidationGroup="LoginUserValidationGroup"/>
</p>
</div>
</LayoutTemplate>
</asp:Login>
4. Add a redirect to the EmailPassword.aspx Web Form in the Account folder, by adding the following
markup above the PasswordLabel control.
<asp:HyperLink ID="EmailPasswordHyperLink" runat="server"
NavigateUrl="~/Account/EmailPassword.aspx">Forgot Password?</asp:HyperLink>
Note: The EmailPassword.aspx Web Form has not yet been created.
[Visual Basic]
Imports System.Web.Security
3. Add the following code to the Login class to handle the Authenticate event for the LoginUser
server control.
[Visual C#]
protected void LoginUser_Authenticate(object sender, AuthenticateEventArgs e)
{
// Get the membership details for the user
MembershipUser user = Membership.GetUser(LoginUser.UserName.Trim());
8 Lab Instructions: Securing a Web Application
[Visual Basic]
Protected Sub LoginUser_Authenticate(ByVal sender As Object, ByVal e As
AuthenticateEventArgs) Handles LoginUser.Authenticate
' Get the membership details for the user
Dim user As MembershipUser = Membership.GetUser(LoginUser.UserName.Trim())
</mailSettings>
</system.net>
Result: In this exercise, you should have configured the web application to use Forms authentication,
and how to use the Login controls, including the Login and PasswordRecovery server controls.
10 Lab Instructions: Securing a Web Application
Exercise 3: Authorization
The main tasks for this exercise are as follows:
Open an existing ASP.NET web application.
Allow anonymous access to the EmailPassword Web Form.
Create the secured portion of the site.
Test the web application.
Note: You have access to the EmailPassword Web Form as an anonymous user.
[Visual Basic]
http://localhost:15237/Contributors/Home.aspx
Note: You are denied access, because the user John is not authorized to access the Contributors
folder.
Note: You are now redirected to the Contributors/Home.aspx Web Form, because the user Mary
is authorized to access the Contributors folder.
f Task 5: Turn off the virtual machine and revert the changes
1. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Result: In this exercise, you should have configured authorization for web application, including a
Contributors folder and the EmailPassword.aspx specifically, and tested the web application.
Lab Instructions: Applying Master Pages and CSS 1
Module 11
Lab Instructions: Applying Master Pages and CSS
Contents:
Exercise 1: Modify a Master Page 4
Exercise 2: Create a Nested Master Page 6
Exercise 3: Integrate a Master Page 9
Exercise 4: Implement Control Skins 12
Exercise 5: Apply Styles and Themes 13
2 Lab Instructions: Applyinng Master Pages and CSS
L 11: Applyin
Lab A ng Mastter Page
es and CSS
N
Note: Tasks in this lab will be the same, re
egardless of the programmin
ng language yo
our solution iss using.
O
Objectives:
After completin
ng this lab, you
u will be able to:
t
Modify a master
m page.
Create nestted master pag
ges.
Apply mastter pages.
Apply Them
mes, Skins, and
d Styles.
In
ntroduction
n
In w first modiffy the existing master page for
n this lab, you will f the AdventtureWorks web bsite, add a neew
CoontentPlaceH Holder for the footer conten nt, and implem
ment it in the About.aspx
A pa
age. You will th
hen
crreate an area in the existing master page for f status messsages and imp a child pages. You
plement it for all
w then create two control skkins and applyy them to conttrols in the exissting website. You will also modify
will m
exxisting CSS styyles, create two o themes for th nd implement one
he website bassed on the exissting styles, an
th
heme in the Web.config
W file
e.
Lab Instruuctions: Applying Maaster Pages and CSS 3
L Scen
Lab nario
Adventure Works is redesigning their Webssite in a corporrate branding initiative. You will present tw
wo
op
ptions using th
he new color palette,
p taking advantage of the theme and skin features of ASP.NET to t make
fu
uture changes to the look-an
nd-feel easy to
o perform.
Yo dd an application-wide location for reporting errors and sending messsages to users. You
ou will also ad
ne
eed to implem ment this messaaging location
n consistently across
a the app
plication.
4 Lab Instructions: Applying Master Pages and CSS
</asp:Content>
Note: The rendered page should appear as follows. Notice the text you added at the bottom of the
image.
Lab Instructions: Applying Master Pages and CSS 5
Results: After completing this exercise, you should have added a new ContentPlaceHolder in the
Site.Master master page, and added a new Content control in the About.aspx page displaying a
copyright string for the application using the new ContentPlaceHolder we added to the master page.
6 Lab Instructions: Applying Master Pages and CSS
[Visual Basic]
<%@ Master Language="VB" MasterPageFile="~/Site.Master" AutoEventWireup="false"
CodeBehind="Nested.master.vb" Inherits="AdventureWorks.Nested" %>
<asp:Content ID="Header" ContentPlaceHolderID="HeadContent" runat="server">
</asp:Content>
<asp:Content ID="Main" ContentPlaceHolderID="MainContent" runat="server">
</asp:Content>
<asp:Content ID="Footer" ContentPlaceHolderID="FooterContent" runat="server">
</asp:Content>
f Task 5: Change the Default.aspx page Web Form to use the Nested.master page
1. Modify the Page directive in the Default.aspx file, by adding following markup to change the master
page.
[Visual C#]
<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Nested.master"
AutoEventWireup="true"
CodeBehind="Default.aspx.cs" Inherits="AdventureWorks._Default" %>
[Visual Basic]
<%@ Page Title="Home Page" Language="vb" MasterPageFile="~/Nested.master"
AutoEventWireup="false"
CodeBehind="Default.aspx.vb" Inherits="AdventureWorks._Default" %>
2. Change the ContentPlaceHolder controls to which the Content controls refer to RightContent and
LeftContent. Rename the Content controls to RightBodyContent and LeftBodyContent.
<asp:Content ID="RightBodyContent" runat="server"
ContentPlaceHolderID="RightContent">
...
<asp:Content ID="LeftBodyContent" runat="server" ContentPlaceHolderID="LeftContent">
3. Add the following markup to the Content control with an ID attribute value of RightBodyContent.
<asp:Content ID="RightBodyContent" runat="server"
ContentPlaceHolderID="RightContent">
<p>
Right Content
</p>
</asp:Content>
4. Move the Content control with an ID attribute value of RightBodyContent to after the Content
control with an ID attribute value of LeftBodyContent.
<asp:Content ID="LeftBodyContent" runat="server" ContentPlaceHolderID="LeftContent">
<h2>
Welcome to AdventureWorks!
</h2>
<p>
Product Categories
<br />
<asp:ListBox ID="lbCategories" runat="server" DataTextField="Name"
DataValueField="ProductCategoryID"
Height="270px" Width="186px"></asp:ListBox>
<br />
<asp:Button ID="btnCategory" runat="server" Text="Submit"></asp:Button>
</p>
</asp:Content>
<asp:Content ID="RightBodyContent" runat="server"
ContentPlaceHolderID="RightContent">
<p>
Right Content
</p>
</asp:Content>
Note: The rendered page should appear as follows. Notice the content displayed in two columns.
Results: After completing this exercise, you should have added a new nested master page to the
project, configured the master page to have two new ContentPlaceHolder controls, configured the
Default.aspx page to use the new nested master page, and added configured the content in the page
to use the new ContentPlaceHolder controls.
Lab Instructions: Applying Master Pages and CSS 9
[Visual Basic]
Public Property StatusMessage() As String
Get
Return StatusMessageLabel.Text
End Get
Set(ByVal value As String)
StatusMessageLabel.Text = value
End Set
End Property
[Visual Basic]
<%@ MasterType TypeName="AdventureWorks.Site" %>
10 Lab Instructions: Applying Master Pages and CSS
2. In the Page_Load event handler for the About.aspx page, set the StatusMessage property.
[Visual C#]
protected void Page_Load(object sender, EventArgs e)
{
Master.StatusMessage = "You are on the About page";
}
[Visual Basic]
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
Master.StatusMessage = "You are on the About page"
End Sub
3. In the Page_Load event handler for the Products.aspx page, set the StatusMessage property.
[Visual C#]
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
string categoryName;
string categoryId = "5";
if (Request["id"] != null)
{
categoryId = Request["id"];
}
categoryName =
DataAccessLayer.Products.GetCategoryName(int.Parse(categoryId));
lblCategory.Text = categoryName;
var data =
DataAccessLayer.Products.GetProductsByCategory(int.Parse(categoryId));
gvProducts.DataSource = data;
gvProducts.DataBind();
}
[Visual Basic]
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles
Me.Load
If Not Page.IsPostBack Then
Dim categoryName As String = Nothing
Dim categoryID As String = "5"
categoryName =
AdventureWorks.DataAccessLayer.Products.GetCategoryName(Integer.Parse(categoryID))
lblCategory.Text = categoryName
Dim data =
AdventureWorks.DataAccessLayer.Products.GetProductsByCategory(Integer.Parse(categoryI
D))
gvProducts.DataSource = data
gvProducts.DataBind()
End If
Lab Instructions: Applying Master Pages and CSS 11
Results: After completing this exercise, you should have added a Label control in the Site.Master
master page to display status messages to users, created a property in the Site.Master master page to
set the value of the Label control, and set the value of the property on two pages consuming the
Site.Master master page.
12 Lab Instructions: Applying Master Pages and CSS
Note: Observe the light blue background color in the ListBox control.
Results: After completing this exercise, you should have created a new theme, added a skin file to the
theme containing two named skins for the ListBox control, and applied a named skin to the ListBox
control on the Default.aspx Web Form.
Lab Instructions: Applying Master Pages and CSS 13
4. Change the background color to Red, and close the Modify Style dialog box.
5. Save and close the StyleB.css file.
6. Remove the theme attribute and value from the Page directive.
Theme="Default"
f Task 7: Turn off the virtual machine and revert the changes
1. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Results: After completing this exercise, you should have applied styles to existing elements and
implemented a theme in your application.
Lab Instructions: Developing Client-side Scripts and Services 1
Module 12
Lab Instructions: Developing Client-side Scripts and Services
Contents:
Exercise 1: Using jQuery 4
Exercise 2: Using Advanced jQuery 7
Exercise 3: Creating a WCF Service 9
2 Lab Instructions: Developping Client-side Scrippts and Services
O
Objectives
After completin
ng this lab, you
u will be able to:
Enable clien
nt-side sorting
g.
Use jQuery selectors.
Embed jQu
uery visual effe
ects.
Create a WCF
W Service and
d invoke it usin
ng the client-sside code.
In
ntroduction
n
In
n this lab, you will
w enhance the shopping cart
c interface to support client-side sorting g, and use sele
ectors in
jQ
Query. You willl also embed jQ
Query visual effects
e in your application, crreate a WCF se
ervice, and the
en
in
nvoke it using the
t client-side
e code.
Lab Instructions: Devveloping Client-side Scripts and Services 3
L Scen
Lab nario
Yo
ou have also been
b requested
d to display addvertisement innformation abbout the produ
ucts when the users
ho
over the mousse over the prooduct name. In u must create a WCF service for retrieving
n addition, you
prroducts, and the service musst be callable from
f client-sid
de code.
4 Lab Instructions: Developing Client-side Scripts and Services
Note: Make sure that you add the closing script tag (</script>) and not the self-closing script tag
(</>). The self-closing tag for the script references is not recognized by the browsers.
Best Practices: For Web Forms applications, you can use the ResolveUrl method, which correctly
resolves the URL relative to the request.
if (this.gvCart.Rows.Count > 0)
{
gvCart.UseAccessibleHeader = true;
gvCart.HeaderRow.TableSection = TableRowSection.TableHeader;
gvCart.FooterRow.TableSection = TableRowSection.TableFooter;
}
}
[Visual Basic]
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles
Me.Load
If Not Session("_cart") Is Nothing Then
Dim cart = CType(Session("_cart"), List(Of clsShoppingCart))
gvCart.DataSource = cart
gvCart.DataBind()
Else
lblMessage.Text = "Your cart is empty"
btnPlaceOrder.Visible = False
End If
Note: Notice how the rows are sorted ascending according to the value of the ID column for the
individual rows.
Result: At the end of this exercise, you should have enhanced the ShoppingCart interface to support
client-side sorting. You also learned how to perform script reference and use selectors in jQuery.
Lab Instructions: Developing Client-side Scripts and Services 7
4. Append the following script element to the Products.aspx Web Form, at the end of the Content
control with an ID attribute value of BodyContent.
<script type="text/javascript">
$(document).ready(function () {
$("a").mouseover(function () {
var divs = $(this).closest("tr").find("div").fadeIn("slow");
});
$("a").mouseout(function () {
var divs = $(this).closest("tr").find("div").fadeOut("slow");
});
});
</script>
</asp:Content>
$(document).ready(function () {
$("a").mouseover(function () {
var divs = $(this).closest("tr").find("div").fadeIn("slow");
});
$("a").mouseout(function () {
var divs = $(this).closest("tr").find("div").fadeOut("slow");
});
});
$(document).ready(function () {
$("a").mouseover(function () {
$(this).closest("tr").find("div").fadeInFadeOut("slow");
});
});
</script>
Note: The custom advertisement message is displayed in the rightmost column, but now it closes after
a short period.
Result: After this exercise, you should be able to embed jQuery effects in your application.
Lab Instructions: Developing Client-side Scripts and Services 9
f Task 3: Add Logic to the query and return a random product from the database
1. Remove the default DoWork method and comments from the service class.
[Visual C#]
// To use HTTP GET, add [WebGet] attribute. (Default ResponseFormat is
WebMessageFormat.Json)
// To create an operation that returns XML,
// add [WebGet(ResponseFormat=WebMessageFormat.Xml)],
// and include the following line in the operation body:
// WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml";
[OperationContract]
public void DoWork()
{
// Add your operation implementation here
return;
}
[Visual Basic]
' To use HTTP GET, add <WebGet()> attribute. (Default ResponseFormat is
WebMessageFormat.Json)
' To create an operation that returns XML,
' add <WebGet(ResponseFormat:=WebMessageFormat.Xml)>,
' and include the following line in the operation body:
' WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml"
<OperationContract()>
Public Sub DoWork()
' Add your operation implementation here
End Sub
' Add more operations here and mark them with <OperationContract()>
[Visual Basic]
Public Class ProductsService
<OperationContract()>
Public Function GetRandomProduct() As String
Dim random = New Random()
Return New
System.Web.Script.Serialization.JavaScriptSerializer().Serialize(randomProduct)
End Using
End Function
End Class
Note: We are invoking the ProductsService from the client side. Hence, we want the returned format
to be XML or Json. For this reason, we are using the JavaScriptSerializer class to serialize the class into
a valid Json format.
f Task 5: Invoke WCF service using client-side code from the master page
1. Open the Site.Master master page.
2. Add a reference to the ProductsService WCF by adding a ScriptManager control.
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="~/ProductsService.svc" />
</Services>
</asp:ScriptManager>
3. Add the following code to the Site.Master master page, after the closing html tag, at the end of the
script element.
getRandomProduct();
function getRandomProduct() {
ProductsService.GetRandomProduct(function (response) {
var product = eval('(' + response + ')');
document.getElementById("ProductName").innerHTML = product.Name;
document.getElementById("ProductNumber").innerHTML = product.ProductNumber;
document.getElementById("ProductPrice").innerHTML = product.ListPrice;
});
}
f Task 6: Turn off the virtual machine and revert the changes
1. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Result: After this exercise, you should have created a WCF service and invoked it using the client-side
code.
Lab Instructions: Implementing Advanced Ajax in a Web Application 1
Module 13
Lab Instructions: Implementing Advanced Ajax in a Web
Application
Contents:
Exercise 1: Using Microsoft Ajax in an MVC Page 4
Exercise 2: Using jQuery in an MVC View 7
Exercise 3: Handling Events 9
2 Lab Instructions: Implem
menting Advanced Ajaax in a Web Application
L Scen
Lab nario
Adding the product catalog to the Adventu ureWorks webssite has been a success. Now
w, you have be
een
assked to enhance the usability of the catalo
og.
Management would
M w like to display two Featured Productts when a user clicks a produ
uct category, to
o
en
ncourage purcchases.
In
n addition, theyy would like to
o show all of th
he products an
nd product cattegories on th
he same page when
th
he user selects a category.
O
Objectives
After completin
ng this lab, stud
dents will be able to:
Dynamically load contentt into a view using Microsoftt Ajax Library.
Dynamically load contentt into a view using jQuery Ajjax.
Add Ajax evvent handlers using jQuery Ajax.
In
ntroduction
n
In w add Ajax libraries to the pages and ma
n this lab, you will aster page, and create a parrtial Ajax MVC view.
Yo e jQuery in an MVC view, an
ou will also use nd handle even
nts using jQue
ery.
4 Lab Instructions: Implementing Advanced Ajax in a Web Application
return View(prodCategories);
}
[Visual Basic]
Public Function Index(ByVal CategoryID As String) As ActionResult
Dim id As Integer = CInt(CategoryID)
Dim prodCategories = pr.GetCategories()
Return View(prodCategories)
End Function
2. Insert the following markup and code in the _AjaxProductCategories.ascx file, after the Control
directive.
[Visual C#]
[Visual Basic]
[Visual Basic]
<h2>
Product Catalog</h2>
<label>
Choose a category:</label>
<br />
<% Html.RenderPartial("_AjaxProductCategories", Model)%>
Products
6. Base the Index view on a different data class, by modifying the Inherits attribute value in the Page
directive.
[Visual C#]
Inherits="System.Web.Mvc.ViewPage<IEnumerable<AdventureWorksMvc.Mo
dels.ProductCategory>>"
[Visual Basic]
Results: After this exercise, you should have added the product line to the index view using the
Microsoft Ajax Library.
Lab Instructions: Implementing Advanced Ajax in a Web Application 7
[Visual Basic]
<br />
<div id="featured-products"></div>
8 Lab Instructions: Implementing Advanced Ajax in a Web Application
3. Create the Ajax method call. This function calls the controller action, and then returns the results into
the featured products div created earlier. Add the following markup to handle the click event for
the rendered select element, at the bottom of the page, before the closing Content tag.
<script type="text/javascript">
$(document).ready(function () {
$("#CategoryID").click(function () {
var id = $(this).val();
$("#featured-products").load('<%= Url.Action("FeaturedProducts") %>', {
CategoryId: id });
});
});
</script>
Note: The products for the chosen category are displayed below the list.
Results: After this exercise, you should have added a "Featured Products" section to the Index.aspx
page. Using jQuery, the page should update the featured products based on the selection in the
Product Categories list.
Lab Instructions: Implementing Advanced Ajax in a Web Application 9
<div class="log"></div>
3. After the featured-products div element, add a div to display the Ajax error messages.
<div class="error"></div>
4. In the $(document).ready jQuery function, add the following functions to display and hide the status
messages.
$(document).ready(function () {
$("#CategoryID").click(function () {
var id = $(this).val();
$("#featured-products").load('<%= Url.Action("FeaturedProducts") %>', {
CategoryId: id });
});
$('.log').ajaxStart(function () {
$(this).text('Loading...');
$('.error').text('');
});
$('.log').ajaxComplete(function () {
$(this).text('');
});
});
$('.error').ajaxError(function () {
$(this).text('There was an error! Please try again later...');
});
[Visual Basic]
$(document).ready(function () {
$("#CategoryID").click(function () {
var id = $(this).val();
$("#featured-products").load('<%= Url.Action("FeaturedProducts") %>', {
CategoryId: id });
});
$('.log').ajaxStart(function () {
$(this).text('Loading...');
$('.error').text('');
});
$('.log').ajaxComplete(function () {
$(this).text('');
});
$('.error').ajaxError(function () {
$(this).text('There was an error! Please try again later...');
});
});
</script>
</asp:Content>
Note: The products for the chosen category are displayed below the list, but first you see the
Loading... notice.
f Task 5: Turn off the virtual machine and revert the changes
1. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Results: After this exercise, you should have used jQuery to provide feedback on the page.
Lab Instructions: ASP.NET Deployments 1
Module 14
Lab Instructions: ASP.NET Deployments
Contents:
Exercise 1: Creating a Profile for Deploying a Web Application Project
Using One-Click Publish 4
Exercise 2: Creating a Web Deployment Package 7
2 Lab Instructions: ASP.NEET Deployments
O
Objectives
After completin
ng this lab, you
u will be able to:
t
Create a One-Click Publish
P profile
e.
Create and deploy a web deploym
ment package.
In
ntroduction
n
In
n this lab, you will
w create a profile
p
for deplloying a web application
a pro
oject using one
e-click publish
h. You
w also create a web deploym
will ment package and use it to deploy a web application to o IIS.
Lab Instructions: ASP.NET Deployments 3
L Scen
Lab nario
Note: An ASP.NET Application Services SQL Server database file ASPNETDB.MDF is created in the
App_Data folder, and the values that you entered have been saved to it.
f Task 6: Update the connection string in the Web.config file by creating a transform file
1. [Visual Basic] Show all files for the Deployment project in Solution Explorer.
2. Expand the Web.config file.
3. Open the Web.Release.config file.
4. Examine and delete the block of comments that contains a connectionStrings element.
5. Insert the following markup after the opening configuration element.
<connectionStrings>
<add name="ApplicationServices"
connectionString="Data
Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\aspnetdb.mdf;Integrated
Security=True;User Instance=True"
providerName="System.Data.SqlClient"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
</connectionStrings>
Note: If you were not using a database file, as in this case, you would typically use the connection
string that you received from your hosting company.
Note: If your hosting company advises you to allow untrusted certificates, select the Allow untrusted
certificate check box.
7. Save the profile and close the Publish Web dialog box.
8. Close Visual Studio 2010.
Results: After this exercise, you should have created a profile to deploy your web application project
using one-click publish.
Lab Instructions: ASP.NET Deployments 7
3. In the Create New SQL Server Database dialog box, enter the following information, and then click
OK.
Server name: 10264a-gen-dev\SQLEXPRESS
New database name: DeploymentTest
4. In the IIS Web site/application name to use on the destination server box, type Default Web
Site/Deployment.
5. Save the changes.
Note: You are using the same destination connection string for both local databases. Therefore, during
deployment, the scripts that create and populate database objects will all run in the same database.
13. Ensure that the Pull data and/or schema from an existing database check box is selected.
14. In the Connection string for source database box, type Data
Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\AdventureWorksLT2008R2_Data.m
df;Integrated Security=True;Connect Timeout=30;User Instance=True.
15. Set the database scripting options to Schema and Data.
16. Add the D:\Lab Files\CS\Lab 14\Starter\DeploymentGrant.sql or D:\Lab Files\VB\Lab
14\Starter\DeploymentGrant.sql script, by clicking Add Script.
17. Save the changes.
<connectionStrings>
<add name="ApplicationServices"
connectionString="Data Source=10264A-GEN-DEV\SQLEXPRESS;Initial
Catalog=DeploymentTest;Integrated Security=True;Pooling=False"
providerName="System.Data.SqlClient" xdt:Transform="SetAttributes"
xdt:Locator="Match(name)" />
<add name="AW"
connectionString="Data Source=10264A-GEN-DEV\SQLEXPRESS;Initial
Catalog=DeploymentTest;Integrated Security=True;Pooling=False"
providerName="System.Data.SqlClient"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
</connectionStrings>
Note: Visual Studio builds the project and creates the deployment package, displaying a log in the
Output window. As part of the package creation process, the Web Deploy dbFullSQL provider
creates two SQL server scriptsone for each source database. There is only one destination
database, and both of these scripts will run in that database when you import the package.
http://localhost/Deployment
Note: The Default.aspx page is displayed. It looks the same as it does when you run it in Visual
Studio 2010.
Note: The Default.aspx page is displayed, with Welcome student! next to the Log Out link. This
demonstrates that the ASP.NET membership database was deployed successfully.
f Task 10: Turn off the virtual machine and revert the changes
1. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
Lab Instructions: ASP.NET Deployments 11
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Results: After this exercise, you should have created and deployed a Web Application using a Web
Deployment Package.
Lab Instructions: Developing a Web Application by Using Silverlight 1
Module 15
Lab Instructions: Developing a Web Application by Using
Silverlight
Contents:
Exercise 1: Creating a Silverlight Project 5
Exercise 2: Creating a Silverlight WCF Service 6
Exercise 3: Displaying Data by Using Silverlight Controls 8
2 Lab Instructions: Developping a Web Applicatiion by Using Silverligght
O
Objectives
After completin
ng this lab, you
u will be able to:
t
Create a Silverlight projecct.
Create a Silverlight WCF service.
Display datta by using Silvverlight contro
ols.
In
ntroduction
n
In w learn how to add Silverlight to an exissting AdventurreWorks web application.
n this lab, you will a Th
he
Siilverlight application will be used to consu
ume a WCF Serrvice and displlay the data byy using the Da
ataGrid
Siilverlight contrrol.
Lab Instructions: Developingg a Web Application by Using Silverlight 3
L Scen
Lab nario
So
ome of AdventureWorks competitors are experiencing higher web tra affic than Adve
entureWorks.
M
Management wants
w to explorre the feasibilitty of using RIA
A technology to increase use er stickiness wh
hen
deeveloping the AdventureWo orks web site inn future. For thhis purpose, yoou have been tasked
t with creating a
simple prototyppe. The resultin
ng prototype should
s look sim
milar to the following screennshot.
4 Lab Instructions: Developing a Web Application by Using Silverlight
Lab Instructions: Developing a Web Application by Using Silverlight 5
Results: After this exercise, you should have created a Silverlight project and also have become familiar
with how to host a Silverlight project.
6 Lab Instructions: Developing a Web Application by Using Silverlight
f Task 3: Create methods that return a list of product categories, and a list of products by
category
1. Delete the stub method DoWork from the code file.
2. Import the System.Collections.Generic namespace.
3. Add the following method, which returns a list of product categories, to the ProductServiceSL class.
[Visual C#]
[OperationContract]
public IEnumerable<ProductCategory> GetProductCategories()
{
return DataAccessLayer.Products.GetCategories();
}
[Visual Basic]
<OperationContract>
Public Function GetProductCategories() As IEnumerable(Of
ProductCategory)
Return AdventureWorks.DataAccessLayer.Products.GetCategories()
End Function
4. Add the following method that returns a list of products by category, to the ProductServiceSL class.
[Visual C#]
[OperationContract]
public IEnumerable<Product> GetProductsByCategory(int
ProductCategoryID)
{
return DataAccessLayer.Products.GetProductsByCategory(ProductCategoryID);
}
[Visual Basic]
<OperationContract>
Public Function GetProductsByCategory(ProductCategoryID As Integer) As
IEnumerable(Of Product)
Return AdventureWorks.DataAccessLayer.Products.GetProductsByCategory(Prod
uctCategoryID)
End Function
Results: After this exercise, you should have created a Silverlight WCF service and added some code to
return product categories and products from the database.
8 Lab Instructions: Developing a Web Application by Using Silverlight
Height: 14
Width: 100
Content: Categories
9. Make the following changes to the right-most Labels control.
Name: ProductLabel
Height: 14
Width: 100
Content: Products
10. The final result will look something like this:
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-
compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentati
on/sdk" Height="400" Width="600">
12. Configure the CategoriesDataGrid control to display the necessary columns returned from the
GetProductCategories service method, by adding a DataGrid.Columns element to the
CategoriesDataGrid control.
<sdk:DataGrid AutoGenerateColumns="False" Height="156"
HorizontalAlignment="Left" Name="CategoriesDataGrid"
VerticalAlignment="Top" Width="100" Margin="5,30,0,0">
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Binding="{Binding
ProductCategoryID}" Header="ID" Visibility="Collapsed" />
<sdk:DataGridTextColumn Binding="{Binding Name}"
Header="Name" />
</sdk:DataGrid.Columns>
</sdk:DataGrid>
13. Configure the ProductsDataGrid control to display the necessary columns returned from the
GetProductByCategory service method, by adding a DataGrid.Columns element to the
ProductsDataGrid control.
<sdk:DataGrid AutoGenerateColumns="False" Height="300"
HorizontalAlignment="Left" Margin="106,30,0,0"
Name="ProductsDataGrid" VerticalAlignment="Top" Width="370" />
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Binding="{Binding Name}"
Header="Name" />
<sdk:DataGridTextColumn Binding="{Binding ProductNumber}"
Header="Product Number" />
<sdk:DataGridTextColumn Binding="{Binding Color}"
Header="Color" />
<sdk:DataGridTextColumn Binding="{Binding Size}"
Header="Size" />
</sdk:DataGrid.Columns>
</sdk:DataGrid>
[Visual C#]
private void CategoriesDataGrid_SelectionChanged(object sender,
SelectionChangedEventArgs e)
{
[Visual Basic]
Private Sub CategoriesDataGrid_SelectionChanged(ByVal sender As
Lab Instructions: Developing a Web Application by Using Silverlight 11
System.Object, ByVal e As
System.Windows.Controls.SelectionChangedEventArgs) Handles
CategoriesDataGrid.SelectionChanged
End Sub
2. In the MainPage class, create a protected variable for the ProductServiceSLClient object.
[Visual C#]
public partial class MainPage : UserControl
{
protected AdventureWorks.ProductServiceSLClient productService
= new AdventureWorks.ProductServiceSLClient();
...
[Visual Basic]
Public Partial Class MainPage
Inherits UserControl
3. In the MainPage class constructor, wire up event handlers for the two Web service methods.
[Visual C#]
public MainPage()
{
InitializeComponent();
productService.GetProductCategoriesCompleted += new
EventHandler<AdventureWorks.GetProductCategoriesCompletedEventArgs
>(productService_GetProductCategoriesCompleted);
productService.GetProductsByCategoryCompleted += new
EventHandler<AdventureWorks.GetProductsByCategoryCompletedEventArg
s>(productService_GetProductsByCategoryCompleted);
}
[Visual Basic]
Public Sub New()
InitializeComponent()
AddHandler productService.GetProductCategoriesCompleted,
AddressOf productService_GetProductCategoriesCompleted
AddHandler productService.GetProductsByCategoryCompleted,
AddressOf productService_GetProductsByCategoryCompleted
End Sub
4. Each event handler needs a method to execute once the asynchronous call completes.
[Visual C#]
void productService_GetProductsByCategoryCompleted(object sender,
AdventureWorks.GetProductsByCategoryCompletedEventArgs e)
{
[Visual Basic]
Private Sub productService_GetProductCategoriesCompleted(ByVal
sender As Object, ByVal e As
AdventureWorks.GetProductCategoriesCompletedEventArgs)
End Sub
End Sub
5. When the page loads, the CategoriesDataGrid control must be populated. In the class constructor,
add a call to the service method GetProductCategoriesAsync.
[Visual C#]
public MainPage()
{
InitializeComponent();
productService.GetProductCategoriesCompleted += new
EventHandler<AdventureWorks.GetProductCategoriesCompletedEventArgs
>(productService_GetProductCategoriesCompleted);
productService.GetProductsByCategoryCompleted += new
EventHandler<AdventureWorks.GetProductsByCategoryCompletedEventArgs
>(productService_GetProductsByCategoryCompleted);
productService.GetProductCategoriesAsync();
}
[Visual Basic]
Public Sub New()
InitializeComponent()
AddHandler productService.GetProductCategoriesCompleted,
AddressOf productService_GetProductCategoriesCompleted
AddHandler productService.GetProductsByCategoryCompleted,
AddressOf productService_GetProductsByCategoryCompleted
productService.GetProductCategoriesAsync()
End Sub
f Task 5: Bind the data returned from the services to the grids
1. The initial call to GetProductCategoriesAsync returns to
productService_GetProductCategoriesCompleted. In the
productService_GetProductCategoriesCompleted method, bind the results using the ItemsSource
property returned by the service to the grid.
[Visual C#]
void productService_GetProductCategoriesCompleted(object sender,
AdventureWorks.GetProductCategoriesCompletedEventArgs e)
{
CategoriesDataGrid.ItemsSource = e.Result;
}
[Visual Basic]
Sub productService_GetProductCategoriesCompleted(sender As Object,
e As AdventureWorks.GetProductCategoriesCompletedEventArgs)
CategoriesDataGrid.ItemsSource = e.Result
End Sub
Lab Instructions: Developing a Web Application by Using Silverlight 13
2. In the CategoriesDataGrid_SelectionChanged event handler, get the selected category, and retrieve
the products by category.
[Visual C#]
private void CategoriesDataGrid_SelectionChanged(object sender,
SelectionChangedEventArgs e)
{
AdventureWorks.ProductCategory category =
CategoriesDataGrid.SelectedItem as AdventureWorks.ProductCategory;
productService.GetProductsByCategoryAsync(category.ProductCategory
ID);
}
14 Lab Instructions: Developing a Web Application by Using Silverlight
[Visual Basic]
Private Sub CategoriesDataGrid_SelectionChanged(sender As Object,
e As SelectionChangedEventArgs)
Dim category As AdventureWorks.ProductCategory =
TryCast(CategoriesDataGrid.SelectedItem,
AdventureWorks.ProductCategory)
productService.GetProductsByCategoryAsync(category.ProductCategory
ID)
End Sub
[Visual Basic]
Sub productService_GetProductsByCategoryCompleted(sender As
Object, e As
AdventureWorks.GetProductsByCategoryCompletedEventArgs)
ProductsDataGrid.ItemsSource = e.Result
End Sub
public MainPage()
{
InitializeComponent();
productService.GetProductCategoriesCompleted += new
EventHandler<AdventureWorks.GetProductCategoriesCompletedEventArgs
>(productService_GetProductCategoriesCompleted);
productService.GetProductsByCategoryCompleted += new
EventHandler<AdventureWorks.GetProductsByCategoryCompletedEventArg
s>(productService_GetProductsByCategoryCompleted);
productService.GetProductCategoriesAsync();
}
void productService_GetProductsByCategoryCompleted(object
sender, AdventureWorks.GetProductsByCategoryCompletedEventArgs e)
{
ProductsDataGrid.ItemsSource = e.Result;
Lab Instructions: Developing a Web Application by Using Silverlight 15
void productService_GetProductCategoriesCompleted(object
sender, AdventureWorks.GetProductCategoriesCompletedEventArgs e)
{
CategoriesDataGrid.ItemsSource = e.Result;
}
}
[Visual Basic]
Partial Public Class MainPage
Inherits UserControl
Protected productService As New
AdventureWorks.ProductServiceSLClient()
productService.GetProductsByCategoryAsync(category.ParentProductCa
tegoryID)
End Sub
End Class
f Task 6: Bind the data returned from the services to the grids
1. Set AdventureWorksSLTestPage.aspx as the start page.
2. Run the application.
Note: It might take a while to load the data from the WCF service.
Note: Notice how the Products list is populated with all the products for the selected category.
16 Lab Instructions: Developing a Web Application by Using Silverlight
f Task 7: Turn off the virtual machine and revert the changes
1. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Results: After this exercise, you should be able to consume a Silverlight WCF service from a Silverlight
application.
Lab Answer Key: Overview of Web Application Architecture and Design 1
Module 1
Lab Answer Key: Overview of Web Application Architecture
and Design
Contents:
Exercise 1: Exploring the Adventure Works Website 2
Exercise 2: Comparing Web Forms and MVC 5
Exercise 3: Working with the Request Life Cycle 6
2 Lab Answer Key: Overview of Web Application Architecture and Design
a. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project,
or press CTRL+SHIFT+O.
b. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab
01\Starter\WebForms\AdventureWorks.sln or D:\Lab Files\VB\Lab
01\Starter\WebForms\AdventureWorks.sln, and then click Open.
6. Step through the web application startup until you reach the end of Page_Load method.
a. On the Debug menu, click Step Over, or press F10.
b. [Visual C#] Repeat step a six times.
[Visual Basic] Repeat step a four times.
7. Continue the web application.
On the Debug menu, click Continue, or press F5.
Note: The URL displayed in the address bar of Internet Explorer includes the name of the Web
Form or page (Default.aspx) displayed.
On the Start menu of 10264A-GEN-DEV, point to All Programs, click Microsoft Visual Studio
2010, and then click Microsoft Visual Studio 2010.
2. Open the AdventureWorksMvc solution at the following location.
a. In the Microsoft Visual Studio window, on the File menu, click Open Project, or press
CTRL+SHIFT+O.
b. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab
01\Starter\MVC\AdventureWorksMvc.sln or D:\Lab Files\VB\Lab
01\Starter\MVC\AdventureWorksMvc.sln, and then click Open.
Note: The URL displayed in the address bar of Internet Explorer does not include the name of the
page (Index.aspx) displayed.
f Task 2: Examine the markup and code found in the Default.aspx Web Forms page
1. Examine the code in the Default.aspx.cs or Default.aspx.vb code file.
In the Default.aspx.cs or Default.aspx.vb window, notice the code in the Page_Load event
handler, including the Page.IsPostBack property and the Response.Redirect method.
2. Examine the markup in the Default.aspx Web Form.
a. In Solution Explorer, double-click Default.aspx.
b. In the Default.aspx window, notice the markup, including the use of a master page, Content
controls, and ListBox and Button server controls.
f Task 4: Examine the markup and code used for rendering the default MVC page
1. Open the Adventure Works MVC project at the following location:
Language Location
f Task 5: Discuss as a group the differences in the way Web Forms and MVC responds and
delivers content to a request
In the classroom, discuss the differences between the page life cycles of the two different web
application models, Web Forms, and MVC, including the page-centric Web Forms request vs. the
MVC routing, the use of server controls in Web Forms vs. HTML controls, and MVC helper methods.
[Visual Basic]
7. Run the web application and view the rendered Default.aspx page.
On the Debug menu, click Start Without Debugging or click CTRL+F5.
Note: During the pages Load event, the text is added to the lblAdvertisement Label control.
In the AdventureWorks Microsoft Visual Studio window, click the Close button.
[Visual Basic]
[Visual Basic]
8. Run the web application and view the rendered Index.aspx view.
On the Debug menu, click Start Without Debugging or click CTRL+F5.
Note: During the controllers Index action method, the text is added to Index view by using the
ViewData.
f Task 3: Turn off the virtual machine and revert the changes
1. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and
then click Turn Off.
8 Lab Answer Key: Overview of Web Application Architecture and Design
Module 2
Lab Answer Key: Designing a Web Application
Contents:
Exercise 1: Reviewing the Adventure Works Website Structure 2
Exercise 2: Redesign the AdventureWorks Website 2
Exercise 3: Add MVC Capabilities to the AdventureWorks Website 4
2 Lab Answer Key: Designing a Web Application
a. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or
press CTRL+SHIFT+O.
b. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab
02\Solution\Exercise 01\AdventureWorks.sln or D:\Lab Files\VB\Lab 02\Solution\Exercise
01\AdventureWorks.sln and then click Open.
f Task 2: Determine which pages will use Web Forms and which will use MVC
Based on the requirements given, determine and document which pages will remain as Web Forms
pages and which will be implemented in MVC.
f Task 3: Discuss your recommendations and their rationale with the class
Discuss the recommendations created with the class.
a. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or
press CTRL+SHIFT+O.
b. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab
02\Starter\Exercise 03\AdventureWorks.sln or D:\Lab Files\VB\Lab 02\Starter\Exercise
03\AdventureWorks.sln and then click Open.
f Task 3: Add the MVC Assembly references and namespaces to the Web.config file
1. Open the Web.config file in the root AdventureWorks folder.
In Solution Explorer, double-click Web.config.
2. Add the following text to your Web.config file in their proper sections as shown, this adds the
appropriate assemblies to your project and configures special MVC handlers:
<system.web>
<compilation debug="true" targetFramework="4.0">
<assemblies>
Lab Answer Key: Designing a Web Application 5
...
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35"/>
</assemblies>
</compilation>
...
<pages>
<namespaces>
<add namespace="System.Web.Mvc"/>
<add namespace="System.Web.Mvc.Ajax"/>
<add namespace="System.Web.Mvc.Html"/>
<add namespace="System.Web.Routing"/>
</namespaces>
</pages>
<httpHandlers>
<add verb="*" path="*.mvc" validate="false"
type="System.Web.Mvc.MvcHttpHandler"/>
</httpHandlers>
</system.web>
<system.webServer>
...
<handlers>
<remove name="MvcHttpHandler"/>
<add name="MvcHttpHandler" preCondition="integratedMode" verb="*" path="*.mvc"
type="System.Web.Mvc.MvcHttpHandler"/>
</handlers>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31BF3856AD364E35"/>
<bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
a. In the Web.config file, locate the assemblies element in the compilation element.
</system.web>
d. Add opening and closing pages tags, just before the closing system.web tag.
6 Lab Answer Key: Designing a Web Application
<pages>
</pages>
</system.web>
<pages>
<namespaces>
</namespaces>
</pages>
<add namespace="System.Web.Mvc"/>
<add namespace="System.Web.Mvc.Ajax"/>
<add namespace="System.Web.Mvc.Html"/>
<add namespace="System.Web.Routing"/>
g. Add opening and closing httpHandlers tags, just before the closing system.web tag.
<httpHandlers>
</httpHandlers>
</system.web>
</system.webServer>
<system.webServer>
<handlers>
<remove name="MvcHttpHandler"/>
<add name="MvcHttpHandler" preCondition="integratedMode" verb="*"
path="*.mvc" type="System.Web.Mvc.MvcHttpHandler"/>
</handlers>
</system.webServer>
k. Add opening and closing runtime tags, just before the closing configuration tag.
<runtime>
</runtime>
</configuration>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31BF3856AD364E35"/>
<bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
Lab Answer Key: Designing a Web Application 7
[Visual C#]
<?xml version="1.0"?>
<configuration>
<appSettings />
<connectionStrings>
<add name="ApplicationServices" connectionString="data
source=.\SQLEXPRESS;Integrated
Security=SSPI;AttachDBFilename=|DataDirectory|\aspnetdb.mdf;User Instance=true"
providerName="System.Data.SqlClient" />
<add name="AdventureWorksEntities"
connectionString="metadata=res://*/mdlAdventureWorks.csdl|res://*/mdlAdventureWorks.s
sdl|res://*/mdlAdventureWorks.msl;provider=System.Data.SqlClient;provider connection
string="Data Source=.\sqlexpress;Initial
Catalog=AdventureWorksLT2008R2;Integrated
Security=True;MultipleActiveResultSets=True""
providerName="System.Data.EntityClient" />
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089" />
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35"/>
</assemblies>
</compilation>
<authentication mode="Forms">
<forms loginUrl="~/Account/Login.aspx" timeout="2880" />
</authentication>
<membership>
<providers>
<clear />
<add name="AspNetSqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider"
connectionStringName="ApplicationServices" enablePasswordRetrieval="false"
enablePasswordReset="true" requiresQuestionAndAnswer="false"
requiresUniqueEmail="false" maxInvalidPasswordAttempts="5"
minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0"
passwordAttemptWindow="10" applicationName="/" />
</providers>
</membership>
<profile>
<providers>
<clear />
<add name="AspNetSqlProfileProvider"
type="System.Web.Profile.SqlProfileProvider"
connectionStringName="ApplicationServices" applicationName="/" />
</providers>
</profile>
<roleManager enabled="false">
<providers>
<clear />
<add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider"
connectionStringName="ApplicationServices" applicationName="/" />
8 Lab Answer Key: Designing a Web Application
<add name="AspNetWindowsTokenRoleProvider"
type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" />
</providers>
</roleManager>
<pages>
<namespaces>
<add namespace="System.Web.Mvc"/>
<add namespace="System.Web.Mvc.Ajax"/>
<add namespace="System.Web.Mvc.Html"/>
<add namespace="System.Web.Routing"/>
</namespaces>
</pages>
<httpHandlers>
<add verb="*" path="*.mvc" validate="false"
type="System.Web.Mvc.MvcHttpHandler"/>
</httpHandlers>
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<handlers>
<remove name="MvcHttpHandler"/>
<add name="MvcHttpHandler" preCondition="integratedMode" verb="*" path="*.mvc"
type="System.Web.Mvc.MvcHttpHandler"/>
</handlers>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31BF3856AD364E35"/>
<bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
[Visual Basic]
<?xml version="1.0" encoding="utf-8"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<connectionStrings>
<add name="ApplicationServices" connectionString="data
source=.\SQLEXPRESS;Integrated
Security=SSPI;AttachDBFilename=|DataDirectory|\aspnetdb.mdf;User Instance=true"
providerName="System.Data.SqlClient" />
<add name="AdventureWorksEntities"
connectionString="metadata=res://*/mdlAdventureWorks.csdl|res://*/mdlAdventureWorks.s
sdl|res://*/mdlAdventureWorks.msl;provider=System.Data.SqlClient;provider connection
string="Data Source=.\sqlexpress;Initial
Catalog=AdventureWorksLT2008R2;Integrated
Security=True;MultipleActiveResultSets=True""
providerName="System.Data.EntityClient" />
</connectionStrings>
<system.web>
<compilation debug="true" strict="false" explicit="true" targetFramework="4.0">
<assemblies>
<add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089" />
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35"/>
Lab Answer Key: Designing a Web Application 9
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
[Visual C#]
using System.Web.Mvc;
using System.Web.Routing;
[Visual Basic]
Imports System.Web.Mvc
Imports System.Web.Routing
[Visual C#]
using System.Web.Mvc;
using System.Web.Routing;
[Visual Basic]
Imports System.Web.Mvc
Imports System.Web.Routing
2. Create a method named RegisterRoutes to register the MVC routes and exclude routes for existing
Web Form pages, handlers, and WCF services.
[Visual C#]
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{resource}.aspx/{*pathInfo}");
routes.IgnoreRoute("{resource}.svc/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
}
[Visual Basic]
Shared Sub RegisterRoutes(ByVal routes As RouteCollection)
routes.IgnoreRoute("{resource}.axd/{*pathInfo}")
routes.IgnoreRoute("{resource}.aspx/{*pathInfo}")
routes.IgnoreRoute("{resource}.svc/{*pathInfo}")
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
Lab Answer Key: Designing a Web Application 11
In the Global.asax.cs or Global.asax.vb window, in the Global_asax class, type the following
code.
[Visual C#]
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{resource}.aspx/{*pathInfo}");
routes.IgnoreRoute("{resource}.svc/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter
defaults
);
}
[Visual Basic]
Shared Sub RegisterRoutes(ByVal routes As RouteCollection)
routes.IgnoreRoute("{resource}.axd/{*pathInfo}")
routes.IgnoreRoute("{resource}.aspx/{*pathInfo}")
routes.IgnoreRoute("{resource}.svc/{*pathInfo}")
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
New With {.controller = "Home", .action = "Index", .id = ""}
)
End Sub
[Visual C#]
protected void Application_Start(object sender, EventArgs e)
{
RegisterRoutes(RouteTable.Routes);
}
[Visual Basic]
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
RegisterRoutes(RouteTable.Routes)
End Sub
[Visual C#]
RegisterRoutes(RouteTable.Routes);
[Visual Basic]
12 Lab Answer Key: Designing a Web Application
RegisterRoutes(RouteTable.Routes)
[Visual C#]
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-
00c04f79efbc}</ProjectTypeGuids>
[Visual Basic]
<ProjectTypeGuids{349c5851-65df-11da-9384-00065b846f21};{F184B08F-C81C-45F6-A57F-
5ABD9991F28F}</ProjectTypeGuids>
[Visual C#]
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-
bf4b-00c04f79efbc}</ProjectTypeGuids>
[Visual Basic]
<ProjectTypeGuids{349c5851-65df-11da-9384-00065b846f21};{F184B08F-C81C-45F6-A57F-
5ABD9991F28F}</ProjectTypeGuids>
{F85E285D-A4E0-4152-9332-AB1D724D3325};
Note: The top of the project file should look like this.
[Visual C#]
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
...
<ProjectGuid>{A8D6241C-680E-42BA-884B-501CC08D3FA9}</ProjectGuid>
Lab Answer Key: Designing a Web Application 13
<ProjectTypeGuids>{F85E285D-A4E0-4152-9332-AB1D724D3325};{349c5851-65df-11da-
9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
...
[Visual Basic]
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
...
<ProjectGuid>{F9BE0786-D923-4DF0-9483-CE13D5D26A1F}</ProjectGuid>
<ProjectTypeGuids>{F85E285D-A4E0-4152-9332-AB1D724D3325{349c5851-65df-11da-9384-
00065b846f21};{F184B08F-C81C-45F6-A57F-5ABD9991F28F}</ProjectTypeGuids>
...
f Task 6: Turn off the virtual machine and revert the changes
1. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and
then click Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Lab Answer Key: Developing MVC Models 1
Module 3
Lab Answer Key: Developing MVC Models
Contents:
Exercise 1: Exploring the AdventureWorks Database 2
Exercise 2: Adding an ADO.NET Entity Data Model 4
Exercise 3: Model Data Validation 10
2 Lab Answer Key: Developing MVC Models
a. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or
press CTRL+SHIFT+O.
b. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab
03\Starter\Exercise 01\AdventureWorksMvc.sln or D:\Lab Files\VB\Lab 03\Starter\Exercise
01\AdventureWorksMvc.sln and then click Open.
Note: The relationship between the Customer and CustomerAddress table is one-to-many, which
means that a single customer can have multiple addresses.
4 Lab Answer Key: Developing MVC Models
a. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or
press CTRL+SHIFT+O.
b. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab
03\Starter\Exercise 02\AdventureWorksMvc.sln or D:\Lab Files\VB\Lab 03\Starter\Exercise
02\AdventureWorksMvc.sln and then click Open.
a. In Solution Explorer, right-click Models, point to Add, and then click New Item.
b. In the Add New Item AdventureWorksMvc dialog box, in the left pane, click Data.
c. In the middle pane, click ADO.NET Entity Data Model, in the Name box, type
AdventureWorks.edmx, and then click Add.
d. In the Entity Data Model Wizard, on the Choose Model Contents page, click Generate from
database, and then click Next.
2. Use the existing AdventureWorksLT2008ConnectionString connection string to connect to the
database, and save the connection settings in the Web.config file as AdventureWorksEntities.
6 Lab Answer Key: Developing MVC Models
On the Choose Your Data Connection page, in the Which data connection should your
application use to connect to the database? list, click
AdventureWorksLT2008ConnectionString (Settings), in the Save entity connection settings
in Web.config as box, type AdventureWorksEntities, and then click Next.
3. Select the Blog and Blogger tables from the database and name the model namespace
AdventureWorksModel.
Lab Answer Key: Developing MVC Models 7
On the Choose Your Database Objects page, in the Which database objects do you want to
include in your model list, expand Tables, select the Blog and Blogger check boxes, in the
Model Namespace box, type AdventureWorksModel, and then click Finish.
4. Build the solution, and fix any errors.
In the AdventureWorksMvc Microsoft Visual Studio window, on the Build menu, click Build
Solution, or press CTRL+SHIFT+B.
[Visual Basic]
[Visual Basic]
2. Add the following method to the BlogRepository class to return a list of all of the blogs.
[Visual C#]
[Visual Basic]
3. Add the following method to the BlogRepository class to return a list of all of the blogs for a specific
blogger.
[Visual C#]
[Visual Basic]
4. Add the following method to the BlogRepository class to return a specific blog.
[Visual C#]
where blog.BlogID == id
select blog).SingleOrDefault();
}
[Visual Basic]
5. Add the following method to the BlogRepository class to return the name of the blogger.
[Visual C#]
return bloggerName;
}
[Visual Basic]
Return bloggerName
End Function
6. Add the following methods to the BlogRepository class to add, update, delete, and save individual
blogs.
[Visual C#]
[Visual Basic]
10 Lab Answer Key: Developing MVC Models
a. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or
press CTRL+SHIFT+O.
b. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab
03\Starter\Exercise 03\AdventureWorksMvc.sln or D:\Lab Files\VB\Lab 03\Starter\Exercise
03\AdventureWorksMvc.sln and then click Open.
[Visual Basic]
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
[Visual Basic]
Imports System.ComponentModel.DataAnnotations
Imports System.ComponentModel
a. In the Blog.cs or Blog.vb window, add the following code at the top.
[Visual C#]
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
[Visual Basic]
Imports System.ComponentModel.DataAnnotations
Imports System.ComponentModel
[DisplayName("Date Posted")]
[DisplayFormat(DataFormatString = "{0:d}")]
public object DatePosted { get; set; }
[Required]
public object Title { get; set; }
[Required]
[DisplayName("Blog Entry")]
public object BlogEntry { get; set; }
}
[Visual Basic]
<DisplayName("Date Posted")>
<DisplayFormat(DataFormatString:="{0:d}")>
Public Property DatePosted As Object
<Required()>
Public Property Title As Object
In the Blog.cs or Blog.vb window, add the following code at the bottom.
[Visual C#]
[DisplayName("Date Posted")]
[DisplayFormat(DataFormatString = "{0:d}")]
public object DatePosted { get; set; }
[Required]
public object Title { get; set; }
[Required]
[DisplayName("Blog Entry")]
public object BlogEntry { get; set; }
}
[Visual Basic]
<DisplayName("Date Posted")>
<DisplayFormat(DataFormatString:="{0:d}")>
Public Property DatePosted As Object
<Required()>
Public Property Title As Object
2. Apply the MetadataType attribute to the Blog class, and reference the Blog_Metadata type as the
metadata type.
[Visual C#]
[MetadataType(typeof(Blog_MetaData))]
public partial class Blog
[Visual Basic]
<MetadataType(GetType(Blog_MetaData))>
Partial Public Class Blog
Lab Answer Key: Developing MVC Models 13
In the Blog.cs or Blog.vb window, add the following above the class declaration.
[Visual C#]
[MetadataType(typeof(Blog_MetaData))]
public partial class Blog
[Visual Basic]
<MetadataType(GetType(Blog_MetaData))>
Partial Public Class Blog
f Task 4: Turn off the virtual machine and revert the changes
1. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and
then click Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Lab Answer Key: Developing MVC Controllers 1
Module 4
Lab Answer Key: Developing MVC Controllers
Contents:
Exercise 1: Creating an MVC Controller 2
Exercise 2: Adding code to list the existing blog entries 3
Exercise 3: Adding code to create a new blog entry 7
Exercise 4: Adding code to edit a blog entry 10
Exercise 5: Adding code to delete a blog entry 14
2 Lab Answer Key: Developing MVC Controllers
a. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or
press CTRL+SHIFT+O.
b. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab
04\Starter\Exercise 01\AdventureWorksMvc.sln or D:\Lab Files\VB\Lab 04\Starter\Exercise
01\AdventureWorksMvc.sln and then click Open.
[Visual C#]
[HandleError]
[Visual Basic]
<HandleError()>
[Visual C#]
[HandleError]
[Visual Basic]
<HandleError()>
Lab Answer Key: Developing MVC Controllers 3
3. Verify that the code in the BlogController code file matches the following code.
[Visual C#]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace AdventureWorksMvc.Controllers
{
[HandleError]
public class BlogController : Controller
{
//
// GET: /Blog/
public ActionResult Index()
{
return View();
}
}
}
[Visual Basic]
Namespace AdventureWorksMvc
<HandleError()>
Public Class BlogController
Inherits System.Web.Mvc.Controller
'
' GET: /Blog
a. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or
press CTRL+SHIFT+O.
b. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab
04\Starter\Exercise 02\AdventureWorksMvc.sln or D:\Lab Files\VB\Lab 04\Starter\Exercise
02\AdventureWorksMvc.sln and then click Open.
[Visual C#]
using AdventureWorksMvc.Models;
[Visual Basic]
Not applicable
[Visual C#]
using AdventureWorksMvc.Models;
[Visual Basic]
Not applicable
2. Declare and instantiate a private BlogRepository object at the top of the BlogController class.
[Visual C#]
private BlogRepository blogRepository = new BlogRepository();
[Visual Basic]
Private blogRepository As New BlogRepository()
[Visual C#]
var blogs = blogRepository.GetAllBlogs();
return View(blogs);
[Visual Basic]
Dim blogs = blogRepository.GetAllBlogs()
Lab Answer Key: Developing MVC Controllers 5
Return View(blogs)
2. Verify that the final Index action method matches the following code:
[Visual C#]
public ActionResult Index()
{
var blogs = blogRepository.GetAllBlogs();
return View(blogs);
}
[Visual Basic]
Function Index() As ActionResult
Dim blogs = blogRepository.GetAllBlogs()
Return View(blogs)
End Function
[Visual C#]
public ActionResult Blogger(int id)
{
}
[Visual Basic]
Function Blogger(ByVal id As Integer) As ActionResult
End Function
2. Add code to the Blogger action method to return only the blog entries for the indicated blogger to
the view.
[Visual C#]
var blogs = blogRepository.GetAllBlogs(id);
return View(blogs);
[Visual Basic]
Dim blogs = blogRepository.GetAllBlogs(id)
Return View(blogs)
3. Verify that the final Blogger action method matches the following code.
[Visual C#]
public ActionResult Blogger(int id)
{
var blogs = blogRepository.GetAllBlogs(id);
return View(blogs);
}
6 Lab Answer Key: Developing MVC Controllers
[Visual Basic]
Function Blogger(ByVal id As Integer) As ActionResult
Dim blogs = blogRepository.GetAllBlogs(id)
Return View(blogs)
End Function
[Visual C#]
public ActionResult Details(int id)
{
}
[Visual Basic]
Function Details(ByVal id As Integer) As ActionResult
End Function
2. Add code to the Details action method to return only the indicated blog entry, to the view. However,
if the blog entry no longer exists, redirect the user to the Index view.
[Visual C#]
var blogEntry = blogRepository.GetBlog(id);
if (blogEntry == null)
return RedirectToAction("Index");
return View(blogEntry);
[Visual Basic]
Dim blogEntry = blogRepository.GetBlog(id)
Return View(blogEntry)
3. Verify that the final Details action method matches the following code.
[Visual C#]
public ActionResult Details(int id)
{
var blogEntry = blogRepository.GetBlog(id);
if (blogEntry == null)
return RedirectToAction("Index");
return View(blogEntry);
}
[Visual Basic]
Function Details(ByVal id As Integer) As ActionResult
Lab Answer Key: Developing MVC Controllers 7
Return View(blogEntry)
End Function
[Visual C#]
public ActionResult Create()
{
}
[Visual Basic]
Function Create() As ActionResult
End Function
[Visual C#]
8 Lab Answer Key: Developing MVC Controllers
[Visual Basic]
Function Create() As ActionResult
End Function
2. Add code to the Create action method to return an empty ActionResult, to the view.
[Visual C#]
return View();
[Visual Basic]
Return View()
3. Verify that the final Create action method matches the following code:
[Visual C#]
public ActionResult Create()
{
return View();
}
[Visual Basic]
Function Create() As ActionResult
Return View()
End Function
[Visual C#]
[HttpPost]
public ActionResult Create(Blog blog)
{
}
[Visual Basic]
<HttpPost()>
Function Create(ByVal blg As Blog) As ActionResult
End Function
2. Add code to the Create action method to save the new Blog object and redirect the user to the
Index view. However, if the call to the Save method fails, return the user to the Create view.
[Visual C#]
if (!ModelState.IsValid)
return View(blog);
try
{
Lab Answer Key: Developing MVC Controllers 9
blog.DatePosted = DateTime.Now;
blogRepository.AddBlog(blog);
blogRepository.Save();
return RedirectToAction("Index");
}
catch (Exception)
{
return View(blog);
};
[Visual Basic]
If ModelState.IsValid Then
Try
blg.DatePosted = DateTime.Now
blogRepository.AddBlog(blg)
blogRepository.Save()
Return RedirectToAction("Index")
Catch
Return View(blg)
End Try
End If
Return View(blg)
3. Verify that the final Create action method that for the HTTP Post request matches the following code.
[Visual C#]
[HttpPost]
public ActionResult Create(Blog blog)
{
if (!ModelState.IsValid)
return View(blog);
try
{
blog.DatePosted = DateTime.Now;
blogRepository.AddBlog(blog);
blogRepository.Save();
return RedirectToAction("Index");
}
catch (Exception)
{
return View(blog);
};
}
[Visual Basic]
<HttpPost()>
Function Create(ByVal blg As Blog) As ActionResult
If ModelState.IsValid Then
10 Lab Answer Key: Developing MVC Controllers
Try
blg.DatePosted = DateTime.Now
blogRepository.AddBlog(blg)
blogRepository.Save()
Return RedirectToAction("Index")
Catch
Return View(blg)
End Try
End If
Return View(blg)
End Function
a. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or
press CTRL+SHIFT+O.
b. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab
04\Starter\Exercise 04\AdventureWorksMvc.sln or D:\Lab Files\VB\Lab 04\Starter\Exercise
04\AdventureWorksMvc.sln and then click Open.
[Visual C#]
public ActionResult Edit(int id)
{
}
[Visual Basic]
Lab Answer Key: Developing MVC Controllers 11
[Visual C#]
public ActionResult Edit(int id)
{
}
[Visual Basic]
Function Edit(ByVal id As Integer) As ActionResult
End Function
2. Add code to the Edit action method to return the indicated Blog entry, to the view. However, if the
blog entry no longer exists, redirect the user to the Index view.
[Visual C#]
var blog = blogRepository.GetBlog(id);
if (blog == null)
return RedirectToAction("Index");
return View(blog);
[Visual Basic]
Dim blogEntry = blogRepository.GetBlog(id)
Return View(blogEntry)
3. Verify that the final Edit action method matches the following code.
[Visual C#]
public ActionResult Edit(int id)
{
var blog = blogRepository.GetBlog(id);
if (blog == null)
return RedirectToAction("Index");
return View(blog);
}
[Visual Basic]
Function Edit(ByVal id As Integer) As ActionResult
Dim blogEntry = blogRepository.GetBlog(id)
Return View(blogEntry)
12 Lab Answer Key: Developing MVC Controllers
End Function
[Visual C#]
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
}
[Visual Basic]
<HttpPost()>
Function Edit(ByVal id As Integer, ByVal collection As FormCollection) As
ActionResult
End Function
2. Add code to the Edit action method to save the blog entry and redirect the user to the Index view.
However, if the call to the Save method fails, return the user to the Edit view. Also, if the blog entry
no longer exists, redirect the user to the Index view.
[Visual C#]
var blog = blogRepository.GetBlog(id);
if (blog == null)
return RedirectToAction("Index");
try
{
UpdateModel(blog, collection.ToValueProvider());
blogRepository.UpdateBlog(blog);
blogRepository.Save();
return RedirectToAction("Index");
}
catch (Exception)
{
return View(blog);
};
[Visual Basic]
Dim blogEntry = blogRepository.GetBlog(id)
Try
UpdateModel(blogEntry, collection.ToValueProvider())
blogRepository.UpdateBlog(CType(blogEntry, Blog))
blogRepository.Save()
Return RedirectToAction("Index")
Catch
Return View(blogEntry)
End Try
3. Verify that the final Edit action method for an HTTP Post request matches the following code.
[Visual C#]
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
var blog = blogRepository.GetBlog(id);
if (blog == null)
return RedirectToAction("Index");
try
{
UpdateModel(blog, collection.ToValueProvider());
blogRepository.UpdateBlog(blog);
blogRepository.Save();
return RedirectToAction("Index");
}
catch (Exception)
{
return View(blog);
};
}
[Visual Basic]
<HttpPost()>
Function Edit(ByVal id As Integer, ByVal collection As FormCollection) As
ActionResult
Dim blogEntry = blogRepository.GetBlog(id)
Try
UpdateModel(blogEntry, collection.ToValueProvider())
blogRepository.UpdateBlog(CType(blogEntry, Blog))
blogRepository.Save()
Return RedirectToAction("Index")
Catch
Return View(blogEntry)
End Try
End Function
In the AdventureWorksMvc Microsoft Visual Studio window, click the Close button.
[Visual C#]
public ActionResult Delete(int id)
{
}
[Visual Basic]
Function Delete(ByVal id As Integer) As ActionResult
End Function
[Visual C#]
public ActionResult Delete(int id)
{
}
[Visual Basic]
Function Delete(ByVal id As Integer) As ActionResult
End Function
2. Add code to the Delete action method to redirect to the Index view.
[Visual C#]
var blog = blogRepository.GetBlog(id);
Lab Answer Key: Developing MVC Controllers 15
if (blog == null)
return RedirectToAction("Index");
return View(blog);
[Visual Basic]
Dim blogEntry = blogRepository.GetBlog(id)
Return View(blogEntry)
3. Verify that the final Delete action method matches the following code.
[Visual C#]
public ActionResult Delete(int id)
{
var blog = blogRepository.GetBlog(id);
if (blog == null)
return RedirectToAction("Index");
return View(blog);
}
[Visual Basic]
Function Delete(ByVal id As Integer) As ActionResult
Dim blogEntry = blogRepository.GetBlog(id)
Return View(blogEntry)
End Function
[Visual C#]
[HttpPost]
public ActionResult Delete(int id, string confirmation)
{
}
[Visual Basic]
<HttpPost()>
Function Delete(ByVal id As Integer, ByVal confirmation As String) As ActionResult
End Function
16 Lab Answer Key: Developing MVC Controllers
2. Add code to the Delete action method to delete the blog entry and redirect the user to the Index
view.
[Visual C#]
var blog = blogRepository.GetBlog(id);
if (blog == null)
return RedirectToAction("Index");
blogRepository.DeleteBlog((Blog) blog);
blogRepository.Save();
return RedirectToAction("Index");
[Visual Basic]
Dim blogEntry = blogRepository.GetBlog(id)
blogRepository.DeleteBlog(CType(blogEntry, Blog))
blogRepository.Save()
Return RedirectToAction("Index")
3. Verify that the final Delete action method for an HTTP Post request matches the following code.
[Visual C#]
[HttpPost]
public ActionResult Delete(int id, string confirmation)
{
var blog = blogRepository.GetBlog(id);
if (blog == null)
return RedirectToAction("Index");
blogRepository.DeleteBlog((Blog) blog);
blogRepository.Save();
return RedirectToAction("Index");
}
[Visual Basic]
<HttpPost()>
Function Delete(ByVal id As Integer, ByVal confirmation As String) As ActionResult
Dim blogEntry = blogRepository.GetBlog(id)
blogRepository.DeleteBlog(CType(blogEntry, Blog))
Lab Answer Key: Developing MVC Controllers 17
blogRepository.Save()
Return RedirectToAction("Index")
End Function
f Task 4: Turn off the virtual machine and revert the changes
1. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and
then click Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Lab Answer Key: Developing MVC Views 1
Module 5
Lab Answer Key: Developing MVC Views
Contents:
Exercise 1: Develop a List MVC View 4
Exercise 2: Develop a Details MVC view 5
Exercise 3: Develop a Create MVC view 7
Exercise 4: Develop an Edit MVC view 13
Exercise 5: Develop a Delete MVC view 19
2 Lab Answer Key: Developing MVC Views
a. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or
press CTRL+SHIFT+O.
b. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab
05\Starter\Exercise 01\AdventureWorksMvc.sln or D:\Lab Files\VB\Lab 05\Starter\Exercise
01\AdventureWorksMvc.sln and then click Open.
[Visual C#]
<li><%= Html.ActionLink("Blog", "", "Blog")%></li>
[Visual Basic]
<li><%: Html.ActionLink("Blog", "", "Blog")%></li>
[Visual C#]
<ul id="menu">
<li><%= Html.ActionLink("Home", "Index", "Home")%></li>
<li><%= Html.ActionLink("Blog", "", "Blog")%></li>
<li><%= Html.ActionLink("About", "About", "Home")%></li>
/ul>
[Visual Basic]
<ul id="menu">
Lab Answer Key: Developing MVC Views 3
[Visual C#]
System.Web.Mvc.ViewPage<IEnumerable<AdventureWorksMvc.Models.Blog>
>
[Visual Basic]
System.Web.Mvc.ViewPage(Of IEnumerable (Of
AdventureWorksMvc.Blog))
4. Add the following markup and code to the Index view in the Content2 Content control,
immediately after the h2 element.
[Visual C#]
<% foreach (var item in Model)
{ %>
<div>
<%: Html.ActionLink("Details", "Details", new { id=item.BlogID })%>
<%: item.DatePosted %>
-
<%: item.Title %>
</div>
<% } %>
[Visual Basic]
<% For Each item As AdventureWorksMvc.Blog In Model%>
<div>
<%: Html.ActionLink("Details", "Details", New With {.id = item.BlogID})%>
<%: item.DatePosted %>
-
<%: item.Title %>
</div>
<% Next%>
4 Lab Answer Key: Developing MVC Views
5. Verify that the markup and code in the Index view matches the following.
[Visual C#]
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<IEnumerable<AdventureWorksMvc.Models.Blog>>" %>
[Visual Basic]
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage(Of IEnumerable (Of AdventureWorksMvc.Blog))" %>
In the Index Windows Internet Explorer window, click the Close button.
4. Close Visual Studio 2010.
In the AdventureWorksMvc Microsoft Visual Studio window, click the Close button.
a. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or
press CTRL+SHIFT+O.
b. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab
05\Starter\Exercise 02\AdventureWorksMvc.sln or D:\Lab Files\VB\Lab 05\Starter\Exercise
02\AdventureWorksMvc.sln and then click Open.
Blogger:
<%: Model.Blogger.Name %>
DatePosted:
<%: Model.DatePosted %>
<h3>
</p>
6 Lab Answer Key: Developing MVC Views
3. Verify that the markup and code in the Details view matches the following.
[Visual C#]
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<AdventureWorksMvc.Models.Blog>" %>
[Visual Basic]
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage(Of AdventureWorksMvc.Blog)" %>
In the AdventureWorksMvc Microsoft Visual Studio window, click the Close button.
a. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or
press CTRL+SHIFT+O.
b. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab
05\Starter\Exercise 03\AdventureWorksMvc.sln or D:\Lab Files\VB\Lab 05\Starter\Exercise
03\AdventureWorksMvc.sln and then click Open.
f Task 2: Add a strongly-typed view named Blogger to list all of the blogs for a particular
blogger
1. Add an empty, strongly-typed view named Blogger based on the Site.Master master page, to the
Blog folder.
a. In Solution Explorer, expand Views, right-click Blog, point to Add, and then click View.
b. In the Add View dialog box, in the View name box, type Blogger, and then click Add.
2. Update the Blogger view to a strongly-typed view of type IEnumerable of type Blog.
[Visual C#]
System.Web.Mvc.ViewPage<IEnumerable<AdventureWorksMvc.Models.Blog>>
[Visual Basic]
System.Web.Mvc.ViewPage(Of IEnumerable (Of AdventureWorksMvc.Blog))
[Visual C#]
System.Web.Mvc.ViewPage<IEnumerable<AdventureWorksMvc.Models.Blog>>
[Visual Basic]
System.Web.Mvc.ViewPage(Of IEnumerable (Of AdventureWorksMvc.Blog))
3. Add the following markup and code to the Blogger view in the Content2 Content control,
immediately after the h2 element.
[Visual C#]
<% foreach (var item in Model)
8 Lab Answer Key: Developing MVC Views
{ %>
<div>
<%: Html.ActionLink("Edit", "Edit", new { id=item.BlogID })%>
<%: Html.ActionLink("Delete", "Delete", new { id=item.BlogID })%>
<%: item.DatePosted %>
-
<%: item.Title %>
</div>
<% } %>
<p>
<%: Html.ActionLink("Create New", "Create") %>
</p>
[Visual Basic]
<% For Each item As AdventureWorksMvc.Blog In Model%>
<div>
<%: Html.ActionLink("Edit", "Edit", New With {.id = item.BlogID})%>
<%: Html.ActionLink("Delete", "Delete", New With {.id = item.BlogID})%>
<%: item.DatePosted %>
-
<%: item.Title %>
</div>
<% Next%>
<p>
<%: Html.ActionLink("Create New", "Create") %>
</p>
4. Verify that the markup and code in the Blogger view matches the following.
[Visual C#]
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<IEnumerable<AdventureWorksMvc.Models.Blog>>" %>
[Visual Basic]
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage(Of IEnumerable (Of AdventureWorksMvc.Blog))" %>
Lab Answer Key: Developing MVC Views 9
[Visual C#]
<% using (Html.BeginForm())
{%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.Title) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Title) %>
<%: Html.ValidationMessageFor(model => model.Title) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.BlogEntry) %>
</div>
<div class="editor-field">
<%: Html.TextAreaFor(model => model.BlogEntry, new { cols = "85" })%>
<%: Html.ValidationMessageFor(model => model.BlogEntry) %>
</div>
</fieldset>
<input type="submit" value="Submit" />
<% } %>
10 Lab Answer Key: Developing MVC Views
<div>
<%: Html.ActionLink("Back to List", "Blogger") %>
</div>
[Visual Basic]
<% Using (Html.BeginForm())%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(Function(m) m.Title)%>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(Function(m) m.Title)%>
<%: Html.ValidationMessageFor(Function(m) m.Title)%>
</div>
<div class="editor-label">
<%: Html.LabelFor(Function(m) m.BlogEntry)%>
</div>
<div class="editor-field">
<%: Html.TextAreaFor(Function(m) m.BlogEntry, New With {.cols = "85"})%>
<%: Html.ValidationMessageFor(Function(m) m.BlogEntry)%>
</div>
</fieldset>
<input type="submit" value="Submit" />
<% End Using%>
<div>
<%: Html.ActionLink("Back to List", "Blogger") %>
</div>
3. Verify that the markup and code in the Create view matches the following.
[Visual C#]
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<AdventureWorksMvc.Models.Blog>" %>
</fieldset>
<input type="submit" value="Submit" />
<% } %>
<div>
<%: Html.ActionLink("Back to List", "Blogger") %>
</div>
</asp:Content>
[Visual Basic]
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage(Of AdventureWorksMvc.Blog)" %>
blog/blogger/1
In the Welcome to AdventureWorks Windows Internet Explorer window, in the address bar,
append the following text.
blog/blogger/1
[Visual C#]
<% if (TempData["ConfirmationMessage"] != null)
{ %>
<div class="message">
<%: TempData["ConfirmationMessage"]%>
</div>
<% } %>
[Visual Basic]
<% If Not TempData("ConfirmationMessage") Is Nothing Then%>
<div class="message">
<%: TempData("ConfirmationMessage")%>
</div>
<% End If%>
3. Verify that the markup and code in the Index view matches the following.
[Visual C#]
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<IEnumerable<AdventureWorksMvc.Models.Blog>>" %>
blog/blogger/1
In the Welcome to AdventureWorks Windows Internet Explorer window, in the address bar,
append the following text.
blog/blogger/1
[Visual C#]
<% using (Html.BeginForm())
{%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.Title) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Title) %>
<%: Html.ValidationMessageFor(model => model.Title) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.BlogEntry) %>
</div>
<div class="editor-field">
<%: Html.TextAreaFor(model => model.BlogEntry, new { cols = "85" })%>
<%: Html.ValidationMessageFor(model => model.BlogEntry) %>
</div>
</fieldset>
<input type="submit" value="Submit" />
Lab Answer Key: Developing MVC Views 15
<% } %>
<div>
<%: Html.ActionLink("Back to List", "Blogger") %>
<div>
[Visual Basic]
<% Using (Html.BeginForm())%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(Function(m) m.Title)%>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(Function(m) m.Title)%>
<%: Html.ValidationMessageFor(Function(m) m.Title)%>
</div>
<div class="editor-label">
<%: Html.LabelFor(Function(m) m.BlogEntry)%>
</div>
<div class="editor-field">
<%: Html.TextAreaFor(Function(m) m.BlogEntry, New With {.cols = "85"})%>
<%: Html.ValidationMessageFor(Function(m) m.BlogEntry)%>
</div>
</fieldset>
<input type="submit" value="Submit" />
<% End Using%>
<div>
<%: Html.ActionLink("Back to List", "Blogger") %>
</div>
[Visual C#]
<%@ Control Language="C#"
Inherits="System.Web.Mvc.ViewUserControl<AdventureWorksMvc.Models.Blog>" %>
<% using (Html.BeginForm())
{%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.Title) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Title) %>
<%: Html.ValidationMessageFor(model => model.Title) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.BlogEntry) %>
</div>
<div class="editor-field">
<%: Html.TextAreaFor(model => model.BlogEntry, new { cols = "85" })%>
<%: Html.ValidationMessageFor(model => model.BlogEntry) %>
</div>
</fieldset>
16 Lab Answer Key: Developing MVC Views
[Visual Basic]
<%@ Control Language="VB" Inherits="System.Web.Mvc.ViewUserControl(Of
AdventureWorksMvc.Blog)" %>
<% Using (Html.BeginForm())%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(Function(m) m.Title)%>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(Function(m) m.Title)%>
<%: Html.ValidationMessageFor(Function(m) m.Title)%>
</div>
<div class="editor-label">
<%: Html.LabelFor(Function(m) m.BlogEntry)%>
</div>
<div class="editor-field">
<%: Html.TextAreaFor(Function(m) m.BlogEntry, New With {.cols = "85"})%>
<%: Html.ValidationMessageFor(Function(m) m.BlogEntry)%>
</div>
</fieldset>
<input type="submit" value="Submit" />
<% End Using%>
<div>
<%: Html.ActionLink("Back to List", "Blogger") %>
</div>
f Task 3: Create an edit view, named Edit, that uses the Blog partial view
1. Add an empty, strongly-typed view of type Blog, named Edit, based on the Site.Master master page,
to the Blog folder.
a. In Solution Explorer, expand Views, right-click Blog, point to Add, and then click View.
b. [Visual C#] In the Add View dialog box, in the View name box, type Edit, select the Create a
strongly-typed view check box, in the View data class box, type
AdventureWorksMvc.Models.Blog, and then click Add.
-or-
[Visual Basic] In the Add View dialog box, in the View name box, type Edit, select the Create a
strongly-typed view check box, in the View data class box, type AdventureWorksMvc.Blog,
and then click Add.
2. Add the following markup and code to the Edit view in the Content2 Content control, immediately
after the h2 element.
[Visual C#]
<% Html.RenderPartial("Blog"); %>
[Visual Basic]
Lab Answer Key: Developing MVC Views 17
3. Verify that the markup and code in the Edit view matches the following.
[Visual C#]
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<AdventureWorksMvc.Models.Blog>" %>
[Visual Basic]
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage(Of AdventureWorksMvc.Blog)" %>
blog/blogger/1
In the Welcome to AdventureWorks Windows Internet Explorer window, in the address bar,
append the following text.
blog/blogger/1
f Task 5: Update the Create view to use the Blog partial view.
1. Replace the markup and code after the h2 element in the Content2 Content element in the Create
view with the following.
[Visual C#]
<% Html.RenderPartial("Blog"); %>
[Visual Basic]
<% Html.RenderPartial("Blog") %>
[Visual C#]
<% Html.RenderPartial("Blog"); %>
[Visual Basic]
<% Html.RenderPartial("Blog") %>
2. Verify that the markup and code in the Create view matches the following.
[Visual C#]
<%@ Page Title="" Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<AdventureWorksMvc.Models.Blog>"
%>
[Visual Basic]
<%@ Page Title="" Language="VB"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage(Of AdventureWorksMvc.Blog)" %>
runat="server">
<h2>
Create</h2>
Lab Answer Key: Developing MVC Views 19
<% Html.RenderPartial("Blog")%>
</asp:Content>
blog/blogger/1
In the Welcome to AdventureWorks Windows Internet Explorer window, in the address bar,
append the following text.
blog/blogger/1
a. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or
press CTRL+SHIFT+O.
b. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab
05\Starter\Exercise 05\AdventureWorksMvc.sln or D:\Lab Files\VB\Lab 05\Starter\Exercise
05\AdventureWorksMvc.sln and then click Open.
20 Lab Answer Key: Developing MVC Views
f Task 2: Add a strongly-typed view named Delete that uses the default markup provided
by the Add View dialog box
1. Build the solution.
In the AdventureWorksMvc Microsoft Visual Studio window, on the Build menu, click Build
Solution, or press CTRL+SHIFT+B.
2. Add a delete, strongly-typed view of type Blog, named Delete, based on the Site.Master master
page, to the Blog folder. The view should use the default content supplied for a Delete operation.
a. In Solution Explorer, expand Views, right-click Blog, point to Add, and then click View.
b. [Visual C#] In the Add View dialog box, in the View name box, type Delete, select the Create a
strongly-typed view check box, in the View data class list, click
AdventureWorksMvc.Models.Blog, in the View content list, click Delete, and then click Add.
-or-
[Visual Basic] In the Add View dialog box, in the View name box, type Delete, select the
Create a strongly-typed view check box, in the View data class list, click
AdventureWorksMvc.Blog, in the View content list, click Delete, and then click Add.
3. Update the markup and code that renders the Back to List link to match the following.
a. In the Delete.aspx window, locate the call to the Html.ActionLink method at the bottom of the
markup.
b. Select the following markup and code.
4. Verify that the markup and code in the Delete view matches the following.
[Visual C#]
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<AdventureWorksMvc.Models.Blog>" %>
DatePosted</div>
<div class="display-field">
<%: String.Format("{0:g}", Model.DatePosted) %></div>
<div class="display-label">
Title</div>
<div class="display-field">
<%: Model.Title %></div>
<div class="display-label">
BlogEntry</div>
<div class="display-field">
<%: Model.BlogEntry %></div>
</fieldset>
<% using (Html.BeginForm())
{ %>
<p>
<input type="submit" value="Delete" />
|
<%: Html.ActionLink("Back to List", "Blogger") %>
</p>
<% } %>
</asp:Content>
[Visual Basic]
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage(Of AdventureWorksMvc.Blog)" %>
</p>
<% End Using%>
</asp:Content>
blog/blogger/1
In the Welcome to AdventureWorks Windows Internet Explorer window, in the address bar,
append the following text.
blog/blogger/1
f Task 4: Turn off the virtual machine and revert the changes
1. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and
then click Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Lab Answer Key: Designing for Discoverability 1
Module 6
Lab Answer Key: Designing for Discoverability
Contents:
Exercise 1: Mapping URLs of Web Forms Pages 2
Exercise 2: Creating a Sitemap File 7
Exercise 3: Building the Application Infrastructure 8
2 Lab Answer Key: Designing for Discoverability
a. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or
press CTRL+SHIFT+O.
b. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab
06\Starter\Exercise 01\AdventureWorks.sln or D:\Lab Files\VB\Lab 06\Starter\Exercise
01\AdventureWorks.sln and then click Open.
[Visual C#]
using System.Web.Routing;
[Visual Basic]
Lab Answer Key: Designing for Discoverability 3
Imports System.Web.Routing
[Visual C#]
void RegisterRoutes(RouteCollection routes)
{
routes.MapPageRoute(
"products-browse", // Route name
"products/{category}", // URL with parameters
"~/Products.aspx" // Web forms page to handle it
);
}
[Visual Basic]
Private Sub RegisterRoutes(ByVal routes As RouteCollection)
' Route name
' URL with parameters
' Web forms page to handle it
routes.MapPageRoute("products-browse", "products/{category}", "~/Products.aspx")
End Sub
In the Global.asax.cs or Global.asax.vb window, in the Global class, add the following code.
[Visual C#]
void RegisterRoutes(RouteCollection routes)
{
routes.MapPageRoute(
"products-browse", // Route name
"products/{category}", // URL with parameters
"~/Products.aspx" // Web forms page to handle it
);
}
[Visual Basic]
Private Sub RegisterRoutes(ByVal routes As RouteCollection)
' Route name
' URL with parameters
' Web forms page to handle it
routes.MapPageRoute("products-browse", "products/{category}",
"~/Products.aspx")
End Sub
[Visual C#]
void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
}
[Visual Basic]
Private Sub Application_Start()
RegisterRoutes(RouteTable.Routes)
End Sub
4 Lab Answer Key: Designing for Discoverability
[Visual C#]
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
string categoryName = null;
string categoryId;
categoryName =
DataAccessLayer.Products.GetCategoryName(int.Parse(categoryId));
lblCategory.Text = categoryName;
var data =
DataAccessLayer.Products.GetProductsByCategory(int.Parse(categoryId));
gvProducts.DataSource = data;
gvProducts.DataBind();
}
}
[Visual Basic]
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
Dim categoryName As String = Nothing
Dim categoryId As String
categoryName =
AdventureWorks.DataAccessLayer.Products.GetCategoryName(Integer.Parse(categoryId))
lblCategory.Text = categoryName
Dim data =
AdventureWorks.DataAccessLayer.Products.GetProductsByCategory(Integer.Parse(categoryI
d))
gvProducts.DataSource = data
gvProducts.DataBind()
End If
End Sub
products/1
Lab Answer Key: Designing for Discoverability 5
In the Home Page Windows Internet Explorer window, in the address bar, append the
following text.
products/1
Note: A grid should render with a single row containing products for the product category, with an ID
value of 1.
[Visual C#]
void RegisterRoutes(RouteCollection routes)
{
routes.MapPageRoute(
"products-browse", // Route name
"products/{category}", // URL with parameters
"~/Products.aspx" // Web forms page to handle it
);
routes.MapPageRoute(
"product-browse", // Route name
"product/{id}", // URL with parameters
"~/ProductDetail.aspx" // Web forms page to handle it
);
}
[Visual Basic]
Private Sub RegisterRoutes(ByVal routes As RouteCollection)
' Route name
' URL with parameters
' Web forms page to handle it
routes.MapPageRoute("products-browse", "products/{category}", "~/Products.aspx")
[Visual C#]
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
string productId;
lblName.Text = data.Name;
lblId.Text = data.ProductID.ToString();
lblColor.Text = data.Color;
lblSize.Text = data.Size;
lblWeight.Text = data.Weight.ToString();
lblListPrice.Text = data.ListPrice.ToString();
hdnProductId.Value = data.ProductID.ToString();
hdnProductName.Value = data.Name;
hdnListPrice.Value = data.ListPrice.ToString();
}
}
[Visual Basic]
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles
Me.Load
If Not Page.IsPostBack Then
Dim productID As String = Nothing
lblName.Text = data.Name
lblId.Text = data.ProductID.ToString()
lblColor.Text = data.Color
lblSize.Text = data.Size
lblWeight.Text = data.Weight.ToString()
lblListPrice.Text = data.ListPrice.ToString()
hdnProductId.Value = data.ProductID.ToString()
hdnProductName.Value = data.Name
hdnListPrice.Value = data.ListPrice.ToString()
End If
End Sub
product/680
In the Home Page Windows Internet Explorer window, in the address bar, append the
following text.
product/680
Note: A grid should render with a single row containing details of the product with an ID value of
680.
In the right pane, in the Management Group section, double-click Search Engine
Optimization.
3. Add a new allow rule for the default website and Sitemap.xml file.
a. In the Search Engine Optimization pane, in the Robots Exclusion section, click Add a new
allow rule.
b. In the Add Allow Rules dialog box, in the URL Paths list, select the Default Web Site and
Sitemap.xml check boxes, and then click OK.
4. Close Internet Information Services (IIS) Manager.
In the Internet Information Services (IIS) Manager window, click the Close button.
5. Close Administrative Tools.
In the Control Panel\System and Security\Administrative Tools window, click the Close
button.
6. Close System and Security.
In the Control Panel\System and Security window, click the Close button.
a. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or
press CTRL+SHIFT+O.
b. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab
06\Starter\Exercise 03\AdventureWorks.sln or D:\Lab Files\VB\Lab 06\Starter\Exercise
03\AdventureWorks.sln and then click Open.
6. Replace the content of the div element with a class attribute value of clear hideSkiplink, with the
following markup.
[Visual C#]
Menu NavigationMenu = (Menu)this.FindControl("NavigationMenu");
[Visual Basic]
Dim NavigationMenu as Menu = Me.FindControl("NavigationMenu")
[Visual C#]
Menu NavigationMenu = (Menu) this.FindControl("NavigationMenu");
[Visual Basic]
Dim NavigationMenu as Menu = Me.FindControl("NavigationMenu")
Note: IntelliSense will show you details about the Menu control. You can expand the different levels
by clicking the +-sign.
7. Stop debugging.
In the AdventureWorks Microsoft Visual Studio window, on the Debug menu, click Stop
Debugging, or press SHIFT+F5.
8. Close Visual Studio 2010.
In the AdventureWorks Microsoft Visual Studio window, click the Close button.
f Task 4: Turn off the virtual machine and revert the changes
1. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and
then click Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Lab Answer Key: Writing Server-Side Code for Web Forms 1
Module 7
Lab Answer Key: Writing Server-Side Code for Web Forms
Contents:
Exercise 1: Modifying a Web Forms Page to Display Localized Content 2
Exercise 2: Persisting Data on Web Forms Pages 7
Exercise 3: Utilizing View State Effectively 13
2 Lab Answer Key: Writing Server-Side Code for Web Forms
a. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or
press CTRL+SHIFT+O.
b. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab
07\Starter\Exercise 01\AdventureWorks.sln or D:\Lab Files\VB\Lab 07\Starter\Exercise
01\AdventureWorks.sln and then click Open.
Note: This automatically creates the App_LocalResources folder in the root of your web application, if
one does not already exist. The process also creates a resource file called Default.aspx.resx, in the
App_LocalResources folder.
Note: The values of these attributes are used to find the localized values for the properties of the
localizable controls in the Default.aspx.resx file.
5. Notice that the Page directive at the top of the page now contains the following information.
6. Open Default.aspx.resx.
In Solution Explorer, in App_LocalResources, double-click Default.aspx.resx.
Note: In the Resource Editor, you will see a list with all the localizable properties of the localizable
controls from the Default.aspx page.
Attribute Value
ID lclWelcome
meta:resourcekey LocalizeResource1
a. Place the cursor within the h2 element, just before the text Welcome to AdventureWorks!.
b. Open the Toolbox, expand Standard, and then double-click Localize.
c. Modify the Localize server control to appear as follows.
Note: Make sure that you do not delete the text Welcome to AdventureWorks! from the Localize
server control.
11. Add a resource string named lclWelcomeResource1.Text to the Default.aspx.resx resource file. The
string must have the value of Welcome to AdventureWorks!.
a. In the AdventureWorks Microsoft Visual Studio window, click Default.aspx.resx.
b. In the bottom row of the Resource Editor, in the Name box, type lclWelcomeResource1.Text, in
the Value box, type Welcome to AdventureWorks!.
4 Lab Answer Key: Writing Server-Side Code for Web Forms
12. Localize the hard-coded Product Categories text explicitly, by adding a Literal server control within
the p element, with the following attributes.
Attribute Value
ID ProductCategoriesLiteral
Note: Make sure that you do not delete the text Product Categories from the Literal server control.
14. Add a resource string named ProductCategoriesLiteral.Text to the Default.aspx.resx resource file.
The string must have the value of Product Categories.
a. In the AdventureWorks Microsoft Visual Studio window, click Default.aspx.resx.
b. In the bottom row of the Resource Editor, in the Name box, type
ProductCategoriesLiteral.Text, in the Value box, type Product Categories.
15. Run the application.
a. In Solution Explorer, click AdventureWorks.
b. In the AdventureWorks Microsoft Visual Studio window, on the Debug menu, click Start
Without Debugging, or press CTRL+F5.
16. Verify that Default.aspx Web Form looks the same as it did before you modified it.
17. Close Windows Internet Explorer.
In the Home Page Windows Internet Explorer window, click the Close button.
18. Add an existing German resource file for the Default.aspx Web Form to the App_LocalResources
folder. The file is named Default.aspx.de.resx and it is located in the D:\Lab Files\CS\Lab
07\Starter\Exercise 01 or D:\Lab Files\VB\Lab 07\Starter\Exercise 01 folder.
a. In Solution Explorer, right-click App_LocalResources, point to Add, and then click Existing
Item.
b. In the Add Existing Item dialog box, in the File name box, type D:\Lab Files\CS\Lab
07\Starter\Exercise 01\Default.aspx.de.resx or D:\Lab Files\VB\Lab 07\Starter\Exercise
01\Default.aspx.de.resx, and then click Add.
2. Localize the hard-coded Log In text, by adding a Literal server control within the a element, with the
following attributes.
Attribute Value
ID LoginLiteral
Text Log In
a. Place the cursor between the opening and closing a tags within the AnonymousTemplate
element, just before the text Log In.
b. Open the Toolbox, expand Standard, and then double-click Literal.
c. Modify the Literal server control to appear as follows.
Note: Make sure that you do not delete the text Log In from the Literal server control.
4. Localize the hard-coded Welcome text, by adding a Literal server control within the
LoggedInTemplate element, with the following attributes.
Attribute Value
ID WelcomeLiteral
Text Welcome
a. Place the cursor between the opening and closing LoggedInTemplate tags, just before the text
Welcome.
b. Open the Toolbox, expand Standard, and then double-click Literal.
c. Modify the Literal server control to appear as follows.
Note: Make sure that you do not delete the text Welcome from the Literal server control.
Note: This generates a new file called Site.Master.resx in the App_LocalResources folder.
6 Lab Answer Key: Writing Server-Side Code for Web Forms
8. Add an existing German resource file for the Site.Master master page to the App_LocalResources
folder. The file is named Site.Master.de.resx and it is located in the D:\Lab Files\CS\Lab
07\Starter\Exercise 01 or D:\Lab Files\VB\Lab 07\Starter\Exercise 01 folder.
a. In Solution Explorer, right-click App_LocalResources, point to Add, and then click Existing
Item.
b. In the Add Existing Item dialog box, in the File name box, type D:\Lab Files\CS\Lab
07\Starter\Exercise 01\Site.Master.de.resx or D:\Lab Files\VB\Lab 07\Starter\Exercise
01\Site.Master.de.resx, and then click Add.
a. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or
press CTRL+SHIFT+O.
b. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab
07\Starter\Exercise 02\AdventureWorks.sln or D:\Lab Files\VB\Lab 07\Starter\Exercise
02\AdventureWorks.sln and then click Open.
Task 2: Use a cookie collection to persist user information and set scope and lifetime to
save the last chosen category
1. Open the Default.aspx Web Form in Code view.
In Solution Explorer, right-click Default.aspx, and then click View Code.
2. On postback, create a cookie object called Preferences that holds the current product category,
saved as a value named LastCategory. Make sure that the cookie will expire after one minute. The
cookie must be appended to the response.
[Visual C#]
else
{
if (lbCategories.SelectedIndex != -1)
{
string category = lbCategories.SelectedValue;
cookie["LastCategory"] = category;
cookie.Expires = DateTime.Now.AddMinutes(1);
Response.AppendCookie(cookie);
Response.Redirect("/Products.aspx?id=" + category);
}
}
[Visual Basic]
Else
If lbCategories.SelectedIndex <> -1 Then
Dim category = lbCategories.SelectedValue
In the Default/_Default class, add the following code to the Page_Load event handler.
[Visual C#]
HttpCookie cookie = new HttpCookie("Preferences");
cookie["LastCategory"] = category;
cookie.Expires = DateTime.Now.AddMinutes(1);
Response.AppendCookie(cookie);
[Visual Basic]
Dim cookie As New HttpCookie("Preferences")
cookie("LastCategory") = category
cookie.Expires = DateTime.Now.AddMinutes(1)
Response.AppendCookie(cookie)
[Visual C#]
else
{
if (lbCategories.SelectedIndex != -1)
{
string category = lbCategories.SelectedValue;
[Visual Basic]
Else
If lbCategories.SelectedIndex <> -1 Then
Dim category = lbCategories.SelectedValue
3. If the page is rendered for the first time, add code to check that a cookie named Preferences exists in
the request cookie collection, and if there is, read the LastCategory value from the cookie, and assign
it to the SelectedValue property of the ListBox control.
[Visual C#]
if (!Page.IsPostBack)
Lab Answer Key: Writing Server-Side Code for Web Forms 9
{
List<ProductCategory> data = DataAccessLayer.Products.GetCategories();
lbCategories.DataSource = data;
lbCategories.DataBind();
[Visual Basic]
If Not Page.IsPostBack Then
Dim data As List(Of ProductCategory) =
AdventureWorks.DataAccessLayer.Products.GetCategories
lbCategories.DataSource = data
lbCategories.DataBind()
In the Default/_Default class, add the following code to the Page_Load event handler.
[Visual C#]
HttpCookie cookie = Request.Cookies["Preferences"];
if (cookie != null)
{
lbCategories.SelectedValue = cookie["LastCategory"];
}
[Visual Basic]
Dim cookie As HttpCookie = Request.Cookies("Preferences")
[Visual C#]
if (!Page.IsPostBack)
{
List<ProductCategory> data = DataAccessLayer.Products.GetCategories();
lbCategories.DataSource = data;
lbCategories.DataBind();
[Visual Basic]
If Not Page.IsPostBack Then
Dim data As List(Of ProductCategory) =
AdventureWorks.DataAccessLayer.Products.GetCategories
10 Lab Answer Key: Writing Server-Side Code for Web Forms
lbCategories.DataSource = data
lbCategories.DataBind()
[Visual C#]
void Application_Start(object sender, EventArgs e)
{
Application["OnlineVisitors"] = 0;
}
[Visual Basic]
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
Application("OnlineVisitors") = 0
End Sub
3. In the Session_Start method increment the value of the OnlineVisitors application variable by 1.
Make sure you prevent multiple threads from writing to the application variable, by locking the
Application object before writing, and unlocking once you have finished writing to it.
[Visual C#]
void Session_Start(object sender, EventArgs e)
{
Application.Lock();
int visitors = (int)Application["OnlineVisitors"];
visitors++;
Application["OnlineVisitors"] = visitors;
Application.UnLock();
}
Lab Answer Key: Writing Server-Side Code for Web Forms 11
[Visual Basic]
Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)
Application.Lock()
Dim visitors As Integer = Integer.Parse(Application("OnlineVisitors"))
visitors += 1
Application("OnlineVisitors") = visitors
Application.UnLock()
End Sub
4. In the Session_End decrement the value of the OnlineVisitors application variable by 1, if the
current value is not 0. Make sure you prevent multiple threads from writing to the application
variable, by locking the Application object before writing, and unlocking once you have finished
writing to it.
[Visual C#]
void Session_End(object sender, EventArgs e)
{
Application.Lock();
int visitors = (int)Application["OnlineVisitors"];
if (visitors > 0)
{
visitors++;
Application["OnlineVisitors"] = visitors;
}
Application.UnLock();
}
[Visual Basic]
Sub Session_End(ByVal sender As Object, ByVal e As EventArgs)
Application.Lock()
Dim visitors As Integer = Integer.Parse(Application("OnlineVisitors"))
Application.UnLock()
End Sub
<system.web>
...
<sessionState mode="SQLServer" sqlConnectionString="Integrated Security=SSPI;Data
Source=.\SQLExpress;" />
</system.web>
In the Web.config window, add the following markup just before the end system.web tag.
3. Configure the local SQL Server instance SQLExpress to host the state database, by running the
following command from the Visual Studio Command Prompt (2010). The Visual Studio Command
Prompt (2010) must be run as an administrator.
a. In the Start menu, point to All Programs, expand Microsoft Visual Studio 2010, expand Visual
Studio Tools, right-click Visual Studio Command Prompt (2010), and then click Run as
administrator.
b. In the User Account Control dialog box, in the Password box, type Pa$$w0rd, and then click
Yes.
c. In the Visual Studio Command Prompt (2010) window, type the following, and then press
ENTER: aspnet_regsql -E -S .\SQLExpress -ssadd
4. Open the SQL Server Command Line Tool, by running the following command from the Visual
Studio Command Prompt (2010).
sqlcmd E S .\SQLExpress
In the Visual Studio Command Prompt (2010) window, type the following, and then press
ENTER: sqlcmd E S .\SQLExpress
5. Add permissions for the user Student to access the tempdb and ASPState database to use the new
SQL Server Session state, by running commands from the SQL Server Command Line Tool within
the Visual Studio Command Prompt (2010). The commands are saved in the D:\Lab Files\CS\Lab
07\Starter\Exercise 02\ASPState.txt or D:\Lab Files\VB\Lab 07\Starter\Exercise 02\ASPState.txt
file, from where you can copy them and paste them into the SQL Server Command Line Tool.
a. On the Start menu, click Run.
Lab Answer Key: Writing Server-Side Code for Web Forms 13
b. In the Run dialog box, in the Open box, type D:\Lab Files\CS\Lab 07\Starter\Exercise
02\ASPState.txt or D:\Lab Files\VB\Lab 07\Starter\Exercise 02\ASPState.txt, and then press
ENTER.
c. In the ASPState.txt Notepad window, on the Edit menu, click Select All, or press CTRL+A.
d. In the ASPState.txt Notepad window, on the Edit menu, click Copy, or press CTRL+C.
e. In the ASPState.txt Notepad window, click the Close button.
f. In the SQLCMD window, right-click next to line 1, and then click Paste.
6. Close the SQL Server Command Line Tool, by running the following command from the Visual
Studio Command Prompt (2010).
quit
a. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or
press CTRL+SHIFT+O.
b. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab
07\Starter\Exercise 03\AdventureWorks.sln or D:\Lab Files\VB\Lab 07\Starter\Exercise
03\AdventureWorks.sln and then click Open.
In the Home Page Windows Internet Explorer window, right-click the page, and then click
View Source.
3. Analyze the HTML code, and pay special attention to the __VIEWSTATE field.
In the http://localhost:xxxx/ Original Source window, notice the size of the __VIEWSTATE
H H
field.
4. Close the View Source window.
In the http://localhost:xxxx/ Original Source window, click the Close button.
H H
a. In the Default.aspx window, place the cursor in the markup for the lbCategories server control.
b. In the Properties window, in the EnableViewState list, click False.
8. Run the application.
a. In Solution Explorer, click AdventureWorks.
b. In the AdventureWorks Microsoft Visual Studio window, on the Debug menu, click Start
Without Debugging, or press CTRL+F5.
9. View the source of the Default.aspx page in Internet Explorer, by using the View Source
functionality.
In the Home Page Windows Internet Explorer window, right-click the page, and then click
View Source.
10. Analyze the HTML code, and pay special attention to the __VIEWSTATE field, which is now much
smaller, almost half the size.
In the http://localhost:xxxx/ Original Source window, notice the size of the __VIEWSTATE
H H
field.
11. Close the View Source window.
In the http://localhost:xxxx/ Original Source window, click the Close button.
H H
12. Notice the effects of disabling view state for the lbCategories server control, by clicking Submit.
Note: The lbCategories server control is now empty because it is not being populated by the server
code on a postback.
a. In the Default.aspx window, place the cursor in the markup for the Page directive.
b. In the Properties window, in the EnableViewState list, click False.
2. Run the application.
a. In Solution Explorer, click AdventureWorks.
b. In the AdventureWorks Microsoft Visual Studio window, on the Debug menu, click Start
Without Debugging, or press CTRL+F5.
3. Click Submit.
Note: The lbCategories server control is now empty because it is not being populated by the server
code on a postback.
a. In the Default.aspx window, place the cursor in the markup for the lbCategories server control.
b. In the Properties window, in the EnableViewState list, click True.
6. Run the application.
a. In Solution Explorer, click AdventureWorks.
b. In the AdventureWorks Microsoft Visual Studio window, on the Debug menu, click Start
Without Debugging, or press CTRL+F5.
7. Click Submit.
Note: The lbCategories server control is now empty, even if you enabled view state for the control.
This is because disabling view state for a control or page will disable the view state for all child controls.
EnableViewState="False"
10. Remove the EnableViewState attribute and value from the lbCategories server control.
16 Lab Answer Key: Writing Server-Side Code for Web Forms
In the Default.aspx window, delete the following text from the markup for the lbCategories
server control.
EnableViewState="True"
11. Disable view state for the Default Web Form by setting the ViewStateMode property to Disabled.
a. In the Default.aspx window, place the cursor in the markup for the Page directive.
b. In the Properties window, in the ViewStateMode list, click Disabled.
12. Enable view state for the lbCategories server control by setting the ViewStateMode property to
Enabled.
a. In the Default.aspx window, place the cursor in the markup for the lbCategories server control.
b. In the Properties window, in the ViewStateMode list, click Enabled.
13. Run the application.
a. In Solution Explorer, click AdventureWorks.
b. In the AdventureWorks Microsoft Visual Studio window, on the Debug menu, click Start
Without Debugging, or press CTRL+F5.
14. Click Submit.
Note: The lbCategories server control is still populated because view state has been enabled for the
server control.
a. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or
press CTRL+SHIFT+O.
b. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab
07\Starter\Exercise 04\AdventureWorks.sln or D:\Lab Files\VB\Lab 07\Starter\Exercise
04\AdventureWorks.sln and then click Open.
<br />
Credit card number: <asp:TextBox runat="server" ID="txtCreditCard"/>
Task 3: Add and configure a RequiredFieldValidator control for the txtCreditCard control
1. Add a RequiredFieldValidator control named CreditCardRequiredFieldValidator to the
ShoppingCart Web Form, and place it immediately after the txtCreditCard control.
Task 4: Add and configure a RegularExpressionValidator control for the credit card field
1. Add a RegularExpressionValidator control named CreditCardRegularExpressionValidator to the
ShoppingCart Web Form, and place it immediately after the CreditCardRequiredFieldValidator
control. Add a self-closing HTML br element after the RegularExpressionValidator control.
</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator ID="CreditCardRegularExpressionValidator"
runat="server">
</asp:RegularExpressionValidator>
<br />
ValidationExpression= ^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13})$
<asp:RegularExpressionValidator ID="CreditCardRegularExpressionValidator"
runat="server"
ControlToValidate="txtCreditCard" Text="*" ErrorMessage="Please enter a valid
credit card number."
ValidationExpression="^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-
9]{13})$">
</asp:RegularExpressionValidator>
[Visual C#]
protected void btnPlaceOrder_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
Session["_cart"] = null;
Response.Redirect("~/ThankYou.aspx", true);
}
}
[Visual Basic]
Protected Sub btnPlaceOrder_Click(ByVal sender As Object, ByVal e As
System.EventArgs) Handles btnPlaceOrder.Click
If Page.IsValid Then
Session("_cart") = Nothing
Response.Redirect("~/ThankYou.aspx", True)
End If
End Sub
Note: Observe that an asterisk (*) is placed next to txtCreditCard server control because you have not
filled in this field.
10. On the Shopping Cart page, in the Credit card number box, type 1234123412341234, and then
click Place Order.
Lab Answer Key: Writing Server-Side Code for Web Forms 19
Note: Observe that an asterisk (*) is placed next to txtCreditCard server control because you have not
entered a valid credit card number.
11. On the Shopping Cart page, in the Credit card number box, type 4058340022020047, and then
click Place Order.
Note: Observe that you are redirected to the ThankYou Web Form because you have filled in a valid
credit card number.
Close button.
13. Close Visual Studio 2010.
In the AdventureWorks Microsoft Visual Studio window, click the Close button.
Task 5: Turn off the virtual machine and revert the changes
1. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and
then click Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Lab Answer Key: Optimizing Data Management for Web Forms 1
Module 8
Lab Answer Key: Optimizing Data Management for Web
Forms
Contents:
Lab 8A: Optimizing Data Management for Web Forms
Exercise 1: Managing Data by Using LINQ to Entities 2
Exercise 2: Customizing the GridView 3
Exercise 3: Using ListView, DetailsView and Charts 17
Lab 8B: Optimizing Data Management for Web Forms
Exercise 4: Managing Data by Using ASP.NET Dynamic Data 25
2 Lab 8A: Optimizing Data Management for Web Forms
In the AdventureWorks Microsoft Visual Studio window, click the Close button.
<asp:TextBox ID="QuantityTextBox"
runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="QuantityRequiredFieldValidator"
runat="server" ErrorMessage="You must fill in the Quantity."
ControlToValidate="QuantityTextBox"
Display="Dynamic"></asp:RequiredFieldValidator>
4. Add a public property named Text to the user control. The property must be of type String/string,
and get and set the Text property of the QuantityTextBox control.
[Visual Basic]
[Visual C#]
[Visual C#]
Note: Observe the Build succeeded message in the Build pane of the Output window.
Lab Answer Key: Optimizing Data Management for Web Forms 5
[Visual C#]
In the ShoppingCart.vb or ShoppingCart.cs window, add the following code, before the
Quantity property.
[Visual Basic]
[Visual C#]
3. Modify the auto-implemented Quantity property, to get and set the productQuantity member
variable.
[Visual Basic]
[Visual C#]
[Visual C#]
[Visual C#]
In the ShoppingCart.vb or ShoppingCart.cs window, add the following code after the ListPrice
property.
[Visual Basic]
[Visual C#]
[Visual C#]
[Visual C#]
Note: Observe how the Quantity field/column has been converted into a TemplateField, and
the newly added Total Price TemplateField.
[Visual C#]
if (!IsPostBack)
{
}
[Visual C#]
[Visual C#]
9. Add code to the gvCart_RowEditing method, for setting the edit index, and bind the data by
using the BindData method.
[Visual Basic]
[Visual C#]
[Visual C#]
10. Add code to the gvCart_RowCancelingEdit method, for resetting the edit index and bind the
data by using the BindData method.
10 Lab 8A: Optimizing Data Management for Web Forms
[Visual Basic]
[Visual C#]
[Visual C#]
11. Add code to the gvCart_RowUpdating method, for retrieving the existing cart from Session.
[Visual Basic]
[Visual C#]
[Visual C#]
12. Append code to the gvCart_RowUpdating method, for retrieving the current row from the
GridView control.
[Visual Basic]
[Visual C#]
[Visual C#]
13. Append code to the gvCart_RowUpdating method, for finding the matching row in the stored
cart, stored in a new variable named cartToEdit of type ShoppingCart. Use the generic List Find
method with an anonymous Lambda expression.
[Visual Basic]
[Visual C#]
[Visual C#]
14. Append code to the gvCart_RowUpdating method, for updating the quantity value of the
cartToEdit shopping cart with the value of the Text property of the Quantity user control,
located in the current row of the GridView control.
[Visual Basic]
[Visual C#]
// Update values
Quantity qty =
gvCart.Rows[e.RowIndex].FindControl("Quantity1") as Quantity;
cartToEdit.Quantity = int.Parse(qty.Text);
[Visual C#]
// Update values
Quantity qty =
gvCart.Rows[e.RowIndex].FindControl("Quantity1") as
Quantity;
cartToEdit.Quantity = int.Parse(qty.Text);
15. Append code to the gvCart_RowUpdating method, to save the updated cart to Session state.
[Visual Basic]
[Visual C#]
[Visual C#]
16. Append code to the gvCart_RowUpdating method, for resetting the edit index and bind the
data by using the BindData method.
[Visual Basic]
[Visual C#]
[Visual C#]
Note: Observe how the Quantity user control has been registered using the Register directive,
and the user control has been added to the web form.
2. Move the markup for the Quantity user control to the top of the EditItemTemplate element.
<EditItemTemplate>
<uc1:Quantity ID="Quantity1" runat="server" />
<asp:TextBox ID="TextBox1" runat="server" Text='<%#
Bind("Quantity") %>'></asp:TextBox>
</EditItemTemplate>
a. In the ShoppingCart.aspx window, locate and select the markup for the Quantity user control.
a. In the ShoppingCart.aspx window, locate the TextBox1 control, and select the markup for the
Text attribute.
ReadOnly="true"
6. Format the display of the ListPrice BoundField control using the DataFormatString attribute and a
value of {0:c}.
In the ShoppingCart.aspx window, add the following markup to the BoundField element with a
DataField attribute value of ListPrice.
DataFormatString="{0:c}"
Lab Answer Key: Optimizing Data Management for Web Forms 15
7. Modify the format of the TemplateField control with a HeaderText attribute value of Total Price, to
appear as follows.
[Visual C#]
[Visual C#]
Note: Observe that the customized pager has been added to the GridView, now that more items than
the specified page size have been added to the GridView.
<WhereParameters>
<asp:Parameter DefaultValue="DateTime.Now" Name="ShipDate"
Type="DateTime" />
</WhereParameters>
<td>
<asp:Button ID="SelectButton" runat="server" Text="Select" CommandName="Select"
/>
</td>
a. In the SalesOrders.aspx window, insert the following markup at the top of the HTML tr element
within the AlternatingItemTemplate element.
20 Lab 8A: Optimizing Data Management for Web Forms
b. In the SalesOrders.aspx window, insert the following markup at the top of the HTML tr element
within the ItemTemplate element.
<td>
<asp:Button ID="SelectButton" runat="server" Text="Select" CommandName="Select"
/>
</td>
23. Add an empty HTML th element to the LayoutTemplate element. Make the th element a server
control and place it at the top of the HTML tr element.
<th runat="server">
</th>
In the SalesOrders.aspx window, insert the following markup at the top of the HTML tr element
within the itemPlaceholderContainer table element in the LayoutTemplate element.
<th runat="server">
</th>
24. Add an empty HTML td element to the SelectedItemTemplate element. Place it at the top of the
HTML tr element.
<td>
</td>
In the SalesOrders.aspx window, insert the following markup at the top of the HTML tr element
within the SelectedItemTemplate element.
<td>
</td>
<p>
</p>
In the SalesOrders.aspx window, insert the following markup below the existing p element.
<p>
</p>
26. Add a new LinqDataSource control with the following markup, within the empty HTML p element.
<asp:LinqDataSource ID="SalesOrderDetailsLinqDataSource"
runat="server"
ContextTypeName="AdventureWorks.AdventureWorksLT2008Entities"
EntityTypeName="" TableName="SalesOrderDetails"
Where="SalesOrderID == @SalesOrderID">
<WhereParameters>
<asp:ControlParameter ControlID="SalesOrdersListView"
Name="SalesOrderID" PropertyName="SelectedValue"
Type="Int32" DefaultValue="0" />
</WhereParameters>
</asp:LinqDataSource>
In the SalesOrders.aspx window, insert the following markup within the empty p element.
<asp:LinqDataSource ID="SalesOrderDetailsLinqDataSource"
Lab Answer Key: Optimizing Data Management for Web Forms 21
runat="server"
ContextTypeName="AdventureWorks.AdventureWorksLT2008Entitie
s"
EntityTypeName="" TableName="SalesOrderDetails"
Where="SalesOrderID == @SalesOrderID">
<WhereParameters>
<asp:ControlParameter
ControlID="SalesOrdersListView" Name="SalesOrderID" PropertyName="SelectedValue"
Type="Int32" DefaultValue="0" />
</WhereParameters>
</asp:LinqDataSource>
27. Add a DetailsView control with the following markup, at the top of the new HTML p element.
<asp:DetailsView ID="SalesOrderDetailDetailsView"
runat="server" DataSourceID="SalesOrderDetailsLinqDataSource"
Height="50px" Width="125px" AutoGenerateRows="False">
<Fields>
<asp:BoundField DataField="SalesOrderDetailID"
HeaderText="SalesOrderDetailID"
SortExpression="SalesOrderDetailID" />
<asp:BoundField DataField="OrderQty"
HeaderText="OrderQty" SortExpression="OrderQty" />
<asp:BoundField DataField="ProductID"
HeaderText="ProductID" SortExpression="ProductID" />
<asp:BoundField DataField="UnitPrice"
HeaderText="UnitPrice" SortExpression="UnitPrice" />
<asp:BoundField DataField="UnitPriceDiscount" HeaderText="UnitPriceDiscount"
SortExpression="UnitPriceDiscount" />
<asp:BoundField DataField="LineTotal"
HeaderText="LineTotal" SortExpression="LineTotal" />
<asp:BoundField DataField="rowguid"
HeaderText="rowguid" SortExpression="rowguid" />
<asp:BoundField DataField="ModifiedDate"
HeaderText="ModifiedDate" SortExpression="ModifiedDate" />
</Fields>
</asp:DetailsView>
In the SalesOrders.aspx window, insert the following markup at the top of the new p element.
<asp:DetailsView ID="SalesOrderDetailDetailsView"
runat="server" DataSourceID="SalesOrderDetailsLinqDataSource"
Height="50px" Width="125px" AutoGenerateRows="False">
<Fields>
<asp:BoundField DataField="SalesOrderDetailID"
HeaderText="SalesOrderDetailID"
SortExpression="SalesOrderDetailID" />
<asp:BoundField DataField="OrderQty"
HeaderText="OrderQty" SortExpression="OrderQty" />
<asp:BoundField DataField="ProductID"
HeaderText="ProductID" SortExpression="ProductID" />
<asp:BoundField DataField="UnitPrice"
HeaderText="UnitPrice" SortExpression="UnitPrice" />
<asp:BoundField DataField="UnitPriceDiscount"
HeaderText="UnitPriceDiscount"
SortExpression="UnitPriceDiscount" />
<asp:BoundField DataField="LineTotal"
HeaderText="LineTotal" SortExpression="LineTotal" />
<asp:BoundField DataField="rowguid"
HeaderText="rowguid" SortExpression="rowguid" />
<asp:BoundField DataField="ModifiedDate"
HeaderText="ModifiedDate" SortExpression="ModifiedDate" />
</Fields>
22 Lab 8A: Optimizing Data Management for Web Forms
</asp:DetailsView>
Note: Notice how the DetailsView containing the Sales Order Details is displayed below the ListView
control.
<asp:EntityDataSource ID="SalesOrderItemsEntityDataSource"
runat="server"
ContextTypeName="AdventureWorks.AdventureWorksLT2008Entities"
CommandText="SELECT Headers.SalesOrderNumber,
Headers.OrderDate, SUM(Details.OrderQty) AS SalesOrderItems
FROM SalesOrderHeaders AS Headers INNER JOIN
SalesOrderDetails AS Details ON Headers.SalesOrderID =
Details.SalesOrderID
GROUP BY Headers.SalesOrderID, Headers.SalesOrderNumber,
Headers.OrderDate"
ConnectionString="name=AdventureWorksLT2008Entities"
DefaultContainerName="AdventureWorksLT2008Entities"
EnableFlattening="False">
</asp:EntityDataSource>
In the SalesOrderItemsHistory.aspx window, place the cursor between the opening and closing
MainContent tags, and type the following markup.
<asp:EntityDataSource ID="SalesOrderItemsEntityDataSource"
runat="server"
ContextTypeName="AdventureWorks.AdventureWorksLT2008Entities"
CommandText="SELECT Headers.SalesOrderNumber,
Headers.OrderDate, SUM(Details.OrderQty) AS SalesOrderItems
FROM SalesOrderHeaders AS Headers INNER JOIN
SalesOrderDetails AS Details ON
Headers.SalesOrderID = Details.SalesOrderID
GROUP BY Headers.SalesOrderID,
Headers.SalesOrderNumber, Headers.OrderDate"
ConnectionString="name=AdventureWorksLT2008Entities"
DefaultContainerName="AdventureWorksLT2008Entities"
EnableFlattening="False">
</asp:EntityDataSource>
Note: Notice how the Chart shows how the number of items per order is shown by order date.
Task 6: Turn off the virtual machine and revert the changes
1. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
24 Lab 8A: Optimizing Data Management for Web Forms
DefaultModel.RegisterContext(GetType(AWDynamicData.AdventureWorksLT2008R2Entities),
New ContextConfiguration() With {.ScaffoldAllTables = True})
[Visual C#]
DefaultModel.RegisterContext(typeof(AWDynamicData.AdventureWorksLT2008R2Entities),
new ContextConfiguration()
{
ScaffoldAllTables = true
});
In the Global.asax.vb or Global.asax.cs window, add the following code at the top of to the
RegisterRoutes procedure.
[Visual Basic]
DefaultModel.RegisterContext(GetType(AWDynamicData.AdventureWorksLT2008R2Entities
),
New ContextConfiguration() With {.ScaffoldAllTables = True})
[Visual C#]
DefaultModel.RegisterContext(typeof(AWDynamicData.AdventureWorksLT2008R2Entities)
,
new ContextConfiguration()
{
ScaffoldAllTables = true
});
Note: The page displayed in the browser displays a list of the tables you added to the data model.
Note: The page displays the List view that contains the data from the Customers table.
Note: The page displays the Details view that contains the data for the selected row from the
Customers table.
4. View the Customers page, showing all customers, by clicking Show all items.
In the Customers - Windows Internet Explorer window, click Show all items.
5. Sort the customers by the LastName column.
In the Customers - Windows Internet Explorer window, click LastName.
Note: The page displays the List view that contains the data of customers, sorted by last name.
6. View the sales order headers associated with the second customer displayed from the top.
In the Customers - Windows Internet Explorer window, in the second row, under
SalesOrderHeaders, click View SalesOrderHeaders.
Note: The page displays the List view that contains the data of customer sales order headers.
7. Filter the sales order headers by entries that have the OnlineOrderFlag column set to True.
In the OnlineOrderFlag list, click True.
Note: The page now displays no sales order headers, because none of the sales order headers have the
OnlineOrderFlag set to true.
Note: The page displays the List view that contains the data from the Customers table. This is the
default view and the one you are returned to, after cancelling.
In the Customers - Windows Internet Explorer window, at the end of the page, click Edit to
modify a customer.
Note: The page displays the Edit view that contains the data for the selected row from the Customers
table.
Task 5: Turn off the virtual machine and revert the changes
1. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Lab Answer Key: Ensuring Quality by Debugging, Unit Testing, and Refactoring 1
Module 9
Lab Answer Key: Ensuring Quality by Debugging, Unit
Testing, and Refactoring
Contents:
Exercise 1: Configuring Error Handling 2
Exercise 2: Debugging Code 3
Exercise 3: Logging 7
Exercise 4: Creating Unit Tests 10
Exercise 5: Implementing the Test-First/Test-Driven Development
Methodology 14
2 Lab Answer Key: Ensuring Quality by Debugging, Unit Testing, and Refactoring
Task 3: Modify web.config to redirect to the generic error page when an unhandled
error occurs
1. Open the Web.config file.
In Solution Explorer, double-click Web.config.
2. Add the following markup to the system.web element.
In the Web.config window, add the following markup after the closing compilation tag.
</compilation>
<customErrors mode="On" defaultRedirect="~/CustomErrorPage.aspx"/>
Lab Answer Key: Ensuring Quality by Debugging, Unit Testing, and Refactoring 3
Note: In Visual Studio, in the FormatException was unhandled by user code pane, the error text
Input string was not in a correct format is displayed.
4 Lab Answer Key: Ensuring Quality by Debugging, Unit Testing, and Refactoring
2. Press F5 to continue.
Note: The custom error page is displayed. Do not close Internet Explorer.
[Visual C#]
string category = lbCategories.SelectedValue;
[Visual Basic]
Dim category As String = lbCategories.SelectedValue
[Visual C#]
string category = lbCategories.SelectedValue;
[Visual Basic]
Dim category As String = lbCategories.SelectedValue
6. Press F10 to step over the line of code that sets the local variable category to the selected value of
the list.
7. Hover the mouse over category and notice it is an empty string, which cannot be parsed by the code
in the Products page.
8. Press SHIFT+F5 to end debugging.
Lab Answer Key: Ensuring Quality by Debugging, Unit Testing, and Refactoring 5
9. In Visual Studio, modify the line of code that sets the local variable category to the selected value of
the list, as follows.
[Visual C#]
string category = lbCategories.SelectedValue == string.Empty ? "5" :
lbCategories.SelectedValue;
[Visual Basic]
Dim category As String = IIf(lbCategories.SelectedValue = String.Empty, "5",
lbCategories.SelectedValue)
Note: If the breakpoint disappears after modifying the line of code, place the cursor on the line of
code, and then press F9.
12. Press F10 to step over the line of code that sets the local variable category to the selected value of
the list.
13. Hover the mouse over category and notice it is a string with the value of 5.
14. Press F5 to continue.
Task 4: Debug a java script error using breakpoints and single stepping
Run the application in Debug mode.
In Solution Explorer, click AdventureWorks, and then press F5.
In the Home Page Windows Internet Explorer window, click Select First.
6. Press F10 to step over the statements of code, until a message box is displayed.
7. In the Message from webpage message box, click OK.
8. Repeat steps 6 and 7 twice.
9. Press F5.
Exercise 3: Logging
Task 1: Open an existing ASP.NET web application
1. Open Microsoft Visual Studio 2010.
On the Start menu of 10264A-GEN-DEV, point to All Programs, click Microsoft Visual Studio
2010, and then click Microsoft Visual Studio 2010.
2. Open the AdventureWorks solution from the D:\Lab Files\CS\Lab 09\Starter\Exercise 03 or D:\Lab
Files\VB\Lab 09\Starter\Exercise 03 folder.
a. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project.
b. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab
09\Starter\Exercise 03\AdventureWorks.sln or D:\Lab Files\VB\Lab 09\Starter\Exercise
03\AdventureWorks.sln, and then click Open.
[Visual C#]
using System.Diagnostics;
[Visual Basic]
Imports System.Diagnostics
[Visual C#]
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
string categoryName = string.Empty;
string categoryId = string.Empty;
if (Request["id"] != null)
{
categoryId = Request["id"];
}
try
{
categoryName =
DataAccessLayer.Products.GetCategoryName(int.Parse(categoryId));
}
catch (Exception ex)
{
EventLog Log = new EventLog();
Log.Source = "Application";
Log.WriteEntry(ex.Message, EventLogEntryType.Error);
}
lblCategory.Text = categoryName;
var data =
DataAccessLayer.Products.GetProductsByCategory(int.Parse(categoryId));
8 Lab Answer Key: Ensuring Quality by Debugging, Unit Testing, and Refactoring
gvProducts.DataSource = data;
gvProducts.DataBind();
}
}
[Visual Basic]
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles
Me.Load
If Not Page.IsPostBack Then
Dim categoryName As String = String.Empty
Dim categoryID As String = String.Empty
Try
categoryName =
AdventureWorks.DataAccessLayer.Products.GetCategoryName(Integer.Parse(categoryID))
Catch ex As Exception
Dim Log As New EventLog()
Log.Source = "Application"
Log.WriteEntry(ex.Message, EventLogEntryType.[Error])
End Try
lblCategory.Text = categoryName
Dim data =
AdventureWorks.DataAccessLayer.Products.GetProductsByCategory(Integer.Parse(categoryI
D))
gvProducts.DataSource = data
gvProducts.DataBind()
End If
End Sub
5. Open the Event Viewer and show the Application log entry. If necessary, sort the Application log
entries by date and time.
Lab Answer Key: Ensuring Quality by Debugging, Unit Testing, and Refactoring 9
a. On the Start menu, point to Administrative Tools, and then click Event Viewer.
b. In the Event Viewer, in the left pane, expand Windows Logs, and then click Application.
c. If needed, click Date and Time to sort by date and time.
d. View the logged Application error, by double-clicking it in the middle pane.
6. Close the Event Viewer.
In the Event Viewer window, click Close button.
7. Close Windows Internet Explorer.
In the http://localhost:xxxx/CustomErrorPage.aspx?aspxerrorpath=/Products.aspx Windows
Internet Explorer window, click the Close button.
Task 3: Set the logging level in the Web.config file to allow for future debugging
1. Open the Web.config file.
In Solution Explorer, double-click Web.config.
2. In the opening compilation tag, ensure that the value of the debug attribute is set to true.
[Visual C#]
10 Lab Answer Key: Ensuring Quality by Debugging, Unit Testing, and Refactoring
using System.Diagnostics;
[Visual Basic]
Imports System.Diagnostics
[Visual C#]
void Application_Error(object sender, EventArgs e)
{
string message =
"Url: " + Request.Path + " Error: " +
Server.GetLastError().ToString();
EventLog log = new EventLog();
log.Source = "Application";
log.WriteEntry(message, EventLogEntryType.Error);
}
[Visual Basic]
Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
Dim message As String =
"Url: " & Request.Path & " Error: " &
Server.GetLastError().ToString()
Dim log As New EventLog()
log.Source = "Application"
log.WriteEntry(message, EventLogEntryType.Error)
End Sub
[Visual C#]
public int Add(int p1, int p2)
{
return p1 + p2;
}
[Visual Basic]
Public Function Add(ByVal p1 As Integer, ByVal p2 As Integer) As Integer
Return p1 + p2
End Function
[Visual C#]
int p1 = 2;
[Visual Basic]
Dim p1 As Integer = 2
[Visual C#]
int p2 = 3;
[Visual Basic]
Dim p2 As Integer = 3
12 Lab Answer Key: Ensuring Quality by Debugging, Unit Testing, and Refactoring
3. In the AddTest method, modify the value assigned to local variable expected to 5.
[Visual C#]
int expected = 5;
[Visual Basic]
Dim expected As Integer = 5
[Visual C#]
Assert.Inconclusive("Verify the correctness of this test method.");
[Visual Basic]
Assert.Inconclusive("Verify the correctness of this test method.")
[Visual C#]
[TestMethod()]
public void AddTest()
{
Calculator target = new Calculator(); // TODO: Initialize to an appropriate value
int p1 = 2; // TODO: Initialize to an appropriate value
int p2 = 3; // TODO: Initialize to an appropriate value
int expected = 5; // TODO: Initialize to an appropriate value
int actual;
actual = target.Add(p1, p2);
Assert.AreEqual(expected, actual);
}
[Visual Basic]
<TestMethod()> _
Public Sub AddTest()
Dim target As Calculator = New Calculator() ' TODO: Initialize to an appropriate
value
Dim p1 As Integer = 2 ' TODO: Initialize to an appropriate value
Dim p2 As Integer = 3 ' TODO: Initialize to an appropriate value
Dim expected As Integer = 5 ' TODO: Initialize to an appropriate value
Dim actual As Integer
actual = target.Add(p1, p2)
Assert.AreEqual(expected, actual)
End Sub
Note: In the Test Result window, you can see that the AddTest test passed.
Lab Answer Key: Ensuring Quality by Debugging, Unit Testing, and Refactoring 13
[Visual C#]
int expected = 6;
[Visual Basic]
Dim expected As Integer = 6
[Visual C#]
[TestMethod()]
public void AddTest()
{
Calculator target = new Calculator(); // TODO: Initialize to an appropriate value
int p1 = 2; // TODO: Initialize to an appropriate value
int p2 = 3; // TODO: Initialize to an appropriate value
int expected = 6; // TODO: Initialize to an appropriate value
int actual;
actual = target.Add(p1, p2);
Assert.AreEqual(expected, actual);
}
[Visual Basic]
<TestMethod()> _
Public Sub AddTest()
Dim target As Calculator = New Calculator() ' TODO: Initialize to an appropriate
value
Dim p1 As Integer = 2 ' TODO: Initialize to an appropriate value
Dim p2 As Integer = 3 ' TODO: Initialize to an appropriate value
Dim expected As Integer = 6 ' TODO: Initialize to an appropriate value
Dim actual As Integer
actual = target.Add(p1, p2)
Assert.AreEqual(expected, actual)
End Sub
Note: In the Test Result window, you can see that the AddTest test failed.
[Visual C#]
[TestMethod()]
public void ClassMultiplyMethodTest()
{
Calculator target = new Calculator();
Assert.IsNotNull(target);
int expected = 6;
int unexpected = 5;
int actual = target.Multiply(3, 2);
Assert.AreEqual(expected, actual);
Assert.AreNotEqual(unexpected, actual);
}
[TestMethod()]
public void ClassSubtractMethodTest()
{
Calculator target = new Calculator();
Assert.IsNotNull(target);
int expected = 1;
int unexpected = 6;
int actual = target.Subtract(3, 2);
Assert.AreEqual(expected, actual);
Assert.AreNotEqual(unexpected, actual);
}
[Visual Basic]
<TestMethod()>
Public Sub ClassMultiplyMethodTest()
Dim target As New Calculator()
Lab Answer Key: Ensuring Quality by Debugging, Unit Testing, and Refactoring 15
Assert.IsNotNull(target)
Assert.AreEqual(expected, actual)
Assert.AreNotEqual(unexpected, actual)
End Sub
<TestMethod()>
Public Sub ClassSubtractMethodTest()
Dim target As New Calculator()
Assert.IsNotNull(target)
Assert.AreEqual(expected, actual)
Assert.AreNotEqual(unexpected, actual)
End Sub
[Visual C#]
public int Multiply(int p1, int p2)
{
throw new NotImplementedException();
}
[Visual Basic]
Public Function Multiply(ByVal p1 As Integer, ByVal p2 As Integer) As Integer
Throw New NotImplementedException()
End Function
In the MyClassLibrary Microsoft Visual Studio window, on the Build menu, click Build
Solution or press CTRL+SHIFT+B.
Note: In the Test Result window, you can see that the ClassMultiplyMethodTest test failed.
Note: In the Test Result window, you can see that the ClassSubtractMethodTest test failed.
[Visual C#]
public int Multiply(int p1, int p2)
{
return p1 * p2;
}
[Visual Basic]
Public Function Multiply (ByVal p1 As Integer, ByVal p2 As Integer) As Integer
Return p1 * p2
End Function
2. Replace the Subtract method in the Calculator class with following code.
[Visual C#]
public int Subtract(int p1, int p2)
{
return p1 - p2;
}
[Visual Basic]
Public Function Subtract(ByVal p1 As Integer, ByVal p2 As Integer) As Integer
Return p1 - p2
Lab Answer Key: Ensuring Quality by Debugging, Unit Testing, and Refactoring 17
End Function
Note: In the Test Result window, you can see that the ClassMultiplyMethodTest test passed.
Note: In the Test Result window, you can see that the ClassSubtractMethodTest test passed.
Task 7: Turn off the virtual machine and revert the changes
1. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Lab Answer Key: Securing a Web Application 1
Module 10
Lab Answer Key: Securing a Web Application
Contents:
Exercise 1: Configuring ASP.NET Membership and Roles 2
Exercise 2: Authentication 3
Exercise 3: Authorization 8
2 Lab Answer Key: Securing a Web Application
Security
User Name Password E-mail Question Security Answer
In the User Name box, type Mary, in the Password box, type Pa$$w0rd, in the Confirm
Password box, type Pa$$w0rd, in the E-mail box, type mary@adventureworks.com, in the
Security Question box, type Favorite pet, in the Security Answer box, type Cat.
3. Click Create User.
4. Click Continue.
5. Fill out the information to create a new user, using the following information.
Lab Answer Key: Securing a Web Application 3
User Security
Name Password E-mail Question Security Answer
In the User Name box, type John, in the Password box, type Pa$$w0rd, in the Confirm
Password box, type Pa$$w0rd, in the E-mail box, type john@adventureworks.com, in the
Security Question box, type High School, in the Security Answer box, type Central.
6. Click Create User.
7. Click Continue.
Exercise 2: Authentication
f Task 1: Open an existing ASP.NET web application
1. Open Microsoft Visual Studio 2010.
4 Lab Answer Key: Securing a Web Application
On the Start menu of 10264A-GEN-DEV, point to All Programs, click Microsoft Visual Studio
2010, and then click Microsoft Visual Studio 2010.
2. Open the AdventureWorks solution from the D:\Lab Files\CS\Lab 10\Starter\Exercise 02 or D:\Lab
Files\VB\Lab 10\Starter\Exercise 02 folder.
a. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project.
b. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab
10\Starter\Exercise 02\AdventureWorks.sln or D:\Lab Files\VB\Lab 10\Starter\Exercise
02\AdventureWorks.sln, and then click Open.
Note: When changing the authentication type in the ASP.NET Web Site Administration Tool to From
the internet, the Web.config file is updated automatically.
3. Add a redirect to the existing Login.aspx Web Form in the Account folder, by modifying the self-
closing authentication tag.
<authentication mode="Forms">
<forms loginUrl="~/Account/Login.aspx" timeout="2880" />
</authentication>
ValidationGroup="LoginUserValidationGroup">*</asp:RequiredFieldValidator>
</p>
<p>
<asp:Label ID="PasswordLabel" runat="server"
AssociatedControlID="Password">Password:</asp:Label>
<asp:TextBox ID="Password" runat="server"
CssClass="passwordEntry" TextMode="Password"></asp:TextBox>
<asp:RequiredFieldValidator ID="PasswordRequired" runat="server"
ControlToValidate="Password"
CssClass="failureNotification" ErrorMessage="Password is
required." ToolTip="Password is required."
ValidationGroup="LoginUserValidationGroup">*</asp:RequiredFieldValidator>
</p>
<p>
<asp:CheckBox ID="RememberMe" runat="server"/>
<asp:Label ID="RememberMeLabel" runat="server"
AssociatedControlID="RememberMe" CssClass="inline">Keep me logged in</asp:Label>
</p>
</fieldset>
<p class="submitButton">
<asp:Button ID="LoginButton" runat="server" CommandName="Login"
Text="Log In" ValidationGroup="LoginUserValidationGroup"/>
</p>
</div>
</LayoutTemplate>
</asp:Login>
4. Add a redirect to the EmailPassword.aspx Web Form in the Account folder, by adding the following
markup above the PasswordLabel control.
<p>
<asp:HyperLink ID="EmailPasswordHyperLink" runat="server"
NavigateUrl="~/Account/EmailPassword.aspx">Forgot Password?</asp:HyperLink>
<asp:Label ID="PasswordLabel" runat="server"
AssociatedControlID="Password">Password:</asp:Label>
Note: The EmailPassword.aspx Web Form has not yet been created.
[Visual C#]
6 Lab Answer Key: Securing a Web Application
using System.Web.Security;
[Visual Basic]
Imports System.Web.Security
At the top of the Login.aspx code-behind file, type the following code.
[Visual C#]
using System.Web.Security;
[Visual Basic]
Imports System.Web.Security
3. Add the following code to the Login class to handle the Authenticate event for the LoginUser
server control.
[Visual C#]
protected void LoginUser_Authenticate(object sender, AuthenticateEventArgs e)
{
// Get the membership details for the user
MembershipUser user = Membership.GetUser(LoginUser.UserName.Trim());
[Visual Basic]
Protected Sub LoginUser_Authenticate(ByVal sender As Object, ByVal e As
AuthenticateEventArgs) Handles LoginUser.Authenticate
' Get the membership details for the user
Dim user As MembershipUser = Membership.GetUser(LoginUser.UserName.Trim())
End If
End If
End Sub
<system.net>
<mailSettings>
<smtp from="someone@adventureworks.com">
<network host="yourhost" userName="hostusername" password="hostpassword" />
</smtp>
</mailSettings>
</system.net>
<system.net>
<mailSettings>
<smtp from="someone@adventureworks.com">
<network host="yourhost" userName="hostusername"
password="hostpassword" />
</smtp>
</mailSettings>
</system.net>
Exercise 3: Authorization
f Task 1: Open an existing ASP.NET web application
1. Open Microsoft Visual Studio 2010.
On the Start menu of 10264A-GEN-DEV, point to All Programs, click Microsoft Visual Studio
2010, and then click Microsoft Visual Studio 2010.
2. Open the AdventureWorks solution from the D:\Lab Files\CS\Lab 10\Starter\Exercise 03 or D:\Lab
Files\VB\Lab 10\Starter\Exercise 03 folder.
a. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project.
b. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab
10\Starter\Exercise 03\AdventureWorks.sln or D:\Lab Files\VB\Lab 10\Starter\Exercise
03\AdventureWorks.sln, and then click Open.
<location path="EmailPassword.aspx">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
In the Home.aspx window, in the Content2 Content control, type the following markup.
6. Add the following markup to the Web.config file, above the opening connectionStrings tag.
<location path="Contributors">
<system.web>
<authorization>
<allow roles="Contributor"/>
<deny users="*"/>
</authorization>
</system.web>
</location>
Note: You have access to the EmailPassword Web Form as an anonymous user.
[Visual C#]
http://localhost:4378/Contributors/Home.aspx
[Visual Basic]
http://localhost:15237/Contributors/Home.aspx
Note: You are denied access because the user John is not authorized to access the Contributors
folder.
Note: You are now redirected to the Contributors/Home.aspx Web Form, because the user Mary is
authorized to access the Contributors folder.
f Task 5: Turn off the virtual machine and revert the changes
1. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Lab Answer Key: Applying Master Pages and CSS 1
Module 11
Lab Answer Key: Applying Master Pages and CSS
Contents:
Exercise 1: Modify a Master Page 2
Exercise 2: Create a Nested Master Page 4
Exercise 3: Integrate a Master Page 7
Exercise 4: Implement Control Skins 11
Exercise 5: Apply Styles and Themes 12
2 Lab Answer Key: Applying Master Pages and CSS
<div class="footer">
<asp:ContentPlaceHolder ID="FooterContent" runat="server" />
</div>
In the Site.Master window, add the following markup to the div element with an ID attribute
value of FooterContent.
</asp:Content>
In the About.aspx window, append the following markup to the existing markup.
Lab Answer Key: Applying Master Pages and CSS 3
</asp:Content>
In the About.aspx window, add the following markup to the Content control with an ID
attribute value of PageFooterContent.
Copyright AdventureWorks
Note: The rendered page should appear as follows. Notice the text you added at the bottom of the
image.
[Visual C#]
<%@ Master Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true"
CodeBehind="Nested.master.cs" Inherits="AdventureWorks.Nested" %>
<asp:Content ID="Header" ContentPlaceHolderID="HeadContent" runat="server">
</asp:Content>
<asp:Content ID="Main" ContentPlaceHolderID="MainContent" runat="server">
</asp:Content>
<asp:Content ID="Footer" ContentPlaceHolderID="FooterContent" runat="server">
</asp:Content>
[Visual Basic]
<%@ Master Language="VB" MasterPageFile="~/Site.Master" AutoEventWireup="false"
CodeBehind="Nested.master.vb" Inherits="AdventureWorks.Nested" %>
<asp:Content ID="Header" ContentPlaceHolderID="HeadContent" runat="server">
</asp:Content>
<asp:Content ID="Main" ContentPlaceHolderID="MainContent" runat="server">
</asp:Content>
<asp:Content ID="Footer" ContentPlaceHolderID="FooterContent" runat="server">
</asp:Content>
a. In the Nested.master window, locate the Content control with an ID attribute value of
Content1, and change it to Header.
b. Locate the Content control with an ID attribute value of Content2, and change it to Main.
c. Locate the Content control with an ID attribute value of Content3, and change it to Footer.
Lab Answer Key: Applying Master Pages and CSS 5
In the Nested.master window, in the Content control with an ID attribute value of Main, type
the following markup.
<div class="left">
<asp:ContentPlaceHolder ID="LeftContent" runat="server" />
</div>
<div class="right">
<asp:ContentPlaceHolder ID="RightContent" runat="server" />
</div>
In the Nested.master window, in the Content control with an ID attribute value of Footer, type
the following markup.
Copyright AdventureWorks
f Task 5: Change the Default.aspx page Web Form to use the Nested.master page
1. Modify the Page directive in the Default.aspx file, by adding following markup to change the master
page.
[Visual C#]
<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Nested.master"
AutoEventWireup="true"
CodeBehind="Default.aspx.cs" Inherits="AdventureWorks._Default" %>
[Visual Basic]
<%@ Page Title="Home Page" Language="vb" MasterPageFile="~/Nested.master"
AutoEventWireup="false"
CodeBehind="Default.aspx.vb" Inherits="AdventureWorks._Default" %>
2. Change the ContentPlaceHolder controls to which the Content controls refer to RightContent and
LeftContent. Rename the Content controls to RightBodyContent and LeftBodyContent.
a. In the Default.aspx window, locate the Content control with an ID attribute value of
HeaderContent, and change it to RightBodyContent. Change the ContentPlaceHolderID
attribute value from HeadContent to RightContent.
b. Locate the Content control with an ID attribute value of BodyContent, and change it to
LeftBodyContent. Change the ContentPlaceHolderID attribute value from MainContent to
LeftContent.
3. Add the following markup to the Content control with an ID attribute value of RightBodyContent.
<p>
Right Content
</p>
4. Move the Content control with an ID attribute value of RightBodyContent to after the Content
control with an ID attribute value of LeftBodyContent.
a. In the Default.aspx window, locate and select the Content control with an ID attribute value of
RightBodyContent, and then press CTRL+X.
b. Place the cursor after the closing Content tag for the Content control with an ID attribute value
of LeftBodyContent, and then press CTRL+V.
Lab Answer Key: Applying Master Pages and CSS 7
Note: The rendered page should appear as follows. Notice the content displayed in two columns.
<div class="main">
<asp:ContentPlaceHolder ID="MainContent" runat="server"/>
<asp:Label ID="StatusMessageLabel" runat="server" />
</div>
In the Site.Master window, in the div element with a class attribute value of main, after the
ContentPlaceHolder control, type the following markup.
[Visual C#]
public string StatusMessage
{
get { return StatusMessageLabel.Text; }
set { StatusMessageLabel.Text = value; }
}
[Visual Basic]
Public Property StatusMessage() As String
Get
Return StatusMessageLabel.Text
End Get
Set(ByVal value As String)
StatusMessageLabel.Text = value
End Set
End Property
[Visual C#]
<%@ MasterType TypeName="AdventureWorks.SiteMaster" %>
[Visual Basic]
<%@ MasterType TypeName="AdventureWorks.Site" %>
[Visual C#]
<%@ MasterType TypeName="AdventureWorks.SiteMaster" %>
Lab Answer Key: Applying Master Pages and CSS 9
[Visual Basic]
<%@ MasterType TypeName="AdventureWorks.Site" %>
[Visual C#]
<%@ MasterType TypeName="AdventureWorks.SiteMaster" %>
[Visual Basic]
<%@ MasterType TypeName="AdventureWorks.Site" %>
2. In the Page_Load event handler for the About.aspx page, set the StatusMessage property.
[Visual C#]
protected void Page_Load(object sender, EventArgs e)
{
Master.StatusMessage = "You are on the About page";
}
[Visual Basic]
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
Master.StatusMessage = "You are on the About page"
End Sub
[Visual C#]
Master.StatusMessage = "You are on the About page";
[Visual Basic]
Master.StatusMessage = "You are on the About page"
3. In the Page_Load event handler for the Products.aspx page, set the StatusMessage property.
[Visual C#]
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
string categoryName;
string categoryId = "5";
if (Request["id"] != null)
{
categoryId = Request["id"];
}
categoryName =
DataAccessLayer.Products.GetCategoryName(int.Parse(categoryId));
10 Lab Answer Key: Applying Master Pages and CSS
lblCategory.Text = categoryName;
var data =
DataAccessLayer.Products.GetProductsByCategory(int.Parse(categoryId));
gvProducts.DataSource = data;
gvProducts.DataBind();
}
[Visual Basic]
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles
Me.Load
If Not Page.IsPostBack Then
Dim categoryName As String = Nothing
Dim categoryID As String = "5"
categoryName =
AdventureWorks.DataAccessLayer.Products.GetCategoryName(Integer.Parse(categoryID))
lblCategory.Text = categoryName
Dim data =
AdventureWorks.DataAccessLayer.Products.GetProductsByCategory(Integer.Parse(categoryI
D))
gvProducts.DataSource = data
gvProducts.DataBind()
End If
[Visual C#]
Master.StatusMessage = "You are on the Products page";
[Visual Basic]
Master.StatusMessage = "You are on the Products page"
In the Default.aspx window, in the Page directive, append the following markup.
Theme="Default"
In the Default.aspx window, in the opening ListBox tag, append the following markup.
SkinID="BlueListBox"
Note: Observe the light blue background color in the ListBox control.
In the AdventureWorks Microsoft Visual Studio window, on the left side, point to CSS
Outline or Document Outline, expand Classes, right-click .header, and then click Build Style.
3. In the Modify Style dialog box, select the Background category.
In the Modify Style dialog box, on the Category list, click Background.
4. Change the background color to Red, and close the Modify Style dialog box.
In the Modify Style dialog box, on the background color list, click Red, and then click OK.
5. Save and close the StyleB.css file.
In the StyleB.css window, press CTRL+S, and then click the Close button.
14 Lab Answer Key: Applying Master Pages and CSS
SkinID="BlueListBox"
In the Default.aspx window, in the markup for the lbCategories ListBox control, delete the
following markup.
SkinID="BlueListBox"
6. Remove the theme attribute and value from the Page directive.
Theme="Default"
In the Default.aspx window, in the markup for the Page directive, delete the following markup.
Theme="Default"
<pages theme="Red"/>
</system.web>
In the Web.config window, add the following markup to the system.web element, just before
the closing system.web tag.
<pages theme="Red"/>
Lab Answer Key: Applying Master Pages and CSS 15
f Task 7: Turn off the virtual machine and revert the changes
1. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Lab Answer Key: Developing Client-side Scripts and Services 1
Module 12
Lab Answer Key: Developing Client-side Scripts and Services
Contents:
Exercise 1: Using jQuery 2
Exercise 2: Using Advanced jQuery 6
Exercise 3: Creating a WCF Service 8
2 Lab Answer Key: Developing Client-side Scripts and Services
<head runat="server">
<title></title>
<link href="~/Styles/Site.css" rel="stylesheet" type="text/css" />
<script src='<%= ResolveUrl("~/Scripts/jquery-1.4.1.js") %>'
type="text/javascript"></script>
<script src='<%= ResolveUrl("~/Scripts/jquery.tablesorter.min.js") %>'
type="text/javascript"></script>
<asp:ContentPlaceHolder ID="HeadContent" runat="server">
</asp:ContentPlaceHolder>
</head>
In the Site.Master window, in the head element, after the link element, type the following
markup.
Note: Make sure that you add the closing script tag (</script>) and not the self-closing script tag
(</>). The self-closing tag for the script references is not recognized by the browsers.
Best Practices: For Web Forms applications, you can use the ResolveUrl method, which correctly
resolves the URL relative to the request.
Lab Answer Key: Developing Client-side Scripts and Services 3
Scroll down to find the rendered i for the gvCart server control. Look for the first text containing
the server control name gvCart. Notice the rendered id, MainContent_gvCart, and how by
default the GridView control does not render the thead and tbody HTML elements.
7. Close the source window.
In the http://localhost:xxxxx/ShoppingCart.aspx Original Source window, click the Close
button.
8. Close Windows Internet Explorer.
In the Home Page Windows Internet Explorer window, click the Close button.
9. In the Site.Master master page, insert the following JavaScript element, after the closing html tag.
<script type="text/javascript">
$(document).ready(function () {
$("#MainContent_gvCart").tablesorter();
});
</script>
[Visual C#]
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
4 Lab Answer Key: Developing Client-side Scripts and Services
{
if (Session["_cart"] != null)
{
List<clsShoppingCart> cart = (List<clsShoppingCart>) Session["_cart"];
gvCart.DataSource = cart;
gvCart.DataBind();
}
else
{
lblMessage.Text = "Your cart is empty";
btnPlaceOrder.Visible = false;
}
}
if (this.gvCart.Rows.Count > 0)
{
gvCart.UseAccessibleHeader = true;
gvCart.HeaderRow.TableSection = TableRowSection.TableHeader;
gvCart.FooterRow.TableSection = TableRowSection.TableFooter;
}
}
[Visual Basic]
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles
Me.Load
If Not Session("_cart") Is Nothing Then
Dim cart = CType(Session("_cart"), List(Of clsShoppingCart))
gvCart.DataSource = cart
gvCart.DataBind()
Else
lblMessage.Text = "Your cart is empty"
btnPlaceOrder.Visible = False
End If
[Visual C#]
if (this.gvCart.Rows.Count > 0)
{
gvCart.UseAccessibleHeader = true;
gvCart.HeaderRow.TableSection = TableRowSection.TableHeader;
gvCart.FooterRow.TableSection = TableRowSection.TableFooter;
}
[Visual Basic]
End If
Note: Notice how the rows are sorted ascending according to the value of the ID column for the
individual rows.
In the Products.aspx window, add the following markup to the Columns element of the
gvProducts GridView control. Add it after the BoundField control, with a DataField attribute
value of ListPrice.
<asp:TemplateField HeaderText="Ad">
<ItemTemplate>
<div style="display: none">
Advertisement for
<%# Eval("Name") %>
</div>
</ItemTemplate>
</asp:TemplateField>
4. Append the following script element to the Products.aspx Web Form, at the end of the Content
control with an ID attribute value of BodyContent.
<script type="text/javascript">
$(document).ready(function () {
$("a").mouseover(function () {
var divs = $(this).closest("tr").find("div").fadeIn("slow");
});
$("a").mouseout(function () {
var divs = $(this).closest("tr").find("div").fadeOut("slow");
});
});
</script>
</asp:Content>
In the Products.aspx window, add the following script element to the Products.aspx Web
Form, at the end of the Content control with an ID attribute value of BodyContent. Add it after
the closing p tag.
<script type="text/javascript">
$(document).ready(function () {
$("a").mouseover(function () {
var divs = $(this).closest("tr").find("div").fadeIn("slow");
});
$("a").mouseout(function () {
var divs = $(this).closest("tr").find("div").fadeOut("slow");
});
});
</script>
<script type="text/javascript">
$(document).ready(function () {
$("a").mouseover(function () {
var divs = $(this).closest("tr").find("div").fadeIn("slow");
});
$("a").mouseout(function () {
var divs = $(this).closest("tr").find("div").fadeOut("slow");
});
});
$(document).ready(function () {
$("a").mouseover(function () {
$(this).closest("tr").find("div").fadeInFadeOut("slow");
});
});
</script>
Note: The custom advertisement message is displayed in the rightmost column, but now it closes
after a short period.
b. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab
12\Starter\Exercise 03\AdventureWorks.sln or D:\Lab Files\VB\Lab 12\Starter\Exercise
03\AdventureWorks.sln, and then click Open.
f Task 3: Add Logic to the query and return a random product from the database
1. Remove the default DoWork method and comments from the service class.
[Visual C#]
// To use HTTP GET, add [WebGet] attribute. (Default ResponseFormat is
WebMessageFormat.Json)
// To create an operation that returns XML,
// add [WebGet(ResponseFormat=WebMessageFormat.Xml)],
// and include the following line in the operation body:
// WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml";
[OperationContract]
public void DoWork()
{
// Add your operation implementation here
return;
}
[Visual Basic]
' To use HTTP GET, add <WebGet()> attribute. (Default ResponseFormat is
WebMessageFormat.Json)
' To create an operation that returns XML,
' add <WebGet(ResponseFormat:=WebMessageFormat.Xml)>,
' and include the following line in the operation body:
' WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml"
<OperationContract()>
Public Sub DoWork()
' Add your operation implementation here
End Sub
' Add more operations here and mark them with <OperationContract()>
In the ProductsService.svc window, select the following code, and then press DELETE.
[Visual C#]
// To use HTTP GET, add [WebGet] attribute. (Default ResponseFormat is
WebMessageFormat.Json)
// To create an operation that returns XML,
// add [WebGet(ResponseFormat=WebMessageFormat.Xml)],
// and include the following line in the operation body:
// WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml";
[OperationContract]
public void DoWork()
{
// Add your operation implementation here
return;
10 Lab Answer Key: Developing Client-side Scripts and Services
[Visual Basic]
' To use HTTP GET, add <WebGet()> attribute. (Default ResponseFormat is
WebMessageFormat.Json)
' To create an operation that returns XML,
' add <WebGet(ResponseFormat:=WebMessageFormat.Xml)>,
' and include the following line in the operation body:
' WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml"
<OperationContract()>
Public Sub DoWork()
' Add your operation implementation here
End Sub
' Add more operations here and mark them with <OperationContract()>
[Visual C#]
public class ProductsService
{
[OperationContract]
public string GetRandomProduct()
{
var random = new Random();
using (var db = new AdventureWorksEntities())
{
var randomNumber = random.Next(1, db.Products.Count() + 1);
var randomProduct = (from p in db.Products
where p.ProductID == randomNumber
select new { p.Name, p.ListPrice, p.ProductNumber
}).FirstOrDefault();
return new
System.Web.Script.Serialization.JavaScriptSerializer().Serialize(randomProduct);
}
}
}
[Visual Basic]
Public Class ProductsService
<OperationContract()>
Public Function GetRandomProduct() As String
Dim random = New Random()
Return New
System.Web.Script.Serialization.JavaScriptSerializer().Serialize(randomProduct)
End Using
End Function
End Class
Lab Answer Key: Developing Client-side Scripts and Services 11
In the ProductsService.svc window, add the following code in the ProductsService class.
[Visual C#]
[OperationContract]
public string GetRandomProduct()
{
var random = new Random();
int randomNumber = 0;
while (count == 0)
{
randomNumber = random.Next(500, 1000);
count = query.Count();
}
return new
System.Web.Script.Serialization.JavaScriptSerializer().Serialize(randomProduct);
}
}
[Visual Basic]
<OperationContract()>
Public Function GetRandomProduct() As String
Dim random = New Random()
Dim randomNumber As Integer
While count = 0
randomNumber = random.[Next](500, 1000)
count = query.Count()
End While
Return New
System.Web.Script.Serialization.JavaScriptSerializer().Serialize(randomProduct)
End Using
12 Lab Answer Key: Developing Client-side Scripts and Services
End Function
Note: We are invoking the ProductsService from the client side. Hence, we want the returned format
to be XML or Json. For this reason, we are using the JavaScriptSerializer class to serialize the class into
a valid Json format.
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="AdventureWorks.ProductsServiceAspNetAjaxBehavior">
<enableWebScript />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
<services>
<service name="AdventureWorks.ProductsService">
<endpoint address=""
behaviorConfiguration="AdventureWorks.ProductsServiceAspNetAjaxBehavior"
binding="webHttpBinding" contract="AdventureWorks.ProductsService" />
</service>
</services>
</system.serviceModel>
f Task 5: Invoke WCF service using client-side code from the master page
1. Open the Site.Master master page.
In Solution Explorer, double-click Site.Master.
2. Add a reference to the ProductsService WCF by adding a ScriptManager control.
In the Site.Master window, add the following markup to the form element at the top of the
Site.Master file, after the opening form tag.
3. Add the following code to the Site.Master master page, after the closing html tag, at the end of the
script element.
Lab Answer Key: Developing Client-side Scripts and Services 13
getRandomProduct();
function getRandomProduct() {
ProductsService.GetRandomProduct(function (response) {
var product = eval('(' + response + ')');
document.getElementById("ProductName").innerHTML = product.Name;
document.getElementById("ProductNumber").innerHTML = product.ProductNumber;
document.getElementById("ProductPrice").innerHTML = product.ListPrice;
});
}
In the Site.Master window, append the following code to the script element at the bottom of
the Site.Master file.
getRandomProduct();
function getRandomProduct() {
ProductsService.GetRandomProduct(function (response) {
var product = eval('(' + response + ')');
document.getElementById("ProductName").innerHTML = product.Name;
document.getElementById("ProductNumber").innerHTML =
product.ProductNumber;
document.getElementById("ProductPrice").innerHTML = product.ListPrice;
});
}
<div class="main">
<asp:ContentPlaceHolder ID="MainContent" runat="server" />
<div style="margin: 10px 10px 10px 10px; padding: 10px 10px 10px 10px; border:
solid 2px black;
float: right; top: 150px; left: 500px; position: absolute;">
<h3>
FEATURED PRODUCT</h3>
Product Name:
<label id="ProductName">
</label>
<br />
Product Number:
<label id="ProductNumber">
</label>
<br />
Product Price: $<label id="ProductPrice"></label>
<br />
</div>
</div>
<div class="clear">
</div>
In the Site.Master window, add the following markup to the div element with a class attribute
value of main, after the MainContent ContentPlaceHolder control.
<div style="margin: 10px 10px 10px 10px; padding: 10px 10px 10px 10px; border:
solid 2px black;
float: right; top: 150px; left: 500px; position: absolute;">
<h3>
FEATURED PRODUCT</h3>
Product Name:
<label id="ProductName">
14 Lab Answer Key: Developing Client-side Scripts and Services
</label>
<br />
Product Number:
<label id="ProductNumber">
</label>
<br />
Product Price: $<label id="ProductPrice"></label>
<br />
</div>
f Task 6: Turn off the virtual machine and revert the changes
1. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Lab Answer Key: Implementing Advanced Ajax in a Web Application 1
Module 13
Lab Answer Key: Implementing Advanced Ajax in a Web
Application
Contents:
Exercise 1: Using Microsoft Ajax in an MVC Page 2
Exercise 2: Using jQuery in an MVC View 6
Exercise 3: Handling Events 8
2 Lab Answer Key: Implementing Advanced Ajax in a Web Application
In the Site.Master window, in the head element, append the following markup.
[Visual C#]
return View(prodCategories);
}
[Visual Basic]
Return View(prodCategories)
End Function
int id = int.Parse(CategoryID);
var products = pr.GetProductsByCategory(id);
return View(products);
[Visual Basic]
return View(prodCategories);
[Visual Basic]
Return View(prodCategories)
IEnumerable<AdventureWorksMvc.Models.ProductCategory> or IEnumerable(Of
AdventureWorksMvc.ProductCategory), and then click Add.
2. Insert the following markup and code in the _AjaxProductCategories.ascx file, after the Control
directive.
[Visual C#]
[Visual Basic]
</option>
<% Next%>
</select>
<div id="productCategories">
</div>
<% End Using%>
<h2>
Product Catalog</h2>
<label>
Choose a Category:</label>
<br />
<% Html.RenderPartial("_AjaxProductCategories", Model);%>
[Visual Basic]
<h2>
Product Catalog</h2>
<label>
Choose a category:</label>
<br />
<% Html.RenderPartial("_AjaxProductCategories", Model)%>
Products
6. Base the Index view on a different data class, by modifying the Inherits attribute value in the Page
directive.
[Visual C#]
Inherits="System.Web.Mvc.ViewPage<IEnumerable<AdventureWorksMvc.Models.ProductCategor
y>>"
6 Lab Answer Key: Implementing Advanced Ajax in a Web Application
[Visual Basic]
In the Index.aspx window, modify the Inherits attribute in the Page directive, to contain the
following value.
[Visual C#]
System.Web.Mvc.ViewPage<IEnumerable<AdventureWorksMvc.Models.ProductCategory>>
[Visual Basic]
In the Site.Master window, in the head element, append the following markup.
[Visual Basic]
<br />
<div id="featured-products"></div>
In the Index.aspx window, in the Content2 Content element, append the following markup.
<br />
<div id="featured-products"></div>
3. Create the Ajax method call. This function calls the controller action, and then returns the
results into the featured products div created earlier. Add the following markup to handle the
click event for the rendered select element, at the bottom of the page, before the closing Content
tag.
<script type="text/javascript">
$(document).ready(function () {
$("#CategoryID ").click(function () {
var id = $(this).val();
$("#featured-products").load('<%= Url.Action("FeaturedProducts") %>', {
CategoryId: id });
});
});
</script>
Note: The products for the chosen category are displayed below the list.
<div class="log"></div>
3. After the featured-products div element, add a div to display the Ajax error messages.
<div class="error"></div>
4. In the $(document).ready jQuery function, add the following functions to display and hide the status
messages.
$(document).ready(function () {
$("#CategoryID").click(function () {
var id = $(this).val();
$("#featured-products").load('<%= Url.Action("FeaturedProducts") %>', {
CategoryId: id });
});
$('.log').ajaxStart(function () {
Lab Answer Key: Implementing Advanced Ajax in a Web Application 9
$(this).text('Loading...');
$('.error').text('');
});
$('.log').ajaxComplete(function () {
$(this).text('');
});
});
$('.log').ajaxStart(function () {
$(this).text('Loading...');
$('.error').text('');
});
$('.log').ajaxComplete(function () {
$(this).text('');
});
$(document).ready(function () {
$("#CategoryID ").click(function () {
var id = $(this).val();
$("#featured-products").load('<%= Url.Action("FeaturedProducts") %>', {
CategoryId: id });
});
$('.error').ajaxError(function () {
$(this).text('There was an error! Please try again later...');
});
$('.error').ajaxError(function () {
$(this).text('There was an error! Please try again later...');
});
$('.log').ajaxStart(function () {
$(this).text('Loading...');
$('.error').text('');
});
$('.log').ajaxComplete(function () {
$(this).text('');
});
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>
Product Catalog</h2>
<label>
Choose a category:</label>
<br />
<% Html.RenderPartial("_AjaxProductCategories", Model);%>
<br />
<div class="log">
</div>
<div id="featured-products">
</div>
<div class="error">
</div>
<script type="text/javascript">
$(document).ready(function () {
$("#CategoryID").click(function () {
var id = $(this).val();
$("#featured-products").load('<%= Url.Action("FeaturedProducts") %>',
{ CategoryId: id });
});
$('.log').ajaxStart(function () {
$(this).text('Loading...');
$('.error').text('');
});
$('.log').ajaxComplete(function () {
$(this).text('');
});
$('.error').ajaxError(function () {
$(this).text('There was an error! Please try again later...');
});
});
</script>
</asp:Content>
[Visual Basic]
Note: The products for the chosen category are displayed below the list, but first you see the Loading...
notice.
f Task 5: Turn off the virtual machine and revert the changes
1. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Lab Answer Key: ASP.NET Deployments 1
Module 14
Lab Answer Key: ASP.NET Deployments
Contents:
Exercise 1: Creating a Profile for Deploying a Web Application Project
Using One-Click Publish 2
Exercise 2: Creating a Web Deployment Package 5
2 Lab Answer Key: ASP.NET Deployments
Note: An ASP.NET Application Services SQL Server database file ASPNETDB.MDF is created in the
App_Data folder, and the values that you entered have been saved to it.
f Task 6: Update the connection string in the Web.config file by creating a transform file
1. [Visual Basic] Show all files for the Deployment project in Solution Explorer.
In Solution Explorer, click Deployment, and then click the Show All Files button.
2. Expand the Web.config file.
In Solution Explorer, expand Web.config.
3. Open the Web.Release.config file.
In Solution Explorer, double-click Web.Release.config.
4. Examine and delete the block of comments that contains a connectionStrings element.
In the Web.Release.config window, select the following markup, and then click DELETE.
<!--
In the example below, the "SetAttributes" transform will change the value of
"connectionString" to use "ReleaseSQLServer" only when the "Match" locator
finds an atrribute "name" that has a value of "MyDB".
<connectionStrings>
<add name="MyDB"
4 Lab Answer Key: ASP.NET Deployments
connectionString="Data Source=ReleaseSQLServer;Initial
Catalog=MyReleaseDB;Integrated Security=True"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>
-->
<connectionStrings>
<add name="ApplicationServices"
connectionString="Data
Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\aspnetdb.mdf;Integrated
Security=True;User Instance=True"
providerName="System.Data.SqlClient"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
</connectionStrings>
Note: If you were not using a database file, as in this case, you would typically use the connection
string that you received from your hosting company.
Note: If your hosting company advises you to allow untrusted certificates, select the Allow
untrusted certificate check box.
<connectionStrings>
<add name="ApplicationServices"
connectionString="data source=.\SQLEXPRESS;Integrated
Security=SSPI;AttachDBFilename=|DataDirectory|\aspnetdb.mdf;User Instance=true"
providerName="System.Data.SqlClient" />
<add name="AW"
connectionString="Data
Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\AdventureWorksLT2008R2_Data.mdf;
Integrated Security=True;Connect Timeout=30;User
Instance=True;MultipleActiveResultSets=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
In the Web.config window, in the connectionString element, add the following markup after
the add element.
<add name="AW"
connectionString="Data
Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\AdventureWorksLT2008R2_Data.
mdf;Integrated Security=True;Connect Timeout=30;User
Instance=True;MultipleActiveResultSets=True"
providerName="System.Data.SqlClient" />
6 Lab Answer Key: ASP.NET Deployments
obj\Debug\Package\Deployment.zip
Lab Answer Key: ASP.NET Deployments 7
4. In the IIS Web site/application name to use on the destination server box, type Default Web
Site/Deployment.
5. Save the changes.
Press CTRL+S.
Note: You are using the same destination connection string for both local databases. Therefore, during
deployment, the scripts that create and populate database objects will all run in the same database.
13. Ensure that the Pull data and/or schema from an existing database check box is selected.
14. In the Connection string for source database box, type Data
Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\AdventureWorksLT2008R2_Data.m
df;Integrated Security=True;Connect Timeout=30;User Instance=True.
15. Set the database scripting options to Schema and Data.
8 Lab Answer Key: ASP.NET Deployments
In the Deployment window, in the Database scripting options list, click Schema and Data.
16. Add the D:\Lab Files\CS\Lab 14\Starter\DeploymentGrant.sql or D:\Lab Files\VB\Lab
14\Starter\DeploymentGrant.sql script, by clicking Add Script.
In the Select File dialog box, in the File name box, type D:\Lab Files\CS\Lab
14\Starter\DeploymentGrant.sql or D:\Lab Files\VB\Lab 14\Starter\DeploymentGrant.sql
script, and then click Open.
17. Save the changes.
Press CTRL+S.
In the Web.Debug.config window, select the following markup, and then click DELETE.
<!--
In the example below, the "SetAttributes" transform will change the value of
"connectionString" to use "ReleaseSQLServer" only when the "Match" locator
finds an atrribute "name" that has a value of "MyDB".
<connectionStrings>
<add name="MyDB"
connectionString="Data Source=ReleaseSQLServer;Initial
Catalog=MyReleaseDB;Integrated Security=True"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>
-->
Note: Visual Studio builds the project and creates the deployment package, displaying a log in the
Output window. As part of the package creation process, the Web Deploy dbFullSQL provider
creates two SQL server scriptsone for each source database. There is only one destination
database, and both of these scripts will run in that database when you import the package.
http://localhost/Deployment
Note: The Default.aspx page is displayed. It looks the same as it does when you run it in Visual
Studio 2010.
Note: The Default.aspx page is displayed, with Welcome student! next to the Log Out link. This
demonstrates that the ASP.NET membership database was deployed successfully.
f Task 10: Turn off the virtual machine and revert the changes
1. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.
Lab Answer Key: Developing a Web Application by Using Silverlight 1
Module 15
Lab Answer Key: Developing a Web Application by Using
Silverlight
Contents:
Exercise 1: Creating a Silverlight Project 2
Exercise 2: Creating a Silverlight WCF Service 3
Exercise 3: Displaying Data by Using Silverlight Controls 5
2 Lab Answer Key: Developing a Web Application by Using Silverlight
Task 3: Create methods that return a list of product categories, and a list of products by
category
1. Delete the stub method DoWork from the code file.
In the ProductServiceSL.svc.cs or ProductServiceSL.svc.vb window, select the following code, and
then press DELETE.
[Visual C#]
[OperationContract]
public void DoWork()
{
// Add your operation implementation here
return;
}
[Visual Basic]
<OperationContract()>
Public Sub DoWork()
' Add your operation implementation here
End Sub
' Add more operations here and mark them with <OperationContract()>
[Visual C#]
using System.Collections.Generic;
[Visual Basic]
Imports System.Collections.Generic
3. Add the following method, which returns a list of product categories, to the ProductServiceSL class.
[Visual C#]
[OperationContract]
public IEnumerable<ProductCategory> GetProductCategories()
{
return DataAccessLayer.Products.GetCategories();
}
[Visual Basic]
Lab Answer Key: Developing a Web Application by Using Silverlight 5
<OperationContract>
Public Function GetProductCategories() As IEnumerable(Of ProductCategory)
Return AdventureWorks.DataAccessLayer.Products.GetCategories()
End Function
4. Add the following method that returns a list of products by category, to the ProductServiceSL class.
[Visual C#]
[OperationContract]
public IEnumerable<Product> GetProductsByCategory(int ProductCategoryID)
{
return DataAccessLayer.Products.GetProductsByCategory(ProductCategoryID);
}
[Visual Basic]
<OperationContract>
Public Function GetProductsByCategory(ProductCategoryID As Integer) As IEnumerable(Of
Product)
Return
AdventureWorks.DataAccessLayer.Products.GetProductsByCategory(ProductCategoryID)
End Function
c. In the Services list, click ProductServiceSL.svc, in the Namespace box, type AdventureWorks,
and then click OK.
c. In the Properties window, in the Height box, type 300, in the Width box, type 370, and
ensure the AutoGenerateColumns check box is cleared.
7. Drag two Silverlight Label controls onto the page. Position them directly above the two DataGrid
controls.
8. Make the following changes to the left-most Labels control.
Name: CategoryLabel
Height: 14
Width: 100
Content: Categories
a. In the Designer, select the left-most Label control.
b. In the XAML view, in the opening Label tag, set the value of the Name attribute to
CategoryLabel.
c. In the Properties window, in the Height box, type 14, in the Width box, type 100, in the
Content box, type Categories, and then press ENTER.
9. Make the following changes to the right-most Labels control.
Name: ProductLabel
Height: 14
Width: 100
Content: Products
a. In the Designer, select the right-most Label control.
b. In the XAML view, in the opening Label tag, set the value of the Name attribute to
ProductLabel.
c. In the Properties window, in the Height box, type 14, in the Width box, type 100, in the
Content box, type Products, and then press ENTER.
10. The final result will look something like this:
8 Lab Answer Key: Developing a Web Application by Using Silverlight
<UserControl x:Class="AdventureWorksSL.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
Height="400" Width="600">
12. Configure the CategoriesDataGrid control to display the necessary columns returned from the
GetProductCategories service method, by adding a DataGrid.Columns element to the
CategoriesDataGrid control.
</sdk:DataGrid>
a. In the XAML view, change the self-closing DataGrid element with the Name attribute value of
CategoriesDataGrid, to an opening and closing element.
b. In the XAML view, between the opening and closing DataGrid element with the Name attribute
value of CategoriesDataGrid, add the following markup.
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Binding="{Binding ProductCategoryID}" Header="ID"
Visibility="Collapsed" />
<sdk:DataGridTextColumn Binding="{Binding Name}" Header="Name" />
</sdk:DataGrid.Columns>
13. Configure the ProductsDataGrid control to display the necessary columns returned from the
GetProductByCategory service method, by adding a DataGrid.Columns element to the
ProductsDataGrid control.
a. In the XAML view, change the self-closing DataGrid element with the Name attribute value of
CategoriesDataGrid, to an opening and closing element.
b. In the XAML view, between the opening and closing DataGrid element with the Name attribute
value of CategoriesDataGrid, add the following markup.
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Binding="{Binding Name}" Header="Name" />
<sdk:DataGridTextColumn Binding="{Binding ProductNumber}" Header="Product
Number" />
<sdk:DataGridTextColumn Binding="{Binding Color}" Header="Color" />
<sdk:DataGridTextColumn Binding="{Binding Size}" Header="Size" />
</sdk:DataGrid.Columns>
[Visual C#]
private void CategoriesDataGrid_SelectionChanged(object sender,
SelectionChangedEventArgs e)
{
[Visual Basic]
Private Sub CategoriesDataGrid_SelectionChanged(ByVal sender As System.Object, ByVal
e As System.Windows.Controls.SelectionChangedEventArgs) Handles
CategoriesDataGrid.SelectionChanged
End Sub
2. In the MainPage class, create a protected variable for the ProductServiceSLClient object.
[Visual C#]
public partial class MainPage : UserControl
{
protected AdventureWorks.ProductServiceSLClient productService = new
AdventureWorks.ProductServiceSLClient();
...
[Visual Basic]
Public Partial Class MainPage
Inherits UserControl
In the MainPage.xaml.cs or MainPage.xaml.vb window, add the following code at the top of
the MainPage class.
[Visual C#]
protected AdventureWorks.ProductServiceSLClient productService = new
AdventureWorks.ProductServiceSLClient();
[Visual Basic]
Protected productService As New AdventureWorks.ProductServiceSLClient()
3. In the MainPage class constructor, wire up event handlers for the two Web service methods.
[Visual C#]
public MainPage()
{
InitializeComponent();
productService.GetProductCategoriesCompleted += new
EventHandler<AdventureWorks.GetProductCategoriesCompletedEventArgs>(productService_Ge
tProductCategoriesCompleted);
productService.GetProductsByCategoryCompleted += new
EventHandler<AdventureWorks.GetProductsByCategoryCompletedEventArgs>(productService_G
etProductsByCategoryCompleted);
}
Lab Answer Key: Developing a Web Application by Using Silverlight 11
[Visual Basic]
Public Sub New()
InitializeComponent()
[Visual C#]
productService.GetProductCategoriesCompleted += new
EventHandler<AdventureWorks.GetProductCategoriesCompletedEventArgs>(productServic
e_GetProductCategoriesCompleted);
productService.GetProductsByCategoryCompleted += new
EventHandler<AdventureWorks.GetProductsByCategoryCompletedEventArgs>(productServi
ce_GetProductsByCategoryCompleted);
[Visual Basic]
AddHandler productService.GetProductCategoriesCompleted, AddressOf
productService_GetProductCategoriesCompleted
AddHandler productService.GetProductsByCategoryCompleted, AddressOf
productService_GetProductsByCategoryCompleted
4. Each event handler needs a method to execute once the asynchronous call completes.
[Visual C#]
void productService_GetProductsByCategoryCompleted(object sender,
AdventureWorks.GetProductsByCategoryCompletedEventArgs e)
{
[Visual Basic]
Private Sub productService_GetProductCategoriesCompleted(ByVal sender As Object,
ByVal e As AdventureWorks.GetProductCategoriesCompletedEventArgs)
End Sub
End Sub
[Visual C#]
void productService_GetProductsByCategoryCompleted(object sender,
AdventureWorks.GetProductsByCategoryCompletedEventArgs e)
{
[Visual Basic]
Private Sub productService_GetProductCategoriesCompleted(ByVal sender As Object,
ByVal e As AdventureWorks.GetProductCategoriesCompletedEventArgs)
End Sub
End Sub
5. When the page loads, the CategoriesDataGrid control must be populated. In the class constructor,
add a call to the service method GetProductCategoriesAsync.
[Visual C#]
public MainPage()
{
InitializeComponent();
productService.GetProductCategoriesCompleted += new
EventHandler<AdventureWorks.GetProductCategoriesCompletedEventArgs>(productService_Ge
tProductCategoriesCompleted);
productService.GetProductsByCategoryCompleted += new
EventHandler<AdventureWorks.GetProductsByCategoryCompletedEventArgs>(productService_G
etProductsByCategoryCompleted);
productService.GetProductCategoriesAsync();
}
[Visual Basic]
Public Sub New()
InitializeComponent()
AddHandler productService.GetProductCategoriesCompleted, AddressOf
productService_GetProductCategoriesCompleted
AddHandler productService.GetProductsByCategoryCompleted, AddressOf
productService_GetProductsByCategoryCompleted
productService.GetProductCategoriesAsync()
End Sub
[Visual C#]
productService.GetProductCategoriesAsync();
Lab Answer Key: Developing a Web Application by Using Silverlight 13
[Visual Basic]
productService.GetProductCategoriesAsync()
Task 5: Bind the data returned from the services to the grids
1. The initial call to GetProductCategoriesAsync returns to
productService_GetProductCategoriesCompleted. In the
productService_GetProductCategoriesCompleted method, bind the results using the ItemsSource
property returned by the service to the grid.
[Visual C#]
void productService_GetProductCategoriesCompleted(object sender,
AdventureWorks.GetProductCategoriesCompletedEventArgs e)
{
CategoriesDataGrid.ItemsSource = e.Result;
}
[Visual Basic]
Sub productService_GetProductCategoriesCompleted(sender As Object, e As
AdventureWorks.GetProductCategoriesCompletedEventArgs)
CategoriesDataGrid.ItemsSource = e.Result
End Sub
[Visual C#]
CategoriesDataGrid.ItemsSource = e.Result;
[Visual Basic]
CategoriesDataGrid.ItemsSource = e.Result
2. In the CategoriesDataGrid_SelectionChanged event handler, get the selected category, and retrieve
the products by category.
[Visual C#]
private void CategoriesDataGrid_SelectionChanged(object sender,
SelectionChangedEventArgs e)
{
AdventureWorks.ProductCategory category = CategoriesDataGrid.SelectedItem as
AdventureWorks.ProductCategory;
productService.GetProductsByCategoryAsync(category.ProductCategoryID);
}
[Visual Basic]
Private Sub CategoriesDataGrid_SelectionChanged(sender As Object, e As
SelectionChangedEventArgs)
Dim category As AdventureWorks.ProductCategory =
TryCast(CategoriesDataGrid.SelectedItem, AdventureWorks.ProductCategory)
productService.GetProductsByCategoryAsync(category.ProductCategoryID)
End Sub
[Visual C#]
AdventureWorks.ProductCategory category = CategoriesDataGrid.SelectedItem as
AdventureWorks.ProductCategory;
productService.GetProductsByCategoryAsync(category.ProductCategoryID);
[Visual Basic]
Dim category As AdventureWorks.ProductCategory =
TryCast(CategoriesDataGrid.SelectedItem, AdventureWorks.ProductCategory)
productService.GetProductsByCategoryAsync(category.ProductCategoryID)
[Visual C#]
void productService_GetProductsByCategoryCompleted(object sender,
AdventureWorks.GetProductsByCategoryCompletedEventArgs e)
{
ProductsDataGrid.ItemsSource = e.Result;
}
[Visual Basic]
Sub productService_GetProductsByCategoryCompleted(sender As Object, e As
AdventureWorks.GetProductsByCategoryCompletedEventArgs)
ProductsDataGrid.ItemsSource = e.Result
End Sub
[Visual C#]
ProductsDataGrid.ItemsSource = e.Result;
[Visual Basic]
ProductsDataGrid.ItemsSource = e.Result
[Visual C#]
public partial class MainPage : UserControl
{
protected AdventureWorks.ProductServiceSLClient productService = new
AdventureWorks.ProductServiceSLClient();
public MainPage()
{
InitializeComponent();
productService.GetProductCategoriesCompleted += new
EventHandler<AdventureWorks.GetProductCategoriesCompletedEventArgs>(productService_Ge
tProductCategoriesCompleted);
productService.GetProductsByCategoryCompleted += new
EventHandler<AdventureWorks.GetProductsByCategoryCompletedEventArgs>(productService_G
etProductsByCategoryCompleted);
productService.GetProductCategoriesAsync();
}
Lab Answer Key: Developing a Web Application by Using Silverlight 15
[Visual Basic]
Partial Public Class MainPage
Inherits UserControl
Protected productService As New AdventureWorks.ProductServiceSLClient()
End Class
Task 6: Bind the data returned from the services to the grids
1. Set AdventureWorksSLTestPage.aspx as the start page.
In Solution Explorer, under AdventureWorks, right-click AdventureWorksSLTestPage.aspx,
and then click Set As Start Page.
16 Lab Answer Key: Developing a Web Application by Using Silverlight
Note: It might take a while to load the data from the WCF service.
Note: Notice how the Products list is populated with all the products for the selected category.
Task 7: Turn off the virtual machine and revert the changes
1. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Turn Off.
2. In the Turn Off Machine dialog box, click Turn Off.
3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click
Revert.
4. In the Revert Virtual Machine dialog box, click Revert.