10264AD ENU LabManual
10264AD ENU LabManual
M I C R O S O F T
L E A R N I N G
P R O D U C T
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. 2010 Microsoft Corporation. All rights reserved. Microsoft, and Windows are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries. All other trademarks are property of their respective owners.
Module 1
Lab Instructions: Overview of Web Application Architecture and Design
Contents:
Exercise 1: Exploring the Adventure Works Website Exercise 2: Comparing Web Forms and MVC Exercise 3: Working with the Request Life Cycle 4 7 8
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 the e existing Adve enture Works website w and be ecome familiar with its desig gn. Fu urthermore, yo ou will compar re how applica ation developm ment by using Web Forms differs from ap pplication dev velopment by using u the MVC C framework. Finally, you will explore how to t create contr rols dynamical lly by adding an advertiseme ent on the pag ge.
As a web develo oper at Adventure Works, yo ou have worke ed extensively with ASP.NET 2.0. However, you ha ave limited experience with ASP.NET 4.0. You Y need to fu urther explore the features of o ASP.NET 4.0 to ac ccomplish the goals set by management m for the new Ad dventure Work ks website. As a first step tow ward this en nd, you want to t examine the e MVC framew work and unde erstand how it compares with h the Web For rms pr rogramming model. m
4. 5.
Note: The debugger reaches your breakpoint in the Page_Load method. 6. 7. Step through the web application startup until you reach the end of Page_Load method. 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. 8. Close Windows Internet Explorer.
Note: The debugger reaches the breakpoint in the Application_Start method. 7. 8. 9. Examine the static/Shared RegisterRoutes method. Step through the web application startup until you reach the last line of code in the Index action method of the Home controller. Continue the web application.
Note: The URL displayed in the address bar of Internet Explorer does not include the name of the page (Index.aspx) displayed. 10. Close Windows Internet Explorer.
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.
f Task 2: Examine the markup and code found in the Default.aspx Web Forms page
1. 2. Examine the code in the Default.aspx.cs or Default.aspx.vb code file. 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 C# Visual Basic 2. 3. Location D:\Lab Files\CS\Lab 01\Starter\MVC D:\Lab Files\VB\Lab 01\Starter\MVC
Examine the code in the HomeController.cs or HomeController.vb code file. Examine the markup in the Index.aspx page.
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.
Exploring the life cycle of a Web Forms page. Exploring the life cycle of a MVC request.
5. 6.
View the code-behind file for the Default Web Form. In the Page_Load method, add the following code at the beginning of the method. [Visual C#]
lblAdvertisement.Text = "My advertisement here";
[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. 8. 9. Close Windows Internet Explorer. Close Visual Studio 2010.
[Visual Basic]
<p><%: ViewData("Advertisement") %></p>
5.
Open the file Controllers\HomeController.cs or Controllers\HomeController.vb. In Solution Explorer, expand Controllers, and then double-click HomeController.cs or HomeController.vb.
6. 7.
Locate the Index method in the file. Add the following code at the beginning of the Index method. [Visual C#]
[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. 9. Close Windows Internet Explorer.
f Task 3: Turn off the virtual machine and revert the changes
1. 2. 3. 4. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. 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.
Module 2
Lab Instructions: Designing a Web Application
Contents:
Exercise 1: Reviewing the Adventure Works Website Structure Exercise 2: Redesigning the Adventure Works Website Exercise 3: Adding MVC Capabilities to the Adventure Works Website 4 5 7
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 diagr rams showing the t overall arc chitecture and page flow of the t Adventure e Works websit te. Identify wh hich pages of the website will use Web For rms, and which h pages will use MVC, based on business requirements. c to the existing website. Add MVC capabilities
In ntroduction n
In n this lab, you will w first capture your understanding of the current Adve enture Works website by di iagramming it ts overall architecture and pa age flow. You will then revie ew the business requirement ts set by m management, and a recommen nd which page es of the website will use We eb Forms, and which pages will w 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 Manage ement approva al comes throu ugh.
Now that you have h a better understanding u of Web Forms s and MVC, yo ou can see the benefits of using M MVC to develop p some pages of the Advent ture Works we ebsite. Your nex xt task is to cre eate a proposa al de etailing recom mmendations fo or redesigning g the website. Your Y proposal needs to desc cribe the struc cture of th he current web bsite and recom mmend an app propriate prog gramming mod del for developing the page es of the re edesigned web bsite. Keep in mind m that you are operating on a tight budget, so you need n to consid der the co osts and benef fits of your dec cisions before making recom mmendations. The proposal should also en numerate the rationale unde erlying your re ecommendatio ons to help ma anagement ass sess them.
Results: After completing this exercise, you should have created two diagrams describing the existing architecture and page flow of the AdventureWorks web application.
Display a welcome message on the home page in English or French (Canada) Minimize page refreshes Provide support for easily changing the overall look of the application Reflect the corporate branding and propose two styles based on the corporate colors Display a marketing message on the Product Detail page Display a product advertisement on the blog pages Display a ticker showing biking-related news headlines on the blog pages
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.
f Task 3: Add the MVC Assembly references and namespaces to the Web.config file
1. 2. Open the Web.config file in the root AdventureWorks folder. 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> ...
<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>
3.
<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
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>
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>
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 = "" } ); } [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
// Parameter defaults
3.
12
RegisterRoutes(RouteTable.Routes); } [Visual Basic] Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs) RegisterRoutes(RouteTable.Routes) End Sub
4.
3.
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-938400065b846f21};{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-938400065b846f21};{F184B08F-C81C-45F6-A57F-5ABD9991F28F}</ProjectTypeGuids> ...
4. 5. 6. 7.
Save the project file. Reload the AdventureWorks project. Test the new project type by opening the Add New Item dialog box. Close Visual Studio 2010.
13
f Task 6: Turn off the virtual machine and revert the changes
1. 2. 3. 4. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. 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.
Module 3
Lab Instructions: Developing MVC Models
Contents:
Exercise 1: Exploring the AdventureWorks Database Exercise 2: Adding an ADO.NET Entity Data Model Exercise 3: Model Data Validation 4 7 12
O Objectives:
After completin ng this lab, you u will be able to: t Work with the Adventure eWorks databa ase. F data model. Use Entity Framework Implement data validatio on for the MVC C models.
In ntroduction n
In n this lab, you will w create rela ationships betw ween database e tables by using the Databa ase Designer, create c an n Entity Frame ework data mo odel, add a dat ta repository, and a implemen nt data model validation. v
3. 4.
Note: The relationship between the Customer and CustomerAddress table is one-to-many, which means a single customer can have multiple addresses.
2. 3.
Close the Database Designer and do not save the diagram. Close Visual Studio 2010.
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.
2.
Use the existing AdventureWorksLT2008ConnectionString connection string to connect to the database, and save the connection settings in the Web.config file as AdventureWorksEntities.
3.
Select the Blog and Blogger tables from the database and name the model namespace AdventureWorksModel.
4.
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
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); }
11
public void UpdateBlog(Blog blog) { db.Blogs.ApplyCurrentValues(blog); } public void DeleteBlog(Blog blog) { db.Blogs.DeleteObject(blog); } public void Save() { db.SaveChanges(); } [Visual Basic] Public Sub AddBlog(ByVal blg As Blog) db.Blogs.ApplyCurrentValues(blg) End Sub Public Sub UpdateBlog(ByVal blg As Blog) db.Blogs.Attach(blg) End Sub Public Sub DeleteBlog(ByVal blg As Blog) db.Blogs.DeleteObject(blg) End Sub Public Sub Save() db.SaveChanges() End Sub
7. 8.
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
3.
Note: In the next section, you will add business rules validation to the partial class.
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 <Required()> <DisplayName("Blog Entry")> _ Public Property BlogEntry As Object End Class
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
3. 4.
Build the solution, and fix any errors. Close Visual Studio 2010.
f Task 4: Turn off the virtual machine and revert the changes
1. 2. 3. 4. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. 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.
Module 4
Lab Instructions: Developing MVC Controllers
Contents:
Exercise 1: Creating an MVC Controller Exercise 2: Adding code to list the existing blog entries Exercise 3: Adding code to create a new blog entry Exercise 4: Adding code to edit a blog entry Exercise 5: Adding code to delete a blog entry 4 6 9 12 16
Note: You can perform the ta N asks in this lab b by using eithe er Microsoft Visual V C# or Microsoft Visua al Ba asic as your programming p language.
O Objectives
After completin ng this lab, you u will be able to: t Create an MVC M controller. List the exis sting blog entr ries. 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 perf form create, re ead, update, an nd de elete (CRUD) operations. o
ions for redesigning the Adv Ba ased on your recommendat r ventureWorks website, the blog b pages nee ed to be de eveloped by using u MVC. You u have already y built your MV VC model classes by leverag ging an existing g ADO.NET Entity y Data Model. Next, you nee ed to develop an a MVC contro oller to handle e the database e op perations.
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 Function Index() As ActionResult Return View() End Function End Class End Namespace
4. 5.
Build the solution, and fix any errors. Close Visual Studio 2010.
Results: After this exercise, you should have created a new controller named BlogController that is decorated with the HandleErrorAttribute attribute.
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()
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
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
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) If blogEntry Is Nothing Then Return RedirectToAction("Index") End If 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) If blogEntry Is Nothing Then Return RedirectToAction("Index") End If Return View(blogEntry) End Function
4. 5.
Build the solution, and fix any errors. Close Visual Studio 2010.
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.
Open the AdventureWorksMvc solution in Visual Studio 2010. Create a Create action method. Create a Create action method that accepts an HTTP Post.
[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
10
[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(); TempData["ConfirmationMessage"] = blog.Title + " has been added."; return RedirectToAction("Index"); } catch (Exception) { return View(blog); };
[Visual Basic]
If ModelState.IsValid Then Try blg.DatePosted = DateTime.Now blogRepository.AddBlog(blg) blogRepository.Save() TempData("ConfirmationMessage") = blg.Title & " has been added" 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();
11
TempData["ConfirmationMessage"] = blog.Title + " has been added."; 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() TempData("ConfirmationMessage") = blg.Title & " has been added" Return RedirectToAction("Index") Catch Return View(blg) End Try End If Return View(blg) End Function
4. 5.
Build the solution, and fix any errors. Close Visual Studio 2010.
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
[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) If blogEntry Is Nothing Then Return RedirectToAction("Index") End If 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);
13
[Visual Basic]
Function Edit(ByVal id As Integer) As ActionResult Dim blogEntry = blogRepository.GetBlog(id) If blogEntry Is Nothing Then Return RedirectToAction("Index") End If 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(); TempData["ConfirmationMessage"] = blog.Title + " has been updated."; return RedirectToAction("Index"); } catch (Exception) { return View(blog); };
[Visual Basic]
Dim blogEntry = blogRepository.GetBlog(id)
14
If blogEntry Is Nothing Then Return RedirectToAction("Index") End If Try UpdateModel(blogEntry, collection.ToValueProvider()) blogRepository.UpdateBlog(CType(blogEntry, Blog)) blogRepository.Save() TempData("ConfirmationMessage") = blogEntry.Title & " has been updated" 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(); TempData["ConfirmationMessage"] = blog.Title + " has been updated."; 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) If blogEntry Is Nothing Then Return RedirectToAction("Index") End If Try UpdateModel(blogEntry, collection.ToValueProvider()) blogRepository.UpdateBlog(CType(blogEntry, Blog)) blogRepository.Save() TempData("ConfirmationMessage") = blogEntry.Title & " has been updated" Return RedirectToAction("Index") Catch Return View(blogEntry) End Try End Function
15
4. 5.
Build the solution, and fix any errors. Close Visual Studio 2010.
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
[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) If blogEntry Is Nothing Then Return RedirectToAction("Index") End If 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);
17
[Visual Basic]
Function Delete(ByVal id As Integer) As ActionResult Dim blogEntry = blogRepository.GetBlog(id) If blogEntry Is Nothing Then Return RedirectToAction("Index") End If 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(); TempData["ConfirmationMessage"] = blog.Title + " has been deleted."; return RedirectToAction("Index");
[Visual Basic]
Dim blogEntry = blogRepository.GetBlog(id) If blogEntry Is Nothing Then Return RedirectToAction("Index") End If blogRepository.DeleteBlog(CType(blogEntry, Blog)) blogRepository.Save() TempData("ConfirmationMessage") = blogEntry.Title & " has been deleted." Return RedirectToAction("Index")
18
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(); TempData["ConfirmationMessage"] = blog.Title + " has been deleted."; return RedirectToAction("Index"); }
[Visual Basic]
<HttpPost()> Function Delete(ByVal id As Integer, ByVal confirmation As String) As ActionResult Dim blogEntry = blogRepository.GetBlog(id) If blogEntry Is Nothing Then Return RedirectToAction("Index") End If blogRepository.DeleteBlog(CType(blogEntry, Blog)) blogRepository.Save() TempData("ConfirmationMessage") = blogEntry.Title & " has been deleted." Return RedirectToAction("Index") End Function
4. 5.
Build the solution, and fix any errors. Close Visual Studio 2010.
f Task 4: Turn off the virtual machine and revert the changes
1. 2. 3. 4. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. 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.
Module 5
Lab Instructions: Developing MVC Views
Contents:
Exercise 1: Develop a List MVC View Exercise 2: Develop a Details MVC view Exercise 3: Develop a Create MVC view Exercise 4: Develop an Edit MVC view Exercise 5: Develop a Delete MVC view 4 7 9 15 19
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 stronglytyped 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 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.
[Visual Basic]
<li><%: Html.ActionLink("Blog", "", "Blog")%></li>
3.
Verify that the ul element matches the following markup. [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"> <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>>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Index </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Index</h2> <% foreach (var item in Model) { %> <div> <%: Html.ActionLink("Details", "Details", new { id=item.BlogID })%> <%: item.DatePosted %> <%: item.Title %> </div> <% } %> </asp:Content>
[Visual Basic]
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of IEnumerable (Of AdventureWorksMvc.Blog))" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Index </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Index</h2> <% For Each item As AdventureWorksMvc.Blog In Model%> <div> <%: Html.ActionLink("Details", "Details", New With {.id = item.BlogID})%> <%: item.DatePosted %>
6.
1. 2.
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>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Details </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Details</h2> Blogger: <%: Model.Blogger.Name %> DatePosted: <%: Model.DatePosted %> <h3> <%: Model.Title %></h3> <%: Model.BlogEntry %> <p> <%: Html.ActionLink("Back to List", "Index") %> </p> </asp:Content>
[Visual Basic]
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of AdventureWorksMvc.Blog)" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Details </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Details</h2> Blogger: <%: Model.Blogger.Name %> DatePosted: <%: Model.DatePosted %> <h3> <%: Model.Title %></h3> <%: Model.BlogEntry %> <p> <%: Html.ActionLink("Back to List", "Index") %> </p> </asp:Content>
4. 5. 6.
Test the Details view. Close Internet Explorer. Close Visual Studio 2010. Results: After this exercise, you should have created a new MVC view that shows the details about an individual blog entry.
Add a strongly-typed view named Blogger to list all of the blogs for a particular blogger. Add a strongly-typed view named Create. Use TempData to add a confirmation message to the Index view.
Task 2: Add a strongly-typed view named Blogger to list all of the blogs for a particular
blogger
1. 2. Add an empty, strongly-typed view named Blogger based on the Site.Master master page, to the Blog folder. 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 <div> <%: <%: <%: <%: Each item As AdventureWorksMvc.Blog In Model%> Html.ActionLink("Edit", "Edit", New With {.id = item.BlogID})%> Html.ActionLink("Delete", "Delete", New With {.id = item.BlogID})%> item.DatePosted %> item.Title %>
10
</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>>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Blogger </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Blogger</h2> <% 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> </asp:Content>
[Visual Basic]
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of IEnumerable (Of AdventureWorksMvc.Blog))" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Blogger </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Blogger</h2> <% 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> </asp:Content>
11
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>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
12
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)" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> 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(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>
13
4. 5.
Run the application. Navigate directly to the Blogger view by using the following route.
blog/blogger/1
6. 7.
[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>>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Index </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Index</h2> <% if (TempData["ConfirmationMessage"] != null) { %> <div class="message"> <%: TempData["ConfirmationMessage"]%> </div> <% } %> <% foreach (var item in Model) { %> <div> <%: Html.ActionLink("Details", "Details", new { id=item.BlogID })%> <%: item.DatePosted %> <%: item.Title %> </div> <% } %> </asp:Content>
14
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of IEnumerable (Of AdventureWorksMvc.Blog))" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Index </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Index</h2> <% If Not TempData("ConfirmationMessage") Is Nothing Then%> <div class="message"> <%: TempData("ConfirmationMessage")%> </div> <% End If%> <% For Each item As AdventureWorksMvc.Blog In Model%> <div> <%: Html.ActionLink("Details", "Details", New With {.id = item.BlogID})%> <%: item.DatePosted %> <%: item.Title %> </div> <% Next%> </asp:Content>
4. 5.
Run the application. Navigate directly to the Blogger view by using the following route.
/blog/blogger/1
6. 7. 8.
Add another blog entry. Close Internet Explorer. Close Visual Studio 2010. 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.
15
Create a partial view named Blog. Create an edit view named Edit, which uses the Blog partial view. Edit a blog entry. Update the Create view to use the Blog partial view.
[Visual Basic]
<% Using (Html.BeginForm())%> <%: Html.ValidationSummary(true) %> <fieldset> <legend>Fields</legend> <div class="editor-label">
16
<%: 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 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)%>
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. 2. Add an empty, strongly-typed view of type Blog, named Edit, based on the Site.Master master page, to the Blog folder. 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>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Edit </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Edit</h2> <% Html.RenderPartial("Blog"); %> </asp:Content>
[Visual Basic]
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of AdventureWorksMvc.Blog)" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Edit </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Edit</h2> <% Html.RenderPartial("Blog")%> </asp:Content>
18
blog/blogger/1
3. 4.
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>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Create </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Create</h2> <% Html.RenderPartial("Blog"); %> </asp:Content>
[Visual Basic]
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of AdventureWorksMvc.Blog)" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Create </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Create</h2> <% Html.RenderPartial("Blog")%> </asp:Content>
3. 4.
Run the application. Navigate directly to the Blogger view by using the following route.
blog/blogger/1
5. 6. 7.
Add another blog entry. Close Internet Explorer. Close Visual Studio 2010. Results: After this exercise, you should have created a partial view that is used by both the Edit view and the Create view.
19
Add a strongly-typed view named Delete that uses the default markup provided by the Add View dialog box. Delete a blog entry.
Task 2: Add a strongly-typed view named Delete that uses the default markup provided
by the Add View dialog box
1. 2. 3. Build the solution. 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. 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>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Delete </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Delete</h2> <h3> Are you sure you want to delete this?</h3> <fieldset> <legend>Fields</legend> <div class="display-label"> BlogID</div> <div class="display-field"> <%: Model.BlogID %></div> <div class="display-label"> BloggerID</div> <div class="display-field"> <%: Model.BloggerID %></div> <div class="display-label"> DatePosted</div> <div class="display-field"> <%: String.Format("{0:g}", Model.DatePosted) %></div> <div class="display-label"> Title</div> <div class="display-field">
20
<%: 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)" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Delete </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Delete</h2> <h3> Are you sure you want to delete this?</h3> <fieldset> <legend>Fields</legend> <div class="display-label"> BlogID</div> <div class="display-field"> <%: Model.BlogID %></div> <div class="display-label"> BloggerID</div> <div class="display-field"> <%: Model.BloggerID %></div> <div class="display-label"> 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> <% End Using%> </asp:Content>
21
2.
3. 4. 5.
Select a blog entry. Close Internet Explorer. Close Visual Studio 2010.
Task 4: Turn off the virtual machine and revert the changes
1. 2. 3. 4. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. In the Revert Virtual Machine dialog box, click Revert. Results: After this exercise, you should have created an MVC view to delete blog entries.
Module 6
Lab Instructions: Designing for Discoverability
Contents:
Exercise 1: Mapping URLs of Web Forms Pages Exercise 2: Creating a Sitemap File Exercise 3: Building the Application Infrastructure 4 8 9
Objectives
After completing this lab, you will be able to: Map URLs of Web Forms pages. Create a sitemap file. Build an application infrastructure.
Introduction
In this lab, you map URLs of Web Forms pages to use ASP.NET URL mapping for listing products by category, and details for a specific product ID. You also create a sitemap, as well as a robots.txt file with an inclusion to the newly created sitemap file for the Default Web Site in IIS, and add navigation controls to the application.
Lab Scenario
You are developing an application that will be used for external customers, and you want to ensure that Search engines can find your site easily. As well, you want to use URLs that are easy for your salespeople to send in emails. Using the routing features of ASP.NET 4.0, you will map the URLs of a Web Forms page. You will create a sitemap page, and complete building the application infrastructure.
Add and verify reference to System.Web.Routing. Edit the Global.asax file to use ASP.NET URL mapping for the page listing products by category. Test the pages. Add a second route to map a URL to the following product ID: http://localhost/product/1. Test the pages.
5.
[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
4.
RegisterRoutes(RouteTable.Routes);
[Visual Basic]
Private Sub Application_Start() RegisterRoutes(RouteTable.Routes) End Sub
5. 6.
Open the Products.aspx.cs or Products.aspx.vb code file. Modify the Page_Load method in the Products class as shown.
[Visual C#]
protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { string categoryName = null; string categoryId; // Retrieve category param from "/Products/{Category}" URL categoryId = Page.RouteData.Values["category"].ToString(); 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 ' Retrieve category param from "/Products/{Category}" URL categoryId = Page.RouteData.Values("category").ToString() 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
Note: A grid should render with a single row containing products for the product category with an ID value of 1. 3. Close Internet Explorer.
[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") ' Route name ' URL with parameters ' Web forms page to handle it routes.MapPageRoute("product-browse", "product/{id}", "~/ProductDetail.aspx") End Sub
3. 4.
Open the ProductDetail.aspx.cs or ProductDetail.aspx.vb code file. Modify the Page_Load method in the ProductDetail class as shown.
[Visual C#]
protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { string productId; // Retrieve id param from /Products/{Id} URL productId = Page.RouteData.Values["id"].ToString(); var data = DataAccessLayer.Products.GetProduct(int.Parse(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();
[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 ' Retrieve id param from /Products/{Id} URL productID = Page.RouteData.Values("id").ToString() Dim data = AdventureWorks.DataAccessLayer.Products.GetProduct(Integer.Parse(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() End If End Sub
Note: A grid should render with a single row containing details of the product with an ID value of 680. 3. 4. Close Internet Explorer. Close Visual Studio 2010.
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.
Create a sitemap file to list products. Modify the robots.txt file to include the sitemap.
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.
3. 4. 5.
Save and close the Web.sitemap file. Open the Site.Master master page. Locate the div element with a class attribute value of clear hideSkiplink.
<div class="clear hideSkiplink"> <asp:Menu ID="NavigationMenu" runat="server" CssClass="menu" EnableViewState="false" IncludeStyleBlock="false" Orientation="Horizontal"> <Items> <asp:MenuItem NavigateUrl="~/Default.aspx" Text="Home" /> <asp:MenuItem NavigateUrl="~/ShoppingCart.aspx" Text="Cart" /> <asp:MenuItem NavigateUrl="~/About.aspx" Text="About" /> </Items> </asp:Menu> </div>
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="MainMenu" Orientation="Horizontal" DataSourceID="siteMapDataSource" /> </div>
7. 8. 9.
Save and close the Site.Master file. Run the application. Close Internet Explorer.
10
[Visual Basic]
Dim NavigationMenu as Menu = Me.FindControl("NavigationMenu")
3. 4. 5. 6.
Place Breakpoint on the new line of code. Debug the application. Single-step over the selected line of code. Hover the mouse over the NavigationMenu variable. Note: IntelliSense will show you details about the Menu control. You can expand the different levels by clicking the +-sign.
7. 8.
Task 4: Turn off the virtual machine and revert the changes
1. 2. 3. 4. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert.G In the Revert Virtual Machine dialog box, click Revert.
Results: After this exercise, you should have added navigation controls to the web application.
Module 7
Lab Instructions: Writing Server-Side Code for Web Forms
Contents:
Exercise 1: Modifying a Web Forms Page to Display Localized Content Exercise 2: Persisting Data on Web Forms Pages Exercise 3: Utilizing View State Effectively Exercise 4: Adding Validation to Web Forms Pages 4 8 12 15
Note: You can perform the e tasks in this la ab by using eit ther Visual C# # or Visual Basic as your programming g language.
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. Persist user r data by using g a variety of methods. m Utilize view w state effective ely. Add validat tion 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 di ifferent resour rce files. You persist user dat ta by using coo okies, application state, and session state, and you le earn how to utilize view state e effectively. You also add va alidation to Web Forms page es, using validation co ontrols.
To o improve the customer exp perience, existing Web Forms s pages of the AdventureWo orks website need to be e updated to display d localize ed information n. Because pur rchases by inte ernational cust tomers make up u a la arge percentag ge of online sales, management has decide ed that the me essages, units, dates, and so on, sh hould be displa ayed in either English or oth her languages based on a cu ustomers langu uage preference. Th herefore, you need to edit th he home page e to detect the e default brows ser language.
Open the AdventureWorks solution from the following location. Programming Language Visual C# Visual Basic Location D:\Lab Files\CS\Lab 07\Starter\Exercise 01 D:\Lab Files\VB\Lab 07\Starter\Exercise 01
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.
7.
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. Localize the hard-coded Welcome to AdventureWorks! text implicitly, by adding a Localize server control within the h2 element, with the following attributes. Attribute ID Text meta:resourcekey Value lclWelcome Welcome to AdventureWorks! LocalizeResource1
9.
10. Delete the text Welcome to AdventureWorks! from the h2 element. 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 ID Text Value ProductCategoriesLiteral <%$ Resources: ProductCategoriesLiteral.Text %>
13. Delete the text Product Categories from the p element. 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.
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 ID Text 5. Value WelcomeLiteral Welcome
Delete the text Welcome from the LoggedInTemplate element. Note: Make sure that you do not delete the text Welcome from the Literal server control.
6. 7.
Open the Site.Master master page in Design view. Generate local resources for Site.Master, by using the Generate Local Resource functionality. 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.
Note: The page should now be shown in German. 3. 4. Close Internet Explorer. Close Visual Studio 2010. Results: After this exercise, you should have a web application that supports different languages, and shows the site in the users preferred language.
f Task 2: Use a cookie collection to persist user information and set scope and lifetime to
save the last chosen category
1. 2. Open the Default.aspx Web Form in Code view. 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; HttpCookie cookie = new HttpCookie("Preferences"); 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 Dim cookie As New HttpCookie("Preferences") cookie("LastCategory") = category cookie.Expires = DateTime.Now.AddMinutes(1) Response.AppendCookie(cookie)
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(); HttpCookie cookie = Request.Cookies["Preferences"]; if (cookie != null) { lbCategories.SelectedValue = cookie["LastCategory"]; } }
[Visual Basic]
If Not Page.IsPostBack Then Dim data As List(Of ProductCategory) = AdventureWorks.DataAccessLayer.Products.GetCategories lbCategories.DataSource = data lbCategories.DataBind() Dim cookie As HttpCookie = Request.Cookies("Preferences") If Not cookie Is Nothing Then lbCategories.SelectedValue = cookie("LastCategory") End If
4.
[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
void Session_Start(object sender, EventArgs e) { Application.Lock(); int visitors = (int)Application["OnlineVisitors"]; visitors++; Application["OnlineVisitors"] = visitors; Application.UnLock(); }
[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")) If visitors > 0 Then visitors -= 1 Application("OnlineVisitors") = visitors End If Application.UnLock() End Sub
5.
11
3. 4.
Open the ShoppingCart Web Form in Code view. Analyze the code in the Page_Load method.
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. Close the SQL Server Command Line Tool, by running the following command from the Visual Studio Command Prompt (2010).
quit
6.
7. 8.
Close the Visual Studio Command Prompt (2010). Close Visual Studio 2010.
Results: After this exercise, you should have implemented state using different techniques, including Application and Session state.
12
8. 9.
Run the application. View the source of the Default.aspx page in Internet Explorer, by using the View Source functionality.
10. Analyze the HTML code, and pay special attention to the __VIEWSTATE field, which is now much smaller, almost half the size. 11. Close the View Source window. 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. 13. Close Internet Explorer.
13
2. 3.
Run the application. Click Submit. Note: The lbCategories server control is now empty because it is not being populated by the server code on a postback.
4. 5.
Close Internet Explorer. Enable view state for the lbCategories server control.
<asp:ListBox ID="lbCategories" runat="server" DataTextField="Name" DataValueField="ProductCategoryID" Height="270px" Width="186px" EnableViewState="True" ></asp:ListBox>
6. 7.
Run the application. 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.
8. 9.
Close Internet Explorer. Remove the EnableViewState attribute and value from the Page directive.
10. Remove the EnableViewState attribute and value from the lbCategories server control. 11. Disable view state for the Default Web Form by setting the ViewStateMode property to Disabled.
<%@ Page Title="Home Page" ... ViewStateMode="Disabled" %>
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>
13. Run the application. Note: The rendered page looks okay. 14. Click Submit. Note: The lbCategories server control is still populated because view state has been enabled for the server control. 15. Close Internet Explorer. 16. Close Visual Studio 2010.
14
Results: After this exercise, you should have examined and implemented the view state in different ways.
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>
2.
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
2.
a.
ControlToValidate = txtCreditCard
d. 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][09]{13})$"> </asp:RegularExpressionValidator>
3. 4.
Open the ShoppingCart Web Form in Code view. Make sure that an order can be placed only if Page.IsValid is true. Add the check to the btnPlaceOrder_Click event handler method. [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
5. 6. 7. 8. 9.
Run the application. Select Bib-Shorts on the Product Categories list, and click Submit. On the Products page, click Men's Bib-Shorts, L. On the Men's Bib-Shorts, L page, click Order. On the Shopping Cart page, click Place Order. 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.
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. 12. Close Internet Explorer. 13. Close Visual Studio 2010. 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. 2. 3. 4. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. In the Revert Virtual Machine dialog box, click Revert.
Module 8
Lab Instructions: Optimizing Data Management for Web Forms
Contents:
Lab 8A: Optimizing Data Management for Web Forms
Section 2: Visual C#
Exercise 1: Managing Data by Using LINQ to Entities Exercise 2: Customizing the GridView Exercise 3: Using ListView, DetailsView and Charts Lab 8B: Optimizing Data Management for Web Forms 14 15 21
Section 2: Visual C#
Exercise 4: Managing Data by Using ASP.NET Dynamic Data 29
Lab Instructions: Optimiz zing Data Manageme ent for Web Forms
Lab 8A: Optimizing Da ata Man nageme ent for Web Fo orms
Note: You can perform tasks in this lab either e by using Visual Basic or o Visual C# pr rogramming language. If you y are using Visual V Basic as your program mming languag ge, refer to the e steps provide ed in the Section 1 of the lab do ocument. If you u are using Vis sual C# as your programmin ng language, re efer to the steps provided p in Sec ction 2 of the lab document.
O Objectives
After completin ng this lab, you u will be able to: t Manage da ata by using th he LinqDataSo ource control. Display dat ta using the gr rid control. Display par rent and child data in the list t and detail co ontrols. Display das shboard inform mation using th he chart 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 dat ta so ource controls.
Lab b Instructions: Optim mizing Data Managem ment for Web Forms
Th he AdventureW Works Sales team has reques sted the addition of an administration section to the we ebsite so th hat they can manage m information, as well as a provide a dashboard to se enior management. As a firs st step to oward this end d, you need to create a set of f web form pa ages that will enable e the Sale es team to do the fo ollowing: View, add, edit, and delet te products View sales orders o View and edit customer details 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 dat ta so ource controls.
3.
Add a RequiredFieldValidator control named QuantityRequiredFieldValidator to the user control. The RequiredFieldValidator control must validate the QuantityTextBox control, and display the text You must fill in the Quantity. as the error message, if the user leaves the text box empty. The display mode must be dynamic.
<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, 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
5. 6.
Save and close the user control. Build the project and fix any errors.
Note: Observe the Build succeeded message in the Build pane of the Output window.
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
4.
5.
6. 7.
Save and close the ShoppingCart entity class. Build the project and fix any errors.
b. c. d. e. f.
Set the AutoGenerateEditButton property to a value of True. Add an event handler for the RowCancelingEdit event. Add an event handler for the RowEditing event. Add an event handler for the RowUpdating event. Make the existing code in the Page_Load event handler execute only on first request by wrapping the existing code in the Page_Load event handler in an If statement.
g.
Private Sub BindData() Dim cart As List(Of ShoppingCart) = CType(Session("_cart"), List(Of ShoppingCart)) gvCart.DataSource = cart gvCart.DataBind() End Sub
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.
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.
n.
Append code to the gvCart_RowUpdating method, to save the updated cart to Session state.
o.
Append code to the gvCart_RowUpdating method, for resetting the edit index and bind the data by using the BindData method.
p. q.
Save and close the ShoppingCart code-behind file. Build the project and fix any errors.
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. d. e. f.
Delete the TextBox1 control. Make the ProductId BoundField control read-only. Format the display of the ListPrice BoundField control using the DataFormatString attribute and a value of {0:c}. 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>
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 ' Display error message Dim newPageIndex As Integer = e.NewPageIndex + 1 lblMessage.Text = "Update the item before moving to page " & newPageIndex.ToString() Else ' Clear message text lblMessage.Text = "" ' Set page index CType(sender, GridView).PageIndex = e.NewPageIndex BindData() End If
d. e.
Save and close the ShoppingCart files. Build the project and fix any errors.
Note: Observe how the Quantity and Total Price columns are updated. f. g. h. i. On the Shopping Cart page, click Continue Shopping. On the Home page, in the Product Categories list, click Cranksets, and then click Submit. On the Products page, in the Cranksets list, click HL Crankset. On the Product Detail page, click Order.
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. j. k. l. On the Shopping Cart page, in the GridView pager, click 2. Close Windows Internet Explorer. Close Visual Studio 2010.
Note: The page index is changed and the content updated appropriately.
10
n.
o. p. q.
Open the SalesOrders.aspx web form in Design view. Configure the SalesOrdersListView control, by using the SalesOrdersListView Smart Tag. Refresh the schema before configuring the control. Select the Grid layout and the Professional style for the SalesOrdersListView control.
11
r. s. t.
Enable paging for the SalesOrdersListView control. Disable editing and inserting a SalesOrderHeader item in the SalesOrdersListView control, by deleting the corresponding templates in Source view. Add a Select button to the AlternatingItemTemplate and ItemTemplate elements. Use the Button server control and place it at the top of the HTML tr element.
<td> <asp:Button ID="SelectButton" runat="server" Text="Select" CommandName="Select" /> </td>
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.
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
</asp:DetailsView>
<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>
b. c. d. e.
Open the SalesOrderItemsHistory.aspx content page in Design view. Add a Chart control named SalesOrderItemsHistoryChart. Set the Chart type to Bar by using the Smart Tag. Use the SalesOrderItemsEntityDataSource control as the data source, by using the DataSourceID property, the X values should come from the SalesOrderItems field, the Y values should come from the OrderDate field. Refresh the schema, after selecting the data source control. Modify the default chart area, by setting the X and Y axis titles to # Sales Order Items and Order Date. Use the ChartArea Collection Editor, accessible from the Properties window.
f.
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. b. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert.
13
c.
Note: The answers to the exercises are on the Course Companion CD.
14
15
b.
Add a RequiredFieldValidator control named QuantityRequiredFieldValidator to the user control. The RequiredFieldValidator control must validate the QuantityTextBox control, and display the text You must fill in the Quantity. as the error message, if the user leaves the text box empty. The display mode must be dynamic.
<asp:RequiredFieldValidator ID="QuantityRequiredFieldValidator" runat="server" ErrorMessage="You must fill in the Quantity." ControlToValidate="QuantityTextBox" Display="Dynamic"></asp:RequiredFieldValidator>
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.
d. e.
Save and close the user control. Build the project and fix any errors.
Note: Observe the Build succeeded message in the Build pane of the Output window.
16
b.
Modify the auto-implemented Quantity property, to get and set the productQuantity member variable.
c.
d.
e. f.
Save and close the ShoppingCart entity class. Build the project and fix any errors.
17
e. f.
Add an event handler for the RowUpdating event. Make the existing code in the Page_Load event handler execute only on first request by wrapping the existing code in the Page_Load event handler in an if statement.
if (!IsPostBack) { }
g.
private void BindData() { List<ShoppingCart> cart = (List<ShoppingCart>) Session["_cart"]; gvCart.DataSource = cart; gvCart.DataBind(); }
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.
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
o.
Append code to the gvCart_RowUpdating method, for resetting the edit index and bind the data by using the BindData method.
p. q.
Save and close the ShoppingCart code-behind file. Build the project and fix any errors.
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.
d.
e.
ReadOnly="true"
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>
19
b. c.
Add an event handler for the PageIndexChanging event. 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 (((GridView) sender).EditIndex != -1) { // Cancel paging operation e.Cancel = true; // Display error message int newPageIndex = e.NewPageIndex + 1; lblMessage.Text = "Update the item before moving to page " + newPageIndex.ToString(); } else { // Clear message text lblMessage.Text = ""; // Set page index ((GridView) sender).PageIndex = e.NewPageIndex; BindData(); }
d. e.
Save and close the ShoppingCart files. Build the project and fix any errors.
Note: Observe how the Quantity and Total Price columns are updated. f. g. h. i. On the Shopping Cart page, click Continue Shopping. On the Home page, in the Product Categories list, click Cranksets, and then click Submit. On the Products page, in the Cranksets list, click HL Crankset. On the Product Detail page, click Order.
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. j. On the Shopping Cart page, in the GridView pager, click 2.
Note: Observe that the page index is changed and the content updated appropriately.
20
k. l.
21
n.
o. p. q.
Open the SalesOrders.aspx web form in Design view. Configure the SalesOrdersListView control, by using the SalesOrdersListView Smart Tag. Refresh the schema before configuring the control. Select the Grid layout and the Professional style for the SalesOrdersListView control.
22
r. s. t.
Enable paging for the SalesOrdersListView control. Disable editing and inserting a SalesOrderHeader item in the SalesOrdersListView control, by deleting the corresponding templates. Add a Select button to the AlternatingItemTemplate and ItemTemplate elements. Use the Button server control and place it at the top of the HTML tr element.
<td> <asp:Button ID="SelectButton" runat="server" Text="Select" CommandName="Select" /> </td>
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.
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>
23
</asp:DetailsView>
<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>
b. c. d. e.
Open the SalesOrderItemsHistory.aspx content page in Design view. Add a Chart control named SalesOrderItemsHistoryChart. Set the Chart type to Bar by using the Smart Tag. Use the SalesOrderItemsEntityDataSource control as the data source, by using the DataSourceID property, the X values should come from the SalesOrderItems field, the Y values should come from the OrderDate field. Refresh the schema, after selecting the data source control. Modify the default chart area, by setting the X and Y axis titles to # Sales Order Items and Order Date. Use the ChartArea Collection Editor, accessible from the Properties window.
f.
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. b. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert.
24
c.
Note: The answers to the exercises are on the Course Companion CD.
Lab b Instructions: Optim mizing Data Managem ment for Web Forms
25
L 8B: Optimiz Lab zing Da ata Man nageme ent for Web Forms
Note: You can perform tasks in this lab either e by using Visual Basic or o Visual C# pr rogramming language. If you y are using Visual V Basic as your program mming languag ge, refer to the e steps provide ed in the Section 1 of the lab do ocument. If you u are using Vis sual C# as your programmin ng language, re efer to the steps provided p in Sec ction 2 of the lab document.
O Objectives
After completin ng this lab, you u will be able to: t Manage da ata by using AS SP.NET Dynam mic Data.
In ntroduction n
In n this lab, you will w develop th he administration section of the website by using variou us ASP.NET dat ta so ource controls and by using the ASP.NET Dynamic D Data framework.
26
Lab b Instructions: Optim mizing Data Managem ment for Web Forms
Th he AdventureW Works Sales team has reques sted the addition of an administration section to the we ebsite so th hat they can manage m information, as well as a provide a dashboard to se enior management. As a firs st step to oward this end d, you need to create a set of f web form pa ages that will enable e the Sale es team to do the fo ollowing: View, add, edit, and delet te products View sales orders View and edit customer details
In n this lab, you will w develop th he administration section of the website by using the AS SP.NET Dynam mic Data framework.
27
Section 1: Visual Basic Exercise 4: Managing Data by Using ASP.NET Dynamic Data
The main tasks in this exercise are as follows: 1. 2. 3. 4. Create a new ASP.NET Dynamic Data web application. Add a new ADO.NET Entity Data Model. Register the object context. Run the application.
b.
28
j. k. l.
The page displays the List view that contains the data of customer sales order headers. Filter the sales order headers by entries that have the OnlineOrderFlag column set to True. 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. o. p. q. r. s. t. Create a new customer, by clicking Insert new item. Save the new customer, with empty fields, and then cancel the new customer. 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. Edit the last customer displayed. The page displays the Edit view that contains the data for the selected row from the Customers table. Cancel the edit and close Windows Internet Explorer. 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. b. c. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. In the Revert Virtual Machine dialog box, click Revert.
29
b.
30
g. h. i. j. k. l.
Sort the customers by the LastName column. The page displays the List view that contains the data of customers, sorted by last name. View the sales order headers associated with the second customer displayed from the top. The page displays the List view that contains the data of customer sales order headers. Filter the sales order headers by entries that have the OnlineOrderFlag column set to True. 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. o. p. q. r. s. t. Create a new customer, by clicking Insert new item. Save the new customer, with empty fields, and then cancel the new customer. 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. Edit the last customer displayed. The page displays the Edit view that contains the data for the selected row from the Customers table. Cancel the edit and close Windows Internet Explorer. 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. b. c. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. In the Revert Virtual Machine dialog box, click Revert.
Note: The answers to the exercises are on the Course Companion CD.
Module 9
Lab Instructions: Ensuring Quality by Debugging, Unit Testing, and Refactoring
Contents:
Exercise 1: Configuring Error Handling Exercise 2: Debugging Code Exercise 3: Logging Exercise 4: Creating Unit Tests Exercise 5: Implementing the Test-First/Test-Driven Development Methodology 4 5 8 12 15
O Objectives
After completin ng this lab, you u will be able to: t Configure error e handling. Debug code. Configure logging. t tests. Create unit Implement the test-first/t test-driven dev velopment me ethodology.
In ntroduction n
In n this lab you will w configure error e handling g in a web application, debug g code to iden ntify errors, log g errors to o the event log g, and create and a run unit te ests.
Adventure Works has request ted that you lo ook into how you y can improve the quality of the coding. As a fir rst step toward d this end, you ur team has de etermined you should look in nto the following functionality and fe eatures of Visual Studio 2010 0 and the .NET T Framework: e handling Configure error Debug code Log errors Implement a code-first development methodology st-driven deve elopment meth hodology Implement a test-first/tes
f Task 3: Modify Web.config to redirect to the generic error page when an unhandled
error occurs
1. 2. Open the Web.config file. Add the following markup to the system.web element.
<customErrors mode="On" defaultRedirect="~/CustomErrorPage.aspx"/>
3. 4. 5.
Save and close the Web.config file. Run the application. Click the Submit button. Note: The custom error page is displayed.
6. 7.
Close Windows Internet Explorer. Close Visual Studio 2010. Results: After this exercise, you should have created a custom error page for unhandled exceptions.
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. 3. In Visual Studio, place a breakpoint in Default.aspx.cs or Default.aspx.vb on the following line of code.
[Visual C#] string category = lbCategories.SelectedValue; [Visual Basic] Dim category As String = lbCategories.SelectedValue
4.
Note: Visual Studio is now shown, with the breakpoint highlighted. 6. Press F10 to step over the line of code that sets the local variable category to the selected value of the list.
7. 8. 9.
Hover the mouse over category and notice it is an empty string, which cannot be parsed by the code in the Products page. Press SHIFT+F5 to end debugging. 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. 10. Run the application in Debug mode. 11. Click the Submit button. Note: Visual Studio is now shown, with the breakpoint highlighted. 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. Note: The Products page is displayed, showing a list of Mountain Bikes. 15. Close Windows Internet Explorer. 16. Remove all breakpoints by pressing CTRL+SHIFT+F9.
f Task 4: Debug a java script error using breakpoints and single stepping
Run the application in Debug mode. Note: The Home page is displayed.
for (i = 0; i < 3;
i++) {
4.
Click the Back button in your browser. Note: The Home page is displayed.
5.
Click the Select First button. Note: Visual Studio is now shown, with the breakpoint highlighted.
6. 7. 8. 9.
Press F10 to step over the statements of code, until a message box is displayed. In the Message from webpage message box, click OK. Repeat the previous two steps twice. Press F5. Note: The Products page is displayed.
10. Close Windows Internet Explorer. 11. Close Visual Studio 2010. Results: After this exercise, you should have experience debugging Visual C# or Visual Basic, and java script code.
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.
3.
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 If Not Request("id") Is Nothing Then categoryID = Request("id") End If 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
4.
5.
Open the Event Viewer and show the Application log entry. If necessary, sort the Application log entries by date and time.
10
6. 7.
f Task 3: Set the logging level in the Web.config file to allow for future debugging
1. 2. Open the Web.config file. In the opening compilation tag, ensure that the value of the debug attribute is set to true.
<compilation debug="true" ...>
3.
3.
11
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
4.
Build the project and fix any errors. In the AdventureWorks Microsoft Visual Studio window, on the Build menu, click Build AdventureWorks.
5.
Close Visual Studio 2010. In the AdventureWorks Microsoft Visual Studio window, click the 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
3. 4.
Save Calculator.cs or Calculator.vb. Build the project and fix any errors.
2.
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
4.
5.
// TODO: Initialize to an appropriate value appropriate value appropriate value to an appropriate value
[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
2.
14
[TestMethod()] public void AddTest() { Calculator target = new Calculator(); int p1 = 2; // TODO: Initialize to an int p2 = 3; // TODO: Initialize to an int expected = 6; // TODO: Initialize int actual; actual = target.Add(p1, p2); Assert.AreEqual(expected, actual); }
// TODO: Initialize to an appropriate value appropriate value appropriate value to an appropriate value
[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. 2. Close Visual Studio 2010.
Results: After this exercise, you should have experience creating unit tests for existing methods.
15
16
Dim expected As Integer = 6 Dim unexpected As Integer = 5 Dim actual As Integer = target.Multiply(3, 2) Assert.AreEqual(expected, actual) Assert.AreNotEqual(unexpected, actual) End Sub <TestMethod()> Public Sub ClassSubtractMethodTest() Dim target As New Calculator() Assert.IsNotNull(target) Dim expected As Integer = 1 Dim unexpected As Integer = 6 Dim actual As Integer = target.Subtract(3, 2) Assert.AreEqual(expected, actual) Assert.AreNotEqual(unexpected, actual) End Sub
3.
3.
17
Note: In the Test Result window, you can see that the ClassSubtractMethodTest test failed. 4. Close the CalculatorTest.cs or CalculatorTest.vb file.
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
3.
f Task 7: Turn off the virtual machine and revert the changes
1. 2. 3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert.
18
4.
In the Revert Virtual Machine dialog box, click Revert. Results: After this exercise, you should have experience creating tests first, and then implementing methods.
Module 10
Lab Instructions: Securing a Web Application
Contents:
Exercise 1: Configuring ASP.NET Membership and Roles Exercise 2: Authentication Exercise 3: Authorization 4 6 10
O Objectives
After completin ng this lab, you u will be able to: Create and manage users s and roles by using the ASP P.NET Web Site e Administratio on Tool ntrol Implement the Login con ess rules Create acce
In ntroduction n
In n this lab you will w learn how to use the ASP P.NET Web Site Administration Tool, authe enticate users by us sing the Login n control. You will also imple ement custom logic to expire 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.
Th he Adventure Works Sales te eam has reque ested that area as of the websi ite be protecte ed so that only y au uthenticated users u are able to t access the secure s areas of f the site. Th his means you must configure ASP.NET Membership, cre eate users, cre eate and assign n roles, implem ment au uthentication and a authorizat tion, implement Login contr rols, and test th he web applica ation.
User Name
Mary 3. 4. 5.
Password
Pa$$w0rd
Security Question
Security Answer
Cat
Click Create User. Click Continue. Fill out the information to create a new user, using the following information.
User Name
John 6. 7.
Password
Pa$$w0rd
E-mail
[email protected]
Security Question
High School
Security Answer
Central
2. 3. 4. 5.
Click Enable roles. Click Create or Manage roles. In the New role name box, type Administration, and then click Add Role. In the New role name box, type Contributor, and then click Add Role.
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 selfclosing authentication tag.
<authentication mode="Forms"> <forms loginUrl="~/Account/Login.aspx" timeout="2880" /> </authentication>
<asp:TextBox ID="UserName" runat="server" CssClass="textEntry"></asp:TextBox> <asp:RequiredFieldValidator ID="UserNameRequired" runat="server" ControlToValidate="UserName" CssClass="failureNotification" ErrorMessage="User Name is required." ToolTip="User Name is required." 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.
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());
// Did we find the user? if (user != null) { // Check if the user password has expired after 90 days if (DateTime.Now.Subtract(user.LastPasswordChangedDate).TotalDays >= 90) { Response.Redirect("PasswordExpired.aspx"); } else { // Authenticate user if (Membership.ValidateUser(LoginUser.UserName.Trim(), LoginUser.Password.Trim())) e.Authenticated = true; } } [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()) ' Did we find the user? If Not user Is Nothing Then ' Check if the user password has expired after 90 days If DateTime.Now.Subtract(user.LastPasswordChangedDate).TotalDays >= 90 Then Response.Redirect("PasswordExpired.aspx") Else ' Authenticate user If Membership.ValidateUser(LoginUser.UserName.Trim(), LoginUser.Password.Trim()) Then e.Authenticated = True End If End If End If End Sub
4. 5. 6.
Build the solution. Close the Login.aspx code-behind file. Close the Login.aspx Web Form.
3.
</mailSettings> </system.net>
4. 5.
Build the solution and fix any errors. Close Visual Studio 2010.
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
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.
3.
4. 5. 6.
Save and close the Home.aspx file. Open the Web.config file. 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>
7.
11
2. 3. 4.
Run the application. On the Home page, click Log In. On the Login page, click Forgot Password?. Note: You have access to the EmailPassword Web Form as an anonymous user.
5.
Click the Back button in your browser. Note: The Login is displayed.
6. 7.
Log on using John as the username and Pa$$w0rd as the password. Access the Contributors/Home.aspx Web Form by typing in the following URL in the Internet Explorer Address bar, and then press ENTER.
[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. 8. Log on using Mary as the username and Pa$$w0rd as the password. Note: You are now redirected to the Contributors/Home.aspx Web Form, because the user Mary is authorized to access the Contributors folder. 9. Close Windows Internet Explorer.
f Task 5: Turn off the virtual machine and revert the changes
1. 2. 3. 4. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. 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.
Module 11
Lab Instructions: Applying Master Pages and CSS
Contents:
Exercise 1: Modify a Master Page Exercise 2: Create a Nested Master Page Exercise 3: Integrate a Master Page Exercise 4: Implement Control Skins Exercise 5: Apply Styles and Themes 4 6 9 12 13
N Note: Tasks in this lab will be the same, re egardless of the programmin ng language yo our solution is s using.
O Objectives:
After completin ng this lab, you u will be able to: t Modify a master m page. Create nest ted master pag ges. Apply mast ter pages. Apply Them mes, Skins, and d Styles.
In ntroduction n
In n this lab, you will w first modif fy the existing master page for f the Advent tureWorks web bsite, add a ne ew Co ontentPlaceH Holder for the footer conten nt, and implem ment it in the About.aspx A pa age. You will th hen cr reate an area in the existing master page for f status mess sages and imp plement it for all a child pages. You w then create two control sk will kins and apply y them to cont trols in the exis sting website. You will also modify m ex xisting CSS sty yles, create two o themes for th he website bas sed on the exis sting styles, an nd implement one th heme in the Web.config W file e.
Adventure Works is redesigning their Webs site in a corpor rate 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 ou will also ad dd an application-wide location for reporting errors and sending mess sages to users. You ne eed to implem ment this messa aging location n consistently across a the app plication.
1. 2.
Close Windows Internet Explorer. Close Visual Studio 2010. 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.
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.
10
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(); } Master.StatusMessage = "You are on the Products page"; } [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" If Not Request("id") Is Nothing Then categoryID = Request("id") End If 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
11
4. 5. 6. 7. 8. 9.
Run the application by pressing CTRL+F5. On the Products page, scroll down to see the status message. Open the About page. On the About page, notice the status message. Close Windows Internet Explorer. Close Visual Studio 2010. 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
2.
3.
4.
Run the application. Note: Observe the light blue background color in the ListBox control.
5. 6.
Close Windows Internet Explorer. Close Visual Studio 2010. 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.
13
3.
14
4. 5.
Change the background color to Red, and close the Modify Style dialog box. Save and close the StyleB.css file.
6.
Remove the theme attribute and value from the Page directive.
Theme="Default"
7.
3.
f Task 7: Turn off the virtual machine and revert the changes
1. 2. 3. 4. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. 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.
Module 12
Lab Instructions: Developing Client-side Scripts and Services
Contents:
Exercise 1: Using jQuery Exercise 2: Using Advanced jQuery Exercise 3: Creating a WCF Service 4 7 9
O Objectives
After completin ng this lab, you u will be able to: Enable clien nt-side sorting g. Use jQuery selectors. uery visual effe ects. Embed jQu Create a WCF W Service and d invoke it usin ng the client-s side 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 will l also embed jQ Query visual effects e in your application, cr reate a WCF se ervice, and the en in nvoke it using the t client-side e code.
Adventure Works has designe ed a shopping cart applicatio on that allows the user to ad dd products into his or r her shopping g cart. After the products are e added, the user can click on o the Cart link to view the current c ite ems in the car rt. Yo ou have also been b requested d to display ad dvertisement in nformation ab bout the produ ucts when the users ho over the mous se over the pro oduct name. In n addition, you u must create a WCF service for retrieving pr roducts, and the service mus st be callable from f client-sid de code.
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.
7.
8. 9.
Close Windows Internet Explorer. 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>
3. 4.
Run the application. Select the Bike Stands product category, and then click Submit.
5. 6. 7. 8. 9.
Select the All-Purpose Bike Stand product. Add the product to the shopping cart. Continue shopping. Select the Bib-Shorts product category, and then click Submit. Select the Men's Bib-Shorts, L product.
10. Add the product to the shopping cart. 11. View the source for the rendered page. 12. Locate the gvCart GridView control, and note that the thead and tbody HTML elements are rendered.
<table cellspacing="0" rules="all" border="1" id="MainContent_gvCart" style="bordercollapse:collapse;"> <thead> <tr> <th scope="col">ID</th><th scope="col">Name</th><th scope="col">Price</th><th scope="col">Quantity</th> </tr> </thead><tbody> <tr> <td>879</td><td>All-Purpose Bike Stand</td><td>1</td><td>159</td> </tr> </tbody><tfoot>
13. Close the source window. 14. Click the ID column header. Note: Notice how the rows are sorted ascending according to the value of the ID column for the individual rows. 15. Close Windows Internet Explorer. 16. Close Visual Studio 2010. 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.
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>
5. 6.
Run the application. On the Products page, hover the mouse over the name of the product. Note: The custom advertisement message is displayed in the rightmost column.
7.
$(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"); }); }); jQuery.fn.fadeInFadeOut = function (speed) { $(this).fadeIn(speed, function () { $(this).fadeOut(speed); }); } $(document).ready(function () { $("a").mouseover(function () { $(this).closest("tr").find("div").fadeInFadeOut("slow"); }); }); </script>
2. 3.
Run the application. On the Products page, hover the mouse over the name of the product. Note: The custom advertisement message is displayed in the rightmost column, but now it closes after a short period.
4. 5.
Close Windows Internet Explorer. Close Visual Studio 2010. Result: After this exercise, you should be able to embed jQuery effects in your application.
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; } // Add more operations here and mark them with [OperationContract] [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()>
2.
10
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() Using db = New AdventureWorksEntities() Dim randomNumber = random.[Next](1, db.Products.Count() + 1) Dim randomProduct = (From p In db.Products Where p.ProductID = randomNumber Select New With {p.Name, p.ListPrice, p.ProductNumber}).FirstOrDefault() 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.
11
f Task 5: Invoke WCF service using client-side code from the master page
1. 2. Open the Site.Master master page. 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; }); }
4.
5.
Run the application. Note: The random product is displayed on the right side.
12
6.
f Task 6: Turn off the virtual machine and revert the changes
1. 2. 3. 4. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. 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.
Module 13
Lab Instructions: Implementing Advanced Ajax in a Web Application
Contents:
Exercise 1: Using Microsoft Ajax in an MVC Page Exercise 2: Using jQuery in an MVC View Exercise 3: Handling Events 4 7 9
Lab 13: Implem L menting Advanced Aja ax for th he A Adventu ureWorks Web b Applic cation
Adding the product catalog to the Adventu ureWorks webs site has been a success. Now w, you have be een as sked to enhance the usability of the catalo og. Management would M w like to display two Featured Product ts when a user clicks a produ uct category, to o en ncourage purc chases. In n addition, they y would like to o show all of th he products an nd product cat tegories on th he same page when th he user selects a category. To o do this, when a user clicks a category, yo ou will need to o load the prod ducts featured d dynamically, and w when the user clicks c the Subm mit button, yo ou will need to load all produ ucts. In n this lab, you will w explore th he features of jQuery and Aja ax in an MVC application. Yo ou will also exa amine th he different client events.
O Objectives
After completin ng this lab, stud dents will be able to: Dynamically load content t into a view using Microsoft t Ajax Library. t into a view using jQuery Aj jax. Dynamically load content vent handlers using jQuery Ajax. Add Ajax ev
In ntroduction n
In n this lab, you will w add Ajax libraries to the pages and ma aster page, and create a par rtial Ajax MVC view. Yo ou will also use e jQuery in an MVC view, an nd handle even nts using jQue ery.
[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#]
<% using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "productCategories" })) { %> <select size="4" id="CategoryID" name="CategoryID" style="height: 270px; width: 186px;"> <% foreach (var ProductCategory in Model) { %> <option value="<%= ProductCategory.ProductCategoryID %>"> <%= Html.Encode(ProductCategory.Name)%> </option> <% } %> </select> <div id="productCategories"> </div> <% } %>
[Visual Basic]
<% Using (Ajax.BeginForm(New AjaxOptions With {.UpdateTargetId = "productCategories" }))%> <select size="4" id="CategoryID" name="CategoryID" style="height: 270px; width: 186px;"> <% For Each ProductCategory In Model%> <option value="<%= ProductCategory.ProductCategoryID %>"> <%= Html.Encode(ProductCategory.Name)%> </option> <% Next%> </select> <div id="productCategories"> </div> <% End Using%>
[Visual Basic]
<h2> Product Catalog</h2> <label> Choose a category:</label> <br /> <% Html.RenderPartial("_AjaxProductCategories", Model)%>
4. 5.
Delete the existing markup in the Content1 Content control. Add the following markup to the Index view, at the top of the Content1 Content control.
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.ProductCategory >>"
[Visual Basic]
Inherits="System.Web.Mvc.ViewPage(Of IEnumerable (Of AdventureWorksMvc.ProductCategory))"
7. 8.
Build the solution and fix any errors. Close Visual Studio 2010.
Results: After this exercise, you should have added the product line to the index view using the Microsoft Ajax Library.
[Visual Basic]
Public Function FeaturedProducts(ByVal CategoryId As String) As ViewResult Dim id As Integer = Integer.Parse(CategoryId) Dim products = pr.GetProductsByCategory(id) Return View("_FeaturedProducts", products) End Function
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>
4. 5. 6.
Run the application. In Windows Internet Explorer, click Submit. In Windows Internet Explorer, in the Choose a category list, click Bib-shorts.
Note: The products for the chosen category are displayed below the list. 7. 8. Close Windows Internet Explorer. Close Visual Studio 2010.
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.
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(''); }); });
2.
Ensure that the Index view page matches the following. [Visual C#]
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<AdventureWorksMvc.Models.ProductCategory >>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Products </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2>
10
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]
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of IEnumerable (Of AdventureWorksMvc.ProductCategory))" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Products </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...');
11
$('.error').text(''); }); $('.log').ajaxComplete(function () { $(this).text(''); }); $('.error').ajaxError(function () { $(this).text('There was an error! Please try again later...'); }); }); </script> </asp:Content>
f Task 5: Turn off the virtual machine and revert the changes
1. 2. 3. 4. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. In the Revert Virtual Machine dialog box, click Revert.
Results: After this exercise, you should have used jQuery to provide feedback on the page.
Module 14
Lab Instructions: ASP.NET Deployments
Contents:
Exercise 1: Creating a Profile for Deploying a Web Application Project Using One-Click Publish Exercise 2: Creating a Web Deployment Package 4 7
Note: You can perform the ta N asks in this lab b by using eithe er Visual C# or Visual Basic c as your pr rogramming la anguage.
O Objectives
After completin ng this lab, you u will be able to: t Create a One-Click Publish P profile e. ment package. Create and deploy a web deploym
In ntroduction n
In n this lab, you will w create a profile p for depl loying 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.
AdventureWork ks is preparing to deploy the e application to o the different t servers for testing, staging, and de eployment. Yo ou will investig gate the differe ent methods of o deployment and the advan ntages and di isadvantages of o each.
Exercise 1: Creating a Profile for Deploying a Web Application Project Using One-Click Publish
The main tasks for this exercise are as follows: 1. 2. 3. 4. 5. 6. 7. Create a new ASP.NET web application. Create an ASP.NET Application Services database. Set the active build configuration. Specify which files and IIS settings to deploy. Specify which SQL Server scripts run during deployment. Update the connection string in the Web.config file by creating a transform file. Create a publish profile.
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. 3. Close Windows Internet Explorer.
6.
4. 5. 6.
f Task 6: Update the connection string in the Web.config file by creating a transform file
1. 2. 3. 4. 5. [Visual Basic] Show all files for the Deployment project in Solution Explorer. Expand the Web.config file. Open the Web.Release.config file. Examine and delete the block of comments that contains a connectionStrings element. 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. 6. Save and close the Web.Release.config file.
Note: If your hosting company advises you to allow untrusted certificates, select the Allow untrusted certificate check box. 3. 4. 5. 6. Enter the credentials for the local user admin. Select the Save password check box. Set the service URL to localhost. Set the site/application URL to Default Web Site/Deployment.
7. 8.
Save the profile and close the Publish Web dialog box. Close Visual Studio 2010.
Results: After this exercise, you should have created a profile to deploy your web application project using one-click publish.
2. 3.
Save and close the Web.config file. Run the application. Click the Log In link. Enter credentials for the user student with a password of Pa$$w0rd, and then log in. Close Windows Internet Explorer.
5. 6. 7. 8.
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
Active (Debug) is selected in the Configuration list. Only files needed to run this application is selected in the list in the Items to deploy (applies to all deployment methods) section. The Exclude generated debug symbols check box is cleared. The Exclude files from the App_Data folder check box is selected. The Include all databases configured in Package/Publish SQL tab check box is selected. The Create deployment package as a zip file check box is selected. The Location where package will be created box contains the following value.
obj\Debug\Package\Deployment.zip
4. 5.
In the IIS Web site/application name to use on the destination server box, type Default Web Site/Deployment. Save the changes.
9.
10. Set the database scripting options to Schema and Data. 11. Ensure that the AW-Deployment row is selected in the Database Entries list. 12. In the Connection string for destination database box, paste the copied value, Data Source=10264A-GEN-DEV\SQLEXPRESS;Initial Catalog=DeploymentTest;Integrated Security=True;Pooling=False.
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.
6.
10
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. 2. 3. 4. 5. 6. 7. 8. Open Internet Information Services (IIS) Manager as an administrator. In Control Panel, click System and Security, and then click Administrative Tools. Right-click Internet Information Services (IIS) Manager, and then click Run as administrator. In the User Account Control dialog box, in the Password box, type Pa$$w0rd, and then press ENTER. In Internet Information Services (IIS) Manager, expand 10264A-GEN-DEV (10264A-GENDEV\Admin), expand Sites, and then click Default Web Site. In the Actions pane, under Deploy, click Import Application. In the Import Application Package wizard, use the D:\Lab Files\CS\Lab 14\Starter\Exercise 02\Deployment\obj\Debug\Package\Deployment.zip or D:\Lab Files\VB\Lab 14\Starter\Exercise 02\Deployment\obj\Debug\Package\Deployment.zip package. Accept the default selected contents of the package.
9.
10. Accept the default application paths and connection strings. 11. Click Finish. 12. Close Internet Information Services (IIS) Manager.
Note: The Default.aspx page is displayed. It looks the same as it does when you run it in Visual Studio 2010.
f Task 10: Turn off the virtual machine and revert the changes
1. 2. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off.
11
3. 4.
In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. 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.
Module 15
Lab Instructions: Developing a Web Application by Using Silverlight
Contents:
Exercise 1: Creating a Silverlight Project Exercise 2: Creating a Silverlight WCF Service Exercise 3: Displaying Data by Using Silverlight Controls 5 6 8
O Objectives
After completin ng this lab, you u will be able to: t Create a Silverlight projec ct. Create a Silverlight WCF service. Display dat ta by using Silv verlight contro ols.
In ntroduction n
In n this lab, you will w learn how to add Silverlight to an exis sting Adventur reWorks web application. a Th he Si ilverlight application will be used to consu ume a WCF Ser rvice and displ lay the data by y using the Da ataGrid Si ilverlight contr rol.
So ome of AdventureWorks competitors are experiencing higher web tra affic than Adve entureWorks. M Management wants w to explor re the feasibilit ty of using RIA A technology to increase use er stickiness wh hen de eveloping the AdventureWo orks web site in n future. For th his purpose, yo ou have been tasked t with creating a simple prototyp pe. The resultin ng prototype should s look sim milar to the following screen nshot.
2. 3. 4.
Build the solution. Save the solution changes. Close Visual Studio 2010.
Results: After this exercise, you should have created a Silverlight project and also have become familiar with how to host a Silverlight project.
f Task 3: Create methods that return a list of product categories, and a list of products by
category
1. 2. 3. Delete the stub method DoWork from the code file. Import the System.Collections.Generic namespace. 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
5. 6.
Build the solution and fix any errors. Close Visual Studio 2010.
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.
Make the following property changes to the DataGrid control. Name: CategoriesDataGrid Height: 156 Width: 100 AutoGenerateColumns: False
5. 6.
From the Toolbox, drag a Silverlight DataGrid control to the right of the CategoriesDataGrid control on the page. Make the following property changes to the DataGrid control. Name: ProductsDataGrid Height: 300 Width: 370 AutoGenerateColumns: False
7. 8.
Drag two Silverlight Label controls onto the page. Position them directly above the two DataGrid controls. Make the following changes to the left-most Labels control. Name: CategoryLabel
9.
Make the following changes to the right-most Labels control. Name: ProductLabel Height: 14 Width: 100 Content: Products
10
Name="ProductsDataGrid" VerticalAlignment="Top" Width="370" /> <sdk:Label Height="14" HorizontalAlignment="Left" Name="CategoryLabel" VerticalAlignment="Top" Width="100" Margin="6,1,0,0" Content="Categories" /> <sdk:Label Height="14" HorizontalAlignment="Left" Margin="106,1,0,0" Name="ProductLabel" VerticalAlignment="Top" Width="100" Content="Products" /> </Grid> </UserControl>
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>
11
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 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_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) { } void productService_GetProductCategoriesCompleted(object sender, AdventureWorks.GetProductCategoriesCompletedEventArgs e) {
12
[Visual Basic]
Private Sub productService_GetProductCategoriesCompleted(ByVal sender As Object, ByVal e As AdventureWorks.GetProductCategoriesCompletedEventArgs) End Sub Private Sub productService_GetProductsByCategoryCompleted(ByVal sender As Object, ByVal e As AdventureWorks.GetProductsByCategoryCompletedEventArgs) 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
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
[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
The call to GetProductsByCategoryAsync returns to the productService_GetProductsByCategoryCompleted method, where the results returned by the service should be bound to the ItemsSource property of the grid.
[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#]
public partial class MainPage : UserControl { protected AdventureWorks.ProductServiceSLClient productService = new AdventureWorks.ProductServiceSLClient(); public MainPage() { InitializeComponent(); productService.GetProductCategoriesCompleted += new EventHandler<AdventureWorks.GetProductCategoriesCompletedEventArgs >(productService_GetProductCategoriesCompleted); productService.GetProductsByCategoryCompleted += new EventHandler<AdventureWorks.GetProductsByCategoryCompletedEventArg s>(productService_GetProductsByCategoryCompleted); productService.GetProductCategoriesAsync(); } private void CategoriesDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e) { AdventureWorks.ProductCategory category = CategoriesDataGrid.SelectedItem as AdventureWorks.ProductCategory; productService.GetProductsByCategoryAsync(category.ProductCategory ID); } void productService_GetProductsByCategoryCompleted(object sender, AdventureWorks.GetProductsByCategoryCompletedEventArgs e) { ProductsDataGrid.ItemsSource = e.Result;
15
[Visual Basic]
Partial Public Class MainPage Inherits UserControl Protected productService As New AdventureWorks.ProductServiceSLClient() Public Sub New() InitializeComponent() AddHandler productService.GetProductCategoriesCompleted , AddressOf productService_GetProductCategoriesCompleted AddHandler productService.GetProductsByCategoryCompleted , AddressOf productService_GetProductsByCategoryCompleted productService.GetProductCategoriesAsync() End Sub Private Sub CategoriesDataGrid_SelectionChanged(ByVal sender As System.Object, ByVal e As System.Windows.Controls.SelectionChangedEventArgs) Dim category As AdventureWorks.ProductCategory = TryCast(CategoriesDataGrid.SelectedItem, AdventureWorks.ProductCategory) productService.GetProductsByCategoryAsync(category.ParentProductCa tegoryID) End Sub Private Sub productService_GetProductCategoriesCompleted(ByVal sender As Object, ByVal e As AdventureWorks.GetProductCategoriesCompletedEventArgs) CategoriesDataGrid.ItemsSource = e.Result End Sub Private Sub productService_GetProductsByCategoryCompleted(ByVal sender As Object, ByVal e As AdventureWorks.GetProductsByCategoryCompletedEventArgs) ProductsDataGrid.ItemsSource = e.Result End Sub End Class
f Task 6: Bind the data returned from the services to the grids
1. 2. Set AdventureWorksSLTestPage.aspx as the start page. Run the application. Note: It might take a while to load the data from the WCF service. 3. Select the Bib-Shorts category. Note: Notice how the Products list is populated with all the products for the selected category.
16
4. 5.
f Task 7: Turn off the virtual machine and revert the changes
1. 2. 3. 4. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. 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.
Module 1
Lab Answer Key: Overview of Web Application Architecture and Design
Contents:
Exercise 1: Exploring the Adventure Works Website Exercise 2: Comparing Web Forms and MVC Exercise 3: Working with the Request Life Cycle 2 5 6
Open the AdventureWorks solution at the following location. Programming Language Microsoft Visual C# Microsoft Visual Basic a. b. Location D:\Lab Files\CS\Lab 01\Starter\WebForms D:\Lab Files\VB\Lab 01\Starter\WebForms
In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or press CTRL+SHIFT+O. 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.
Continue shopping. In the http://localhost:xxxx/ShoppingCart.aspx Windows Internet Explorer window, click Continue Shopping.
Place the order. In the http://localhost:xxxx/ShoppingCart.aspx Windows Internet Explorer window, click Place Order.
Open the Default.aspx Web Form in Code view. In Solution Explorer, right-click Default.aspx, and then click View Code.
3.
Place a breakpoint at the beginning of the Page_Load method. In the Default.aspx.cs or Default.aspx.vb window, locate the Page_Load method, click the first line of code, and then press F9.
4.
Switch to Windows Internet Explorer. On the Windows taskbar, click http://localhost:xxxx/ThankYou.aspx Windows Internet Explorer.
5.
Open the Home page. In the http://localhost:xxxx/ThankYou.aspx Windows Internet Explorer window, on the menu, click Home.
Note: The debugger reaches your breakpoint in the Page_Load method. 6. Step through the web application startup until you reach the end of Page_Load method. a. b. On the Debug menu, click Step Over, or press F10. [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. 8. Close Windows Internet Explorer. In the Home Page Windows Internet Explorer window, on the menu, click the Close button.
2.
On the Start menu of 10264A-GEN-DEV, point to All Programs, click Microsoft Visual Studio 2010, and then click Microsoft Visual Studio 2010.
Open the AdventureWorksMvc solution at the following location. Programming Language Microsoft Visual C# Microsoft Visual Basic a. b. Location D:\Lab Files\CS\Lab 01\Starter\MVC D:\Lab Files\VB\Lab 01\Starter\MVC
In the Microsoft Visual Studio window, on the File menu, click Open Project, or press CTRL+SHIFT+O. 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.
Notice the methods that are available, and the way they relate to the actions that are available to the user. In the HomeController.cs or HomeController.vb window, notice the Index and About action methods.
3.
Close the HomeController.cs or HomeController.vb file. In the HomeController.cs or HomeController.vb window, click the Close button.
4.
5.
Place a breakpoint at the beginning of the Application_Start method. In the Global.asax.cs or Global.asax.vb window, locate the Application_Start method, click the first line of code, and then press F9.
6.
Run the AdventureWorksMvc solution in Debug mode. In the AdventureWorksMvc Microsoft Visual Studio window, on the Debug menu, click Start Debugging, or press F5.
Note: The debugger reaches the breakpoint in the Application_Start method. Examine the static/Shared RegisterRoutes method. a. In the Global.asax.cs or Global.asax.vb window, locate the RegisterRoutes method above the Application_Start method. b. 7. Notice how the MapRoute method is used to register the Default route to map to the Home controller and the Index action method.
Step through the web application startup until you reach the last line of code in the Index action method of the Home controller.
a. b.
On the Debug menu, click Step Over, or press F10. [Visual C#] Repeat step a five times. [Visual Basic] Repeat step a six times.
8.
Continue the web application. On the Debug menu, click Continue, or press F5.
Note: The URL displayed in the address bar of Internet Explorer does not include the name of the page (Index.aspx) displayed. 9. Close Windows Internet Explorer. In the Welcome to AdventureWorks Windows Internet Explorer window, on the menu, click the Close button.
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. 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.
Examine the markup in the Default.aspx Web Form. a. b. In Solution Explorer, double-click Default.aspx. 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 Microsoft C# Microsoft Visual Basic 2. Location D:\Lab Files\CS\Lab 01\Starter\MVC D:\Lab Files\VB\Lab 01\Starter\MVC
Examine the code in the HomeController.cs or HomeController.vb code file. In the HomeController.cs or HomeController.vb window, notice the code in the Index and About action methods, including how a view is returned.
3.
Examine the markup in the Index.aspx page. a. b. In Solution Explorer, expand Views, expand Home, and then double-click Index.aspx. In the Index.aspx window, notice the markup, including the use of a master page, the Content controls, the pure select and input HTML controls, and the Html.BeginForm and Html.Encode MVC helper methods.
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.
View the Default.aspx Web Form. If not already open and displayed, in Solution Explorer, double-click Default.aspx.
3. 4.
Locate the control with the label ASP:Content, which has the ContentPlaceHolderID property set to MainContent. Add the following Label control markup before any other content in the Content control.
<asp:Label ID="lblAdvertisement" runat="server" />
5.
View the code-behind file for the Default Web Form. If not already open and displayed, in Solution Explorer, right-click Default.aspx, and then click View Code.
6.
In the Page_Load method, add the following code at the beginning of the method. [Visual C#]
lblAdvertisement.Text = "My advertisement here";
[Visual Basic]
lblAdvertisement.Text = "My advertisement here"
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. 8. Close Windows Internet Explorer. 9. In the Home Page Windows Internet Explorer window, on the menu, click the Close button.
In the AdventureWorks Microsoft Visual Studio window, click the Close button.
Open the Views\Home\Index.aspx view. In Solution Explorer, expand Views, expand Home, and then double-click Index.aspx.
3. 4.
Locate the Content control with the ContentPlaceHolderID property value of MainContent. Add the following code before any content in the Content control. [Visual C#]
<p><%= ViewData["Advertisement"] %></p>
[Visual Basic]
<p><%: ViewData("Advertisement") %></p>
5.
Open the file Controllers\HomeController.cs or Controllers\HomeController.vb. In Solution Explorer, expand Controllers, and then double-click HomeController.cs or HomeController.vb.
6. 7.
Locate the Index method in the file. Add the following code at the beginning of the Index method. [Visual C#]
ViewData["Advertisement"] = "My advertisement here";
[Visual Basic]
ViewData("Advertisement") = "My advertisement here"
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. 9. Close Windows Internet Explorer. In the Welcome to AdventureWorks Windows Internet Explorer window, on the menu, click the Close button.
10. Close Visual Studio 2010. In the AdventureWorksMvc Microsoft Visual Studio window, click the Close button.
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. 3. 4.
In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. In the Revert Virtual Machine dialog box, click Revert.
Module 2
Lab Answer Key: Designing a Web Application
Contents:
Exercise 1: Reviewing the Adventure Works Website Structure Exercise 2: Redesign the AdventureWorks Website Exercise 3: Add MVC Capabilities to the AdventureWorks Website 2 2 4
Open the AdventureWorks solution at the following location. Programming Language Location Microsoft Visual C# Microsoft Visual Basic a. b. D:\Lab Files\CS\Lab 02\Solution\Exercise 01 D:\Lab Files\VB\Lab 02\Solution\Exercise 01
In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or press CTRL+SHIFT+O. 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: Examine the code and markup location and purpose f Analyze the solution and determine its intent and structure.
a. b. Expand and look at the content of various folders, Account, DataAccessLayer, and Styles. Look at the various files in the root folder, including the Web Forms, master page, Global Application class, Entity Data Model, and Web.config file(s).
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.
Open the AdventureWorks solution at the following location. Programming Language Microsoft Visual C# Microsoft Visual Basic a. b. Location D:\Lab Files\CS\Lab 02\Starter\Exercise 03 D:\Lab Files\VB\Lab 02\Starter\Exercise 03
In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or press CTRL+SHIFT+O. 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.
Add references to the System.Web.MVC and System.Web.Routing assemblies to the project. a. b. c. In Solution Explorer, right-click AdventureWorks, and then click Add Reference. Click .NET. In the list, click System.Web.MVC, press and hold down CTRL, click System.Web.Routing, and then click OK.
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. In Solution Explorer, double-click Web.config.
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> ... <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.
<compilation ... targetFramework="4.0"> <assemblies> ... </assemblies> </compilation>
b.
c.
d.
Add opening and closing pages tags, just before the closing system.web tag.
e.
f.
g.
Add opening and closing httpHandlers tags, just before the closing system.web tag.
<httpHandlers> </httpHandlers> </system.web>
h.
i.
j.
k.
Add opening and closing runtime tags, just before the closing configuration tag.
<runtime> </runtime> </configuration>
l.
3.
Save the Web.config file. In the Web.config window, on the File menu, click Save Web.config, or press CTRL+S.
4.
<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"/>
<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> <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"/>
10
a. b.
In Solution Explorer, double-click Global.asax. In the Global.asax.cs or Global.asax.vb window, at the very top, type the following code.
[Visual C#] using System.Web.Mvc; using 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}",
11
New With {.controller = "Home", .action = "Index", .id = ""} ) End Sub
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 = "" } defaults ); }
// Parameter
[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
3.
[Visual Basic] Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs) RegisterRoutes(RouteTable.Routes) End Sub
In the Global.asax.cs or Global.asax.vb window, in the Application_Start method, type the following code.
[Visual C#] RegisterRoutes(RouteTable.Routes);
[Visual Basic]
12
RegisterRoutes(RouteTable.Routes)
4.
Save the Global.asax file. In the Global.asax.cs or Global.asax.vb window, on the File menu, click Save Global.asax.cs or Save Global.asax.vb, or press CTRL+S.
In the AdventureWorks.csproj - Notepad or AdventureWorks.vbproj - Notepad window, locate the ProjectTypeGuids element at the top of the project file.
[Visual C#] <ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3bf4b-00c04f79efbc}</ProjectTypeGuids>
3.
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>
13
<ProjectTypeGuids>{F85E285D-A4E0-4152-9332-AB1D724D3325};{349c5851-65df-11da9384-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-938400065b846f21};{F184B08F-C81C-45F6-A57F-5ABD9991F28F}</ProjectTypeGuids> ...
4.
Save the project file. In the AdventureWorks.csproj - Notepad or AdventureWorks.vbproj - Notepad window, on the File menu, click Save, or press CTRL+S.
5.
Reload the AdventureWorks project. In the File Modification Detected dialog box, click the Reload button.
6.
Test the new project type by opening the Add New Item dialog box. In Solution Explorer, right-click AdventureWorks, point to Add, and then click New Item, or press CTRL+SHIFT+A. In the Add New Item - AdventureWorks dialog box, notice the addition of the MVC2 project item templates. In the Add New Item - AdventureWorks dialog box, click Cancel.
7.
Close Visual Studio 2010. In the AdventureWorks Microsoft Visual Studio window, click the Close button.
f Task 6: Turn off the virtual machine and revert the changes
1. 2. 3. 4. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. In the Revert Virtual Machine dialog box, click Revert.
Module 3
Lab Answer Key: Developing MVC Models
Contents:
Exercise 1: Exploring the AdventureWorks Database Exercise 2: Adding an ADO.NET Entity Data Model Exercise 3: Model Data Validation 2 4 10
Open the AdventureWorksMvc solution at the following location. Programming Language Location Visual C# Visual Basic a. b. D:\Lab Files\CS\Lab 03\Starter\Exercise 01 D:\Lab Files\VB\Lab 03\Starter\Exercise 01
In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or press CTRL+SHIFT+O. 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.
e.
Open the Customer (SalesLT) table in the Table Designer. Right-click Customer (SalesLT), and then click Open Table Definition.
3. 4.
Examine the schema of the table. Close the Table Designer. In the SalesLT.Customer: Table(10264a-gen-dev\sqlexpress.AdventureWorksLT2008R2) window, click the Close button.
Note: The relationship between the Customer and CustomerAddress table is one-to-many, which means that a single customer can have multiple addresses.
2.
Close the Database Designer and do not save the diagram. a. b. In the 10264A-GEN-DEV\Student.Diagram1: Diagram(10264a-gevdev\sqlexpress.AdventureWorksLT2008R2) window, click the Close button. In the Microsoft Visual Studio dialog box, click No.
3.
Close Visual Studio 2010. In the AdventureWorksMvc Microsoft Visual Studio window, click the Close button.
Open the AdventureWorksMvc solution at the following location. Programming Language Visual C# Visual Basic Location D:\Lab Files\CS\Lab 03\Starter\Exercise 02 D:\Lab Files\VB\Lab 03\Starter\Exercise 02
a. b.
In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or press CTRL+SHIFT+O. 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. b. c. d. 2.
In Solution Explorer, right-click Models, point to Add, and then click New Item. In the Add New Item AdventureWorksMvc dialog box, in the left pane, click Data. In the middle pane, click ADO.NET Entity Data Model, in the Name box, type AdventureWorks.edmx, and then click Add. In the Entity Data Model Wizard, on the Choose Model Contents page, click Generate from database, and then click Next.
Use the existing AdventureWorksLT2008ConnectionString connection string to connect to the database, and save the connection settings in the Web.config file as AdventureWorksEntities.
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.
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]
Private db As New AdventureWorksEntities
a.
In the BlogRepository.cs or BlogRepository.vb window, at the top of the BlogRepository class, type the following code. [Visual C#]
private AdventureWorksEntities db = new AdventureWorksEntities();
[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
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
[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); } public void UpdateBlog(Blog blog) { db.Blogs.ApplyCurrentValues(blog); } public void DeleteBlog(Blog blog) { db.Blogs.DeleteObject(blog); } public void Save() { db.SaveChanges(); }
[Visual Basic]
10
Public Sub AddBlog(ByVal blg As Blog) db.Blogs.AddObject(blg) End Sub Public Sub UpdateBlog(ByVal blg As Blog) db.Blogs.ApplyCurrentValues(blg) End Sub Public Sub DeleteBlog(ByVal blg As Blog) db.Blogs.DeleteObject(blg) End Sub Public Sub Save() db.SaveChanges() End Sub
7.
Save all modified files. In the AdventureWorksMvc Microsoft Visual Studio window, on the File menu, click Save All, or press CTRL+SHIFT+S.
8.
Close Visual Studio 2010. In the AdventureWorksMvc Microsoft Visual Studio window, click the Close button.
Open the AdventureWorksMvc solution at the following location. Programming Language Location Visual C# Visual Basic a. b. D:\Lab Files\CS\Lab 03\Starter\Exercise 03 D:\Lab Files\VB\Lab 03\Starter\Exercise 03
In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or press CTRL+SHIFT+O. 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.
Make the Blog class partial, by prefixing with the keyword partial/Partial. [Visual C#]
11
[Visual Basic]
Partial Public Class Blog
3.
[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
[Visual Basic]
Public Class Blog_MetaData <DisplayName("Blog ID")> Public Property BlogID As Object
12
<DisplayName("Date Posted")> <DisplayFormat(DataFormatString:="{0:d}")> Public Property DatePosted As Object <Required()> Public Property Title As Object <Required()> <DisplayName("Blog Entry")> Public Property BlogEntry As Object End Class
In the Blog.cs or Blog.vb window, add the following code at the bottom. [Visual C#]
public class Blog_MetaData { [DisplayName("Blog ID")] public object BlogID { get; set; } [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]
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 <Required()> <DisplayName("Blog Entry")> Public Property BlogEntry As Object End Class
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
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
3.
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.
4.
Close Visual Studio 2010. In the AdventureWorksMvc Microsoft Visual Studio window, click the Close button.
f Task 4: Turn off the virtual machine and revert the changes
1. 2. 3. 4. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. In the Revert Virtual Machine dialog box, click Revert.
Module 4
Lab Answer Key: Developing MVC Controllers
Contents:
Exercise 1: Creating an MVC Controller Exercise 2: Adding code to list the existing blog entries Exercise 3: Adding code to create a new blog entry Exercise 4: Adding code to edit a blog entry Exercise 5: Adding code to delete a blog entry 2 3 7 10 14
Open the AdventureWorksMvc solution from the following location. Programming Language Visual C# Visual Basic a. b. Location D:\Lab Files\CS\Lab 04\Starter\Exercise 01 D:\Lab Files\VB\Lab 04\Starter\Exercise 01
In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or press CTRL+SHIFT+O. 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.
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 Function Index() As ActionResult Return View() End Function End Class End Namespace
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.
5.
Close Visual Studio 2010. In the AdventureWorksMvc Microsoft Visual Studio window, click the Close button.
Open the AdventureWorksMvc solution from the following location. Programming Language Visual C# Location D:\Lab Files\CS\Lab 04\Starter\Exercise 02
In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or press CTRL+SHIFT+O. 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.
a. b.
In Solution Explorer, expand Controllers, and then double-click BlogController.cs or BlogController.vb. In the BlogController code file, insert the following code at the top of the file.
[Visual C#] using AdventureWorksMvc.Models;
2.
Declare and instantiate a private BlogRepository object at the top of the BlogController class.
[Visual C#] private BlogRepository blogRepository = new BlogRepository();
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
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);
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
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) If blogEntry Is Nothing Then Return RedirectToAction("Index") End If 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); }
Dim blogEntry = blogRepository.GetBlog(id) If blogEntry Is Nothing Then Return RedirectToAction("Index") End If Return View(blogEntry) End Function
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.
5.
Close Visual Studio 2010. In the AdventureWorksMvc Microsoft Visual Studio window, click the Close button.
Open the AdventureWorksMvc solution from the following location. Programming Language Visual C# Visual Basic a. b. Location D:\Lab Files\CS\Lab 04\Starter\Exercise 03 D:\Lab Files\VB\Lab 04\Starter\Exercise 03
In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or press CTRL+SHIFT+O. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab 04\Starter\Exercise 03\AdventureWorksMvc.sln or D:\Lab Files\VB\Lab 04\Starter\Exercise 03\AdventureWorksMvc.sln and then click Open.
a. b.
In Solution Explorer, expand Controllers, and then double-click BlogController.cs or BlogController.vb. In the BlogController code file, add the following method to the BlogController class.
[Visual C#]
2.
Add code to the Create action method to return an empty ActionResult, to the view.
[Visual C#] return View();
3.
Verify that the final Create action method matches the following code:
[Visual C#] public ActionResult Create() { return View(); }
[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(); TempData["ConfirmationMessage"] = blog.Title + " has been added."; return RedirectToAction("Index"); } catch (Exception) { return View(blog); };
[Visual Basic] If ModelState.IsValid Then Try blg.DatePosted = DateTime.Now blogRepository.AddBlog(blg) blogRepository.Save() TempData("ConfirmationMessage") = blg.Title & " has been added" 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(); TempData["ConfirmationMessage"] = blog.Title + " has been added."; return RedirectToAction("Index"); } catch (Exception) { return View(blog); }; }
[Visual Basic] <HttpPost()> Function Create(ByVal blg As Blog) As ActionResult If ModelState.IsValid Then
10
Try blg.DatePosted = DateTime.Now blogRepository.AddBlog(blg) blogRepository.Save() TempData("ConfirmationMessage") = blg.Title & " has been added" Return RedirectToAction("Index") Catch Return View(blg) End Try End If Return View(blg) End Function
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.
5.
Close Visual Studio 2010. In the AdventureWorksMvc Microsoft Visual Studio window, click the Close button.
Open the AdventureWorksMvc solution from the following location. Programming Language Visual C# Visual Basic a. b. Location D:\Lab Files\CS\Lab 04\Starter\Exercise 04 D:\Lab Files\VB\Lab 04\Starter\Exercise 04
In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or press CTRL+SHIFT+O. 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 Basic]
11
a. b.
In Solution Explorer, expand Controllers, and then double-click BlogController.cs or BlogController.vb. In the BlogController code file, add the following method to the BlogController class.
[Visual C#] public ActionResult Edit(int id) { }
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) If blogEntry Is Nothing Then Return RedirectToAction("Index") End If 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) If blogEntry Is Nothing Then Return RedirectToAction("Index") End If Return View(blogEntry)
12
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(); TempData["ConfirmationMessage"] = blog.Title + " has been updated."; return RedirectToAction("Index"); } catch (Exception) { return View(blog); };
[Visual Basic] Dim blogEntry = blogRepository.GetBlog(id) If blogEntry Is Nothing Then Return RedirectToAction("Index") End If Try UpdateModel(blogEntry, collection.ToValueProvider()) blogRepository.UpdateBlog(CType(blogEntry, Blog)) blogRepository.Save() TempData("ConfirmationMessage") = blogEntry.Title & " has been updated"
13
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(); TempData["ConfirmationMessage"] = blog.Title + " has been updated."; 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) If blogEntry Is Nothing Then Return RedirectToAction("Index") End If Try UpdateModel(blogEntry, collection.ToValueProvider()) blogRepository.UpdateBlog(CType(blogEntry, Blog)) blogRepository.Save() TempData("ConfirmationMessage") = blogEntry.Title & " has been updated" Return RedirectToAction("Index") Catch Return View(blogEntry) End Try End Function
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.
5.
14
In the AdventureWorksMvc Microsoft Visual Studio window, click the Close button.
Open the AdventureWorksMvc solution from the following location. Programming Language Visual C# Visual Basic Location D:\Lab Files\CS\Lab 05\Starter\Exercise 03 D:\Lab Files\VB\Lab 05\Starter\Exercise 03
In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or press CTRL+SHIFT+O. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab 04\Starter\Exercise 05\AdventureWorksMvc.sln or D:\Lab Files\VB\Lab 04\Starter\Exercise 05\AdventureWorksMvc.sln and then click Open.
a. b.
In Solution Explorer, expand Controllers, and then double-click BlogController.cs or BlogController.vb. In the BlogController code file, add the following method to the BlogController class.
[Visual C#] public ActionResult Delete(int id) { }
2.
Add code to the Delete action method to redirect to the Index view.
[Visual C#] var blog = blogRepository.GetBlog(id);
15
[Visual Basic] Dim blogEntry = blogRepository.GetBlog(id) If blogEntry Is Nothing Then Return RedirectToAction("Index") End If 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) If blogEntry Is Nothing Then Return RedirectToAction("Index") End If Return View(blogEntry) End Function
[Visual Basic] <HttpPost()> Function Delete(ByVal id As Integer, ByVal confirmation As String) As ActionResult End Function
16
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(); TempData["ConfirmationMessage"] = blog.Title + " has been deleted."; return RedirectToAction("Index");
[Visual Basic] Dim blogEntry = blogRepository.GetBlog(id) If blogEntry Is Nothing Then Return RedirectToAction("Index") End If blogRepository.DeleteBlog(CType(blogEntry, Blog)) blogRepository.Save() TempData("ConfirmationMessage") = blogEntry.Title & " has been deleted." 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(); TempData["ConfirmationMessage"] = blog.Title + " has been deleted."; return RedirectToAction("Index"); }
[Visual Basic] <HttpPost()> Function Delete(ByVal id As Integer, ByVal confirmation As String) As ActionResult Dim blogEntry = blogRepository.GetBlog(id) If blogEntry Is Nothing Then Return RedirectToAction("Index") End If blogRepository.DeleteBlog(CType(blogEntry, Blog))
17
blogRepository.Save() TempData("ConfirmationMessage") = blogEntry.Title & " has been deleted." Return RedirectToAction("Index") End Function
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.
5.
Close Visual Studio 2010. In the AdventureWorksMvc Microsoft Visual Studio window, click the Close button.
f Task 4: Turn off the virtual machine and revert the changes
1. 2. 3. 4. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. In the Revert Virtual Machine dialog box, click Revert.
Module 5
Lab Answer Key: Developing MVC Views
Contents:
Exercise 1: Develop a List MVC View Exercise 2: Develop a Details MVC view Exercise 3: Develop a Create MVC view Exercise 4: Develop an Edit MVC view Exercise 5: Develop a Delete MVC view 4 5 7 13 19
Open the AdventureWorksMvc solution from the following location. Programming Language Location Visual C# Visual Basic a. b. D:\Lab Files\CS\Lab 05\Starter\Exercise 01 D:\Lab Files\VB\Lab 05\Starter\Exercise 01
In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or press CTRL+SHIFT+O. 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.
Add a menu item to the menu on the Site.Master master page, by using an Html.ActionLink method wrapped in a li HTML element within the ul element with an id attribute value of menu. Add the new menu item between the Home and About menu items.
[Visual C#] <li><%= Html.ActionLink("Blog", "", "Blog")%></li>
3.
<li><%: Html.ActionLink("Home", "Index", "Home")%></li> <li><%: Html.ActionLink("Blog", "", "Blog")%></li> <li><%: Html.ActionLink("About", "About", "Home")%></li> </ul>
Add an empty view named Index.aspx, based on the Site.Master page, to the Blog folder. a. b. In Solution Explorer, right-click Blog, point to Add, and then click View. In the Add View dialog box, in the View name box, type Index, ensure the Select master page check box is selected, and then click Add.
3.
Update the new view to a strongly-typed view of type System.Web.Mvc.ViewPage<IEnumerable<AdventureWorksMvc.Models.Blog>> or System.Web.Mvc.ViewPage(Of IEnumerable (Of AdventureWorksMvc.Blog)). Update the Inherits property of the Page directive to the following.
[Visual C#] System.Web.Mvc.ViewPage<IEnumerable<AdventureWorksMvc.Models.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%>
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>>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Index </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Index</h2> <% foreach (var item in Model) { %> <div> <%: Html.ActionLink("Details", "Details", new { id=item.BlogID })%> <%: item.DatePosted %> <%: item.Title %> </div> <% } %> </asp:Content>
[Visual Basic] <%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of IEnumerable (Of AdventureWorksMvc.Blog))" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Index </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Index</h2> <% For Each item As AdventureWorksMvc.Blog In Model%> <div> <%: Html.ActionLink("Details", "Details", New With {.id = item.BlogID})%> <%: item.DatePosted %> <%: item.Title %> </div> <% Next%> </asp:Content>
6.
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.
Display the Blog view. In the Welcome to AdventureWorks Windows Internet Explorer window, click Blog.
3.
4.
In the Index Windows Internet Explorer window, click the Close button.
Close Visual Studio 2010. In the AdventureWorksMvc Microsoft Visual Studio window, click the Close button.
Open the AdventureWorksMvc solution from the following location. Programming Language Location Visual C# Visual Basic a. b. D:\Lab Files\CS\Lab 05\Starter\Exercise 02 D:\Lab Files\VB\Lab 05\Starter\Exercise 02
In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or press CTRL+SHIFT+O. 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.
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>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Details </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Details</h2> Blogger: <%: Model.Blogger.Name %> DatePosted: <%: Model.DatePosted %> <h3> <%: Model.Title %></h3> <%: Model.BlogEntry %> <p> <%: Html.ActionLink("Back to List", "Index") %> </p> </asp:Content>
[Visual Basic] <%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of AdventureWorksMvc.Blog)" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Details </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Details</h2> Blogger: <%: Model.Blogger.Name %> DatePosted: <%: Model.DatePosted %> <h3> <%: Model.Title %></h3> <%: Model.BlogEntry %> <p> <%: Html.ActionLink("Back to List", "Index") %> </p> </asp:Content>
4.
Test the Details view. a. b. c. d. In Solution Explorer, click AdventureWorksMvc. In the AdventureWorksMvc Microsoft Visual Studio window, on the Debug menu, click Start Without Debugging, or press CTRL+F5. In the Welcome to AdventureWorks Windows Internet Explorer window, click Blog. In the Index Windows Internet Explorer window, click Details.
5.
Close Internet Explorer. In the Details Windows Internet Explorer window, click the Close button.
6.
In the AdventureWorksMvc Microsoft Visual Studio window, click the Close button.
Open the AdventureWorksMvc solution from the following location. Programming Language Location Visual C# Visual Basic a. b. D:\Lab Files\CS\Lab 05\Starter\Exercise 03 D:\Lab Files\VB\Lab 05\Starter\Exercise 03
In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or press CTRL+SHIFT+O. 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. b. 2. In Solution Explorer, expand Views, right-click Blog, point to Add, and then click View. In the Add View dialog box, in the View name box, type Blogger, and then click Add.
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>>
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 %> </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>>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Blogger </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Blogger</h2> <% 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> </asp:Content>
[Visual Basic] <%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of IEnumerable (Of AdventureWorksMvc.Blog))" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Blogger </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Blogger</h2> <% 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> </asp:Content>
10
[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>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> 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>
11
</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)" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> 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(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> </asp:Content>
4.
Run the application. a. b. In Solution Explorer, click AdventureWorksMvc. In the AdventureWorksMvc Microsoft Visual Studio window, on the Debug menu, click Start Without Debugging, or press CTRL+F5.
5.
In the Welcome to AdventureWorks Windows Internet Explorer window, in the address bar, append the following text.
blog/blogger/1
6.
12
a. b. 7.
In the Blogger Windows Internet Explorer window, click Create New. In the Create Windows Internet Explorer window, in the Title box, type New Entry, in the Blog Entry box, type This is a new blog entry, and then click Submit.
Close Internet Explorer. In the Index Windows Internet Explorer window, click the Close button.
Add the following markup and code to the Index view, right below the h2 element.
[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>>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Index </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Index</h2> <% if (TempData["ConfirmationMessage"] != null) { %> <div class="message"> <%: TempData["ConfirmationMessage"]%> </div> <% } %> <% foreach (var item in Model) { %> <div> <%: Html.ActionLink("Details", "Details", new { id=item.BlogID })%> <%: item.DatePosted %> <%: item.Title %> </div> <% } %> </asp:Content> <%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of IEnumerable (Of AdventureWorksMvc.Blog))" %>
13
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Index </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Index</h2> <% If Not TempData("ConfirmationMessage") Is Nothing Then%> <div class="message"> <%: TempData("ConfirmationMessage")%> </div> <% End If%> <% For Each item As AdventureWorksMvc.Blog In Model%> <div> <%: Html.ActionLink("Details", "Details", New With {.id = item.BlogID})%> <%: item.DatePosted %> <%: item.Title %> </div> <% Next%> </asp:Content>
4.
Run the application. a. b. In Solution Explorer, click AdventureWorksMvc. In the AdventureWorksMvc Microsoft Visual Studio window, on the Debug menu, click Start Without Debugging, or press CTRL+F5.
5.
In the Welcome to AdventureWorks Windows Internet Explorer window, in the address bar, append the following text.
blog/blogger/1
6.
Add another blog entry. a. b. In the Blogger Windows Internet Explorer window, click Create New. In the Create Windows Internet Explorer window, in the Title box, type Another New Entry, in the Blog Entry box, type This is another new blog entry, and then click Submit.
7.
Close Internet Explorer. In the Index Windows Internet Explorer window, click the Close button.
8.
Close Visual Studio 2010. In the AdventureWorksMvc Microsoft Visual Studio window, click the Close button.
14
Programming Language Location Visual C# Visual Basic a. b. D:\Lab Files\CS\Lab 05\Starter\Exercise 04 D:\Lab Files\VB\Lab 05\Starter\Exercise 04
In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or press CTRL+SHIFT+O. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab 05\Starter\Exercise 04\AdventureWorksMvc.sln or D:\Lab Files\VB\Lab 05\Starter\Exercise 04\AdventureWorksMvc.sln and then click Open.
Add an empty, strongly-typed partial view of type Blog, named Blog, to the Blog folder. a. b. In Solution Explorer, expand Views, right-click Blog, point to Add, and then click View. [Visual C#] In the Add View dialog box, in the View name box, type Blog, select the Create a partial view (.ascx) and Create a strongly-typed view check boxes, 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 Blog, select the Create a partial view (.ascx) and Create a strongly-typed view check boxes, in the View data class box, type AdventureWorksMvc.Blog, and then click Add.
3.
Copy all of the markup and code from the Content2 Content element in the Create view to the partial Blog view. a. b. In Solution Explorer, in the Views\Blog folder, double-click Create.aspx. Select the markup and code from immediately after the h2 element, till the closing the Content element, and then press CTRL+C.
[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" />
15
[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>
a. b. 4.
In the AdventureWorks Microsoft Visual Studio window, click Blog.ascx. In the Blog.ascx window, place the cursor on the line following the Page directive, and press CTRL+V.
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>
16
<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)%> </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. b. In Solution Explorer, expand Views, right-click Blog, point to Add, and then click View. [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]
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>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Edit </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Edit</h2> <% Html.RenderPartial("Blog"); %> </asp:Content>
[Visual Basic] <%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of AdventureWorksMvc.Blog)" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Edit </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Edit</h2> <% Html.RenderPartial("Blog")%> </asp:Content>
In the Welcome to AdventureWorks Windows Internet Explorer window, in the address bar, append the following text.
blog/blogger/1
3.
Edit a blog entry. a. b. c. In the Blogger Windows Internet Explorer window, next to the first blog entry from the top, click Edit. In the Edit Windows Internet Explorer window, in the Title box, type Modified Entry, in the Blog Entry box, type This entry has been modified, and then click Submit. If the AutoComplete dialog box appears, in the AutoComplete dialog box, click No.
4.
Close Internet Explorer. In the Index Windows Internet Explorer window, click the Close button.
18
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"); %>
a. b.
In the AdventureWorks Microsoft Visual Studio window, click Create.aspx. Select the markup and code from immediately after the h2 element, till the closing the Content element, and then type the following.
[Visual C#] <% 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>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Create </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Create</h2> <% Html.RenderPartial("Blog"); %> </asp:Content>
[Visual Basic] <%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of AdventureWorksMvc.Blog)" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Create </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Create</h2>
19
3.
Run the application. a. b. In Solution Explorer, click AdventureWorksMvc. In the AdventureWorksMvc Microsoft Visual Studio window, on the Debug menu, click Start Without Debugging, or press CTRL+F5.
4.
In the Welcome to AdventureWorks Windows Internet Explorer window, in the address bar, append the following text.
blog/blogger/1
5.
Add another blog entry. a. b. c. In the Blogger Windows Internet Explorer window, click Create New. In the Create Windows Internet Explorer window, in the Title box, type Yet Another Entry, in the Blog Entry box, type This is yet another blog entry, and then click Submit. If the AutoComplete dialog box appears, in the AutoComplete dialog box, click No.
6.
Close Internet Explorer. In the Index Windows Internet Explorer window, click the Close button.
7.
Close Visual Studio 2010. In the AdventureWorksMvc Microsoft Visual Studio window, click the Close button.
Open the AdventureWorksMvc solution from the following location. Programming Language Location Visual C# Visual Basic a. b. D:\Lab Files\CS\Lab 05\Starter\Exercise 05 D:\Lab Files\VB\Lab 05\Starter\Exercise 05
In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or press CTRL+SHIFT+O. 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
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. 2. In the AdventureWorksMvc Microsoft Visual Studio window, on the Build menu, click Build Solution, or press CTRL+SHIFT+B.
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. b. In Solution Explorer, expand Views, right-click Blog, point to Add, and then click View. [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.
<%: Html.ActionLink("Back to List", "Blogger") %>
a. b.
In the Delete.aspx window, locate the call to the Html.ActionLink method at the bottom of the markup. Select the following markup and code.
<%: Html.ActionLink("Back to List", "Index") %>
c.
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>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Delete </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Delete</h2> <h3> Are you sure you want to delete this?</h3> <fieldset> <legend>Fields</legend> <div class="display-label"> BlogID</div> <div class="display-field"> <%: Model.BlogID %></div> <div class="display-label"> BloggerID</div> <div class="display-field"> <%: Model.BloggerID %></div> <div class="display-label">
21
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)" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Delete </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> Delete</h2> <h3> Are you sure you want to delete this?</h3> <fieldset> <legend>Fields</legend> <div class="display-label"> BlogID</div> <div class="display-field"> <%: Model.BlogID %></div> <div class="display-label"> BloggerID</div> <div class="display-field"> <%: Model.BloggerID %></div> <div class="display-label"> 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") %>
22
In the Welcome to AdventureWorks Windows Internet Explorer window, in the address bar, append the following text.
blog/blogger/1
3.
Select a blog entry. a. b. In the Blogger Windows Internet Explorer window, next to the first blog entry from the top, click Delete. In the Delete Windows Internet Explorer window, click Delete.
4.
Close Internet Explorer. In the Index Windows Internet Explorer window, click the Close button.
5.
Close Visual Studio 2010. In the AdventureWorksMvc Microsoft Visual Studio window, click the Close button.
f Task 4: Turn off the virtual machine and revert the changes
1. 2. 3. 4. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. In the Revert Virtual Machine dialog box, click Revert.
Module 6
Lab Answer Key: Designing for Discoverability
Contents:
Exercise 1: Mapping URLs of Web Forms Pages Exercise 2: Creating a Sitemap File Exercise 3: Building the Application Infrastructure 2 7 8
Open the AdventureWorks solution at the following location. Programming Language Location Visual C# Visual Basic a. b. D:\Lab Files\CS\Lab 06\Starter\Exercise 01 D:\Lab Files\VB\Lab 06\Starter\Exercise 01
In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or press CTRL+SHIFT+O. 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.
In the list, click System.Web.Routing, and then click OK. 2. Verify reference to the System.Web.Routing assembly. a. b. c. [Visual Basic] In Solution Explorer, click AdventureWorks, and then click the Show All Files button. In Solution Explorer, expand References. Verify that the System.Web.Routing assembly is shown.
Import the System.Web.Routing namespace in the Global.asax code file. At the top of the Global.asax.cs or Global.asax.vb code file, add the following code.
[Visual C#] using System.Web.Routing;
[Visual Basic]
Imports System.Web.Routing
3.
[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
4.
5.
Open the Products.aspx.cs or Products.aspx.vb code file. In Solution Explorer, right-click Products.aspx, and then click View Code.
6.
[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 ' Retrieve category param from "/Products/{Category}" URL categoryId = Page.RouteData.Values("category").ToString() 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
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. 3. Close Windows Internet Explorer. In the http://localhost:xxxx/products/1 Windows Internet Explorer window, click the Close button.
[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") ' Route name ' URL with parameters ' Web forms page to handle it routes.MapPageRoute("product-browse", "product/{id}", "~/ProductDetail.aspx") End Sub
3.
Open the ProductDetail.aspx.cs or ProductDetail.aspx.vb code file. In Solution Explorer, right-click ProductDetail.aspx, and then click View Code.
4.
[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 ' Retrieve id param from /Products/{Id} URL productID = Page.RouteData.Values("id").ToString() Dim data = AdventureWorks.DataAccessLayer.Products.GetProduct(Integer.Parse(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() End If End Sub
2.
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. 3. Close Internet Explorer. 4. In the http://localhost:xxxx/products/1 Windows Internet Explorer window, click the Close button.
Close Visual Studio 2010. In the AdventureWorks Microsoft Visual Studio window, click the Close button.
In Control Panel, click System and Security, and then click Administrative Tools. Right-click Internet Information Services (IIS) Manager, and then click Run as administrator. In the User Account Control dialog box, in the Password box, type Pa$$w0rd, and then press ENTER. Open the Search Engine Optimization feature. In the right pane, in the Management Group section, double-click Search Engine Optimization.
6.
Create a new sitemap for the default website, in a file named Sitemap.xml. Set the change frequency to Daily, do not record the last modified date and time, and set the priority to 1. a. b. c. d. In the Search Engine Optimization pane, in the Sitemaps and Sitemap Indexes section, click Create a new sitemap. In the Choose Site dialog box, in the Site list, click Default Web Site, and then click OK. In the Add Sitemap dialog box, in the File Name box, type Sitemap.xml, and then click OK. In the Add URLs dialog box, in the URL Paths list, click Default Web Site, in the Change Frequency list, click Daily, in the Last Modified list, click Do Not Set, in the Priority list, click 1, and then click OK.
3.
In the right pane, in the Management Group section, double-click Search Engine Optimization.
Add a new allow rule for the default website and Sitemap.xml file. a. b. In the Search Engine Optimization pane, in the Robots Exclusion section, click Add a new allow rule. 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.
Open the AdventureWorks solution at the following location. Programming Language Location Visual C# Visual Basic a. b. D:\Lab Files\CS\Lab 06\Starter\Exercise 03 D:\Lab Files\VB\Lab 06\Starter\Exercise 03
In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or press CTRL+SHIFT+O. 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.
Replace the existing content of the Web.sitemap file with the following markup.
<?xml version="1.0" encoding="utf-8" ?> <siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" > <siteMapNode roles="*"> <siteMapNode url="~/Default.aspx" title="Home" description="Home"></siteMapNode> <siteMapNode url="~/ShoppingCart.aspx" title="Shopping" description="Shopping"></siteMapNode>
3.
Save and close the Web.sitemap file. a. b. In the AdventureWorks Microsoft Visual Studio window, on the File menu, click Save Web.sitemap, or press CTRL+S. In the Web.sitemap window, click the Close button.
4.
5.
Locate the div element with a class attribute value of clear hideSkiplink.
<div class="clear hideSkiplink"> <asp:Menu ID="NavigationMenu" runat="server" CssClass="menu" EnableViewState="false" IncludeStyleBlock="false" Orientation="Horizontal"> <Items> <asp:MenuItem NavigateUrl="~/Default.aspx" Text="Home" /> <asp:MenuItem NavigateUrl="~/ShoppingCart.aspx" Text="Cart" /> <asp:MenuItem NavigateUrl="~/About.aspx" Text="About" /> </Items> </asp:Menu> </div>
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="MainMenu" Orientation="Horizontal" DataSourceID="siteMapDataSource" /> </div>
7.
Save and close the Site.Master file. a. b. In the AdventureWorks Microsoft Visual Studio window, on the File menu, click Save Site.Master, or press CTRL+S. In the Site.Master window, click the Close button.
8.
Run the application. a. b. In Solution Explorer, click AdventureWorks. In the AdventureWorks Microsoft Visual Studio window, on the Debug menu, click Start Without Debugging, or press CTRL+F5.
9.
Close Internet Explorer. In the http://localhost:xxxx/products/1 Windows Internet Explorer window, click the Close button.
10
2.
3.
Place Breakpoint on the new line of code. In the Site.Master.cs or Site.Master.vb window, in the Page_Load method, place the cursor on the following line of code, and press F9.
[Visual C#] Menu NavigationMenu = (Menu) this.FindControl("NavigationMenu");
4.
Debug the application. a. b. In Solution Explorer, click AdventureWorks. In the AdventureWorks Microsoft Visual Studio window, on the Debug menu, click Start Debugging, or press F5.
5.
Single-step over the selected line of code. In the Site.Master.cs or Site.Master.vb window, on the Debug menu, click Step Over, or press F10.
6.
Hover the mouse over the NavigationMenu variable. 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. 2. 3. 4. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. In the Revert Virtual Machine dialog box, click Revert.
Module 7
Lab Answer Key: Writing Server-Side Code for Web Forms
Contents:
Exercise 1: Modifying a Web Forms Page to Display Localized Content Exercise 2: Persisting Data on Web Forms Pages Exercise 3: Utilizing View State Effectively 2 7 13
Open the AdventureWorks solution from the following location. Programming Language Location Visual C# Visual Basic a. b. D:\Lab Files\CS\Lab 07\Starter\Exercise 01 D:\Lab Files\VB\Lab 07\Starter\Exercise 01
In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or press CTRL+SHIFT+O. 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.
Generate local resources for Default.aspx, by using the Generate Local Resource functionality available in Design view. a. b. In the Default.aspx window, click Design. In the AdventureWorks Microsoft Visual Studio window, on the Tools menu, click Generate Local Resource.
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. 3. Switch back to Source view of Default.aspx. 4. In the Default.aspx window, click Source.
Notice that both the lbCategories and btnCategory server controls have had an extra attribute called meta:resourcekey added to the existing markup.
<asp:Button ... meta:resourcekey="btnCategoryResource1"></asp:Button> <asp:ListBox ... meta:resourcekey="lbCategoriesResource1"></asp:ListBox>
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.
Note: In the Resource Editor, you will see a list with all the localizable properties of the localizable controls from the Default.aspx page. 7. Switch back to Default.aspx. 8. In the AdventureWorks Microsoft Visual Studio window, click Default.aspx.
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. Localize the hard-coded Welcome to AdventureWorks! text implicitly, by adding a Localize server control within the h2 element, with the following attributes. Attribute ID Text meta:resourcekey a. b. c. Value lclWelcome Welcome to AdventureWorks! LocalizeResource1
9.
Place the cursor within the h2 element, just before the text Welcome to AdventureWorks!. Open the Toolbox, expand Standard, and then double-click Localize. Modify the Localize server control to appear as follows.
<asp:Localize ID="lclWelcome" runat="server" meta:resourcekey="lclWelcomeResource1" Text="Welcome to AdventureWorks!"></asp:Localize>
10. Delete the text Welcome to AdventureWorks! from the h2 element. 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. b. In the AdventureWorks Microsoft Visual Studio window, click Default.aspx.resx. In the bottom row of the Resource Editor, in the Name box, type lclWelcomeResource1.Text, in the Value box, type 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 ID Text a. b. c. d. Value ProductCategoriesLiteral <%$ Resources: ProductCategoriesLiteral.Text %>
In the AdventureWorks Microsoft Visual Studio window, click Default.aspx. Place the cursor within the p element, just before the text Product Categories. Open the Toolbox, expand Standard, and then double-click Literal. Modify the Literal server control to appear as follows.
<asp:Literal ID="ProductCategoriesLiteral" runat="server" Text="<%$ Resources: ProductCategoriesLiteral.Text %>"></asp:Literal>
13. Delete the text Product Categories from the p element. 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. b. In the AdventureWorks Microsoft Visual Studio window, click Default.aspx.resx. 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. b. In Solution Explorer, click AdventureWorks. 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. b. In Solution Explorer, right-click App_LocalResources, point to Add, and then click Existing Item. 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 ID Text a. b. c. Value LoginLiteral Log In
Place the cursor between the opening and closing a tags within the AnonymousTemplate element, just before the text Log In. Open the Toolbox, expand Standard, and then double-click Literal. Modify the Literal server control to appear as follows.
<asp:Literal ID="LoginLiteral" runat="server" 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 ID Text a. b. c. Value WelcomeLiteral Welcome
Place the cursor between the opening and closing LoggedInTemplate tags, just before the text Welcome. Open the Toolbox, expand Standard, and then double-click Literal. Modify the Literal server control to appear as follows.
<asp:Literal ID="WelcomeLiteral" runat="server" Text="Welcome"></asp:Literal>
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.
6.
Open the Site.Master master page in Design view. In the Site.Master window, click Design.
7.
Generate local resources for Site.Master, by using the Generate Local Resource functionality. In the AdventureWorks Microsoft Visual Studio window, on the Tools menu, click Generate Local Resource.
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. a. b. In Solution Explorer, right-click App_LocalResources, point to Add, and then click Existing Item. 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.
Show the AdventureWorks home page in German, by changing the language preference in the Internet Options dialog box. a. b. c. d. e. In the Home Page - Windows Internet Explorer window, on the Tools menu, click Internet Options. In the Internet Options dialog box, click Languages. In the Language Preference dialog box, click Add. In the Add Language dialog box, in the Language list, click German (Germany) [de-DE], and then click OK. In the Language Preference dialog box, in the Language list, click German (Germany) [deDE], and then click Move up.
f. g. 3.
In the Language Preference dialog box, click OK. In the Internet Options dialog box, click OK.
Refresh the page in Internet Explorer. In the Home Page Windows Internet Explorer window, press F5.
Note: The page should now be shown in German. 4. Close Internet Explorer. 5. In the Startseite Windows Internet Explorer window, click the Close button.
Close Visual Studio 2010. In the AdventureWorks Microsoft Visual Studio window, click the Close button.
Open the AdventureWorks solution from the following location. Programming Language Location Visual C# Visual Basic a. b. D:\Lab Files\CS\Lab 07\Starter\Exercise 02 D:\Lab Files\VB\Lab 07\Starter\Exercise 02
In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or press CTRL+SHIFT+O. 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. 2. In Solution Explorer, right-click Default.aspx, and then click View Code.
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; HttpCookie cookie = new HttpCookie("Preferences");
[Visual Basic] Else If lbCategories.SelectedIndex <> -1 Then Dim category = lbCategories.SelectedValue Dim cookie As New HttpCookie("Preferences") cookie("LastCategory") = category cookie.Expires = DateTime.Now.AddMinutes(1) Response.AppendCookie(cookie) Response.Redirect("/Products.aspx?id=" & category, True) End If End If
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)
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(); HttpCookie cookie = Request.Cookies["Preferences"]; if (cookie != null) { lbCategories.SelectedValue = cookie["LastCategory"]; }
[Visual Basic] If Not Page.IsPostBack Then Dim data As List(Of ProductCategory) = AdventureWorks.DataAccessLayer.Products.GetCategories lbCategories.DataSource = data lbCategories.DataBind() Dim cookie As HttpCookie = Request.Cookies("Preferences") If Not cookie Is Nothing Then lbCategories.SelectedValue = cookie("LastCategory") End If
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") If Not cookie Is Nothing Then lbCategories.SelectedValue = cookie("LastCategory") End If
[Visual Basic] If Not Page.IsPostBack Then Dim data As List(Of ProductCategory) = AdventureWorks.DataAccessLayer.Products.GetCategories
10
4.
Build the solution, and fix any errors. In the AdventureWorks Microsoft Visual Studio window, on the Build menu, click Build Solution, or press CTRL+SHIFT+B.
In the Application_Start method, overwrite the existing code, by adding a new application variable named OnlineVisitors, to the Application object. The variable must have a starting value of 0.
[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(); }
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")) If visitors > 0 Then visitors -= 1 Application("OnlineVisitors") = visitors End If Application.UnLock() End Sub
5.
Build the solution, and fix any errors. In the AdventureWorks Microsoft Visual Studio window, on the Build menu, click Build Solution, or press CTRL+SHIFT+B.
Upon postback, the Order button has been pressed, so the information entered in the Web Form is persisted. In the Page_Load method, notice how the product ID, product name, and list price, which are not displayed to the user, are saved to hidden fields. In the btnOrder_Click event handler, notice that a new List object of type clsShoppingCart is created and saved to Session state. Finally, the user is redirected to the ShoppingCart Web Form. Open the ShoppingCart Web Form in Code view.
3.
12
4.
Analyze the code in the Page_Load method. In the ShoppingCart.aspx.cs or ShoppingCart.aspx.vb window, check the code in the Page_Load event handler method. A check to see if a Session object named _cart exists is performed. If it does exist, the object is retrieved and assigned to the DataSource property of gvCart GridView server control.
Configure your application to use the local SQL Server instance named SQLExpress, for persisting session information instead of the default InProc mode.
<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.
<sessionState mode="SQLServer" sqlConnectionString="Integrated Security=SSPI;Data Source=.\SQLExpress;" />
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
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. In the User Account Control dialog box, in the Password box, type Pa$$w0rd, and then click Yes. In the Visual Studio Command Prompt (2010) window, type the following, and then press ENTER: aspnet_regsql -E -S .\SQLExpress -ssadd
b. c. 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.
In the Visual Studio Command Prompt (2010) window, type the following, and then press ENTER: sqlcmd E S .\SQLExpress
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.
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. In the ASPState.txt Notepad window, on the Edit menu, click Select All, or press CTRL+A. In the ASPState.txt Notepad window, on the Edit menu, click Copy, or press CTRL+C. In the ASPState.txt Notepad window, click the Close button. In the SQLCMD window, right-click next to line 1, and then click Paste.
c. d. e. f. 6.
Close the SQL Server Command Line Tool, by running the following command from the Visual Studio Command Prompt (2010).
quit
7.
Close the Visual Studio Command Prompt (2010). In the Visual Studio Command Prompt (2010) window, type exit, and then press ENTER.
8.
Close Visual Studio 2010. In the AdventureWorks Microsoft Visual Studio window, click the Close button.
Open the AdventureWorks solution from the following location. Programming Language Location Visual C# Visual Basic a. b. D:\Lab Files\CS\Lab 07\Starter\Exercise 03 D:\Lab Files\VB\Lab 07\Starter\Exercise 03
In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or press CTRL+SHIFT+O. 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.
View the source of the Default.aspx page in Internet Explorer, by using the View Source functionality.
14
3.
In the Home Page Windows Internet Explorer window, right-click the page, and then click View Source.
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 field.
H H
4.
Close the View Source window. In the http://localhost:xxxx/ Original Source window, click the Close button.
H H
5.
Close Internet Explorer. In the Home Page Windows Internet Explorer window, click the Close button.
6.
7.
a. b. 8.
In the Default.aspx window, place the cursor in the markup for the lbCategories server control. In the Properties window, in the EnableViewState list, click False.
Run the application. a. b. In Solution Explorer, click AdventureWorks. 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 field.
H H
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. 13. Close Internet Explorer. In the Home Page Windows Internet Explorer window, click the Close button.
15
a. b. 2.
In the Default.aspx window, place the cursor in the markup for the Page directive. In the Properties window, in the EnableViewState list, click False.
Run the application. a. b. In Solution Explorer, click AdventureWorks. 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. 4. Close Internet Explorer. 5. In the Home Page Windows Internet Explorer window, click the Close button.
a. b. 6.
In the Default.aspx window, place the cursor in the markup for the lbCategories server control. In the Properties window, in the EnableViewState list, click True.
Run the application. a. b. In Solution Explorer, click AdventureWorks. 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. 8. Close Internet Explorer. 9. In the Home Page Windows Internet Explorer window, click the Close button.
Remove the EnableViewState attribute and value from the Page directive. In the Default.aspx window, delete the following text from the markup for the Page directive.
EnableViewState="False"
10. Remove the EnableViewState attribute and value from the lbCategories server control.
16
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.
<%@ Page Title="Home Page" ... ViewStateMode="Disabled" %>
a. b.
In the Default.aspx window, place the cursor in the markup for the Page directive. 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.
<asp:ListBox ID="lbCategories" runat="server" DataTextField="Name" DataValueField="ProductCategoryID" Height="270px" Width="186px" ViewStateMode="Enabled"></asp:ListBox>
a. b.
In the Default.aspx window, place the cursor in the markup for the lbCategories server control. In the Properties window, in the ViewStateMode list, click Enabled.
13. Run the application. a. b. In Solution Explorer, click AdventureWorks. 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. 15. Close Internet Explorer. In the Home Page Windows Internet Explorer window, click the Close button.
16. Close Visual Studio 2010. In the AdventureWorks Microsoft Visual Studio window, click the Close button.
Open the AdventureWorks solution from the following location. Programming Language Location Visual C# Visual Basic D:\Lab Files\CS\Lab 07\Starter\Exercise 04 D:\Lab Files\VB\Lab 07\Starter\Exercise 04
17
a. b.
In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project, or press CTRL+SHIFT+O. 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.
Add a TextBox server control for the credit card field and name it txtCreditCard. Place the server control below the gvCart GridView server control. Add describing text, Credit card number:, in front of the server control.
<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.
<asp:TextBox runat="server" ID="txtCreditCard" /> <asp:RequiredFieldValidator ID="CreditCardRequiredFieldValidator" runat="server"> </asp:RequiredFieldValidator>
2.
Set the following properties as indicated. ControlToValidate = txtCreditCard ErrorMessage = Credit card number is required. Text = *
<asp:RequiredFieldValidator ID="CreditCardRequiredFieldValidator" runat="server" ControlToValidate="txtCreditCard" ErrorMessage="Credit card number is required." Text="*"> </asp:RequiredFieldValidator>
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 />
2.
Set the following properties as indicated. ControlToValidate = txtCreditCard ErrorMessage = Please enter a valid credit card number. Text = *
18
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][09]{13})$"> </asp:RegularExpressionValidator>
3.
Open the ShoppingCart Web Form in Code view. In the ShoppingCart.aspx window, right-click anywhere, and then click View Code.
4.
Make sure that an order can be placed only if Page.IsValid is true. Add the check to the btnPlaceOrder_Click event handler method.
[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
5.
Run the application. a. b. In Solution Explorer, click AdventureWorks. In the AdventureWorks Microsoft Visual Studio window, on the Debug menu, click Start Without Debugging, or press CTRL+F5.
6. 7. 8. 9.
Select Bib-Shorts on the Product Categories list, and click Submit. On the Products page, click Men's Bib-Shorts, L. On the Men's Bib-Shorts, L page, click Order. On the Shopping Cart page, click Place Order.
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.
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. 12. Close Internet Explorer. In the http://localhost:xxxx/ThankYou.aspx Windows Internet Explorer window, click the Close button.
H H
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. 2. 3. 4. In Microsoft Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. In the Revert Virtual Machine dialog box, click Revert.
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 Exercise 2: Customizing the GridView Exercise 3: Using ListView, DetailsView and Charts Lab 8B: Optimizing Data Management for Web Forms Exercise 4: Managing Data by Using ASP.NET Dynamic Data 25 2 3 17
Open the AdventureWorks solution from the D:\Lab Files\VB\Lab 08\Starter\Exercise 01 or D:\Lab Files\CS\Lab 08\Starter\Exercise 01 folder. a. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. In the Open Project dialog box, in the File name box, type D:\Lab Files\VB\Lab 08\Starter\Exercise 01\AdventureWorks.sln or D:\Lab Files\CS\Lab 08\Starter\Exercise 01\AdventureWorks.sln, and then click Open.
f. g. 2.
Save and close the ADO.NET Entity Data Model item. a. b. In the AdventureWorks.edmx window, on the File menu, click the Save AdventureWorks.edmx, or press CTRL+S. In the AdventureWorks.edmx window, click the Close button.
3.
Build the project and fix any errors. In the AdventureWorks Microsoft Visual Studio window, on the Build menu, click Build AdventureWorks.
4.
In the AdventureWorks Microsoft Visual Studio window, click the Close button.
Open the AdventureWorks solution from the D:\Lab Files\VB\Lab 08\Starter\Exercise 02 or D:\Lab Files\CS\Lab 08\Starter\Exercise 02 folder. a. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. In the Open Project dialog box, in the File name box, type D:\Lab Files\VB\Lab 08\Starter\Exercise 02\AdventureWorks.sln or D:\Lab Files\CS\Lab 08\Starter\Exercise 02\AdventureWorks.sln, and then click Open.
Add a TextBox control named QuantityTextBox to the user control. In Quantity.ascx window, add the following markup.
<asp:TextBox ID="QuantityTextBox" runat="server"></asp:TextBox>
3.
Add a RequiredFieldValidator control named QuantityRequiredFieldValidator to the user control. The RequiredFieldValidator control must validate the QuantityTextBox control, and display the text You must fill in the Quantity. as the error message, if the user leaves the text box empty. The display mode must be dynamic. In Quantity.ascx window, add the following markup, below the QuantityTextBox control.
<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]
Public Property Text As String Get Return QuantityTextBox.Text End Get Set(ByVal value As String) QuantityTextBox.Text = value End Set End Property
[Visual C#]
public string Text { get { return QuantityTextBox.Text; } set { QuantityTextBox.Text = value; } }
a. b.
In Solution Explorer, right-click Quantity.ascx, and then click View Code. In the Quantity.ascx.vb or Quantity.ascx.cs window, add the following code, at the top of the Quantity class. [Visual Basic]
Public Property Text As String Get Return QuantityTextBox.Text End Get Set(ByVal value As String) QuantityTextBox.Text = value End Set End Property
[Visual C#]
public string Text { get { return QuantityTextBox.Text; } set { QuantityTextBox.Text = value; } }
5.
Save and close the user control. a. b. c. In the AdventureWorks Microsoft Visual Studio window, on the File menu, click Save All. In the Quantity.ascx.vb or Quantity.ascx.cs window, click the Close button. In the Quantity.ascx window, click the Close button.
6.
Build the project and fix any errors. In the AdventureWorks Microsoft Visual Studio window, on the Build menu, click Build AdventureWorks. Note: Observe the Build succeeded message in the Build pane of the Output window.
Add a private member variable named productQuantity of type Integer/int to the ShoppingCart class. [Visual Basic]
Private productQuantity As Integer
[Visual C#]
private int productQuantity;
In the ShoppingCart.vb or ShoppingCart.cs window, add the following code, before the Quantity property. [Visual Basic]
Private productQuantity As Integer
[Visual C#]
private int productQuantity;
3.
Modify the auto-implemented Quantity property, to get and set the productQuantity member variable. [Visual Basic]
Public Property Quantity As Integer Get Return productQuantity End Get Set productQuantity = value End Set End Property
[Visual C#]
public int Quantity { get { return productQuantity; } set { productQuantity = value; } }
In the ShoppingCart.vb or ShoppingCart.cs window, modify the auto-implemented property to look like this. [Visual Basic]
Public Property Quantity As Integer Get Return productQuantity End Get Set productQuantity = value End Set End Property
[Visual C#]
public int Quantity { get { return productQuantity; } set { productQuantity = value; } }
4.
[Visual C#]
public decimal TotalPrice { get; set; }
In the ShoppingCart.vb or ShoppingCart.cs window, add the following code after the ListPrice property. [Visual Basic]
Public Property TotalPrice As Decimal
[Visual C#]
public decimal TotalPrice { get; set; }
5.
Update the TotalPrice property, when the Quantity property is set. [Visual Basic]
TotalPrice = productQuantity * ListPrice
[Visual C#]
TotalPrice = productQuantity * ListPrice;
In the ShoppingCart.vb or ShoppingCart.cs window, append the following code to the Quantity property setter. [Visual Basic]
[Visual C#]
TotalPrice = productQuantity * ListPrice;
6.
Save and close the ShoppingCart entity class. a. b. In the AdventureWorks Microsoft Visual Studio window, on the File menu, click Save ShoppingCart.vb or Save ShoppingCart.cs. In the ShoppingCart.vb or ShoppingCart.cs window, click the Close button.
7.
Build the project and fix any errors. In the AdventureWorks Microsoft Visual Studio window, on the Build menu, click Build AdventureWorks.
Select the gvCart GridView control. In the ShoppingCart.aspx window, click gvCart.
3.
Open the Fields dialog box for the GridView control, by using the Smart Tag. a. b. On the GridView control, click the Smart Tag button. In the GridView Tasks dialog box, click Edit Columns.
4.
Convert the Quantity field to a template field. a. b. In the Fields dialog box, in the Selected fields list, click Quantity. Click Convert this field into a TemplateField.
Open the ShoppingCart.aspx content page in Source view. In the ShoppingCart.aspx window, click Source. Note: Observe how the Quantity field/column has been converted into a TemplateField, and the newly added Total Price TemplateField.
3.
Set the AutoGenerateEditButton property to a value of True. In the Properties window, on the AutoGenerateEditButton list, click True.
4.
Add an event handler for the RowCancelingEdit event. a. b. In the Properties window, click the Events button. Double-click the text box for the RowCancelingEdit event.
5.
Add an event handler for the RowEditing event. a. b. In the AdventureWorks Microsoft Visual Studio window, click ShoppingCart.aspx. Double-click the text box for the RowEditing event.
6.
Add an event handler for the RowUpdating event. a. b. In the AdventureWorks Microsoft Visual Studio window, click ShoppingCart.aspx. Double-click the text box for the RowUpdating event.
7.
Make the existing code in the Page_Load event handler execute only on first request by wrapping the existing code in the Page_Load event handler in an If/if statement. Wrap the existing code in the Page_Load event handler in the following If/if statement. [Visual Basic]
If Not IsPostBack Then End If
[Visual C#]
if (!IsPostBack) { }
8.
Add a new Sub/void method named BindData to the ShoppingCart1 class. [Visual Basic]
Private Sub BindData() Dim cart As List(Of ShoppingCart) = CType(Session("_cart"), List(Of ShoppingCart)) gvCart.DataSource = cart gvCart.DataBind() End Sub
[Visual C#]
private void BindData() { List<ShoppingCart> cart = (List<ShoppingCart>) Session["_cart"]; gvCart.DataSource = cart; gvCart.DataBind(); }
Private Sub BindData() Dim cart As List(Of ShoppingCart) = CType(Session("_cart"), List(Of ShoppingCart)) gvCart.DataSource = cart gvCart.DataBind() End Sub
[Visual C#]
private void BindData() { List<ShoppingCart> cart = (List<ShoppingCart>) Session["_cart"]; gvCart.DataSource = cart; gvCart.DataBind(); }
9.
Add code to the gvCart_RowEditing method, for setting the edit index, and bind the data by using the BindData method. [Visual Basic]
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
[Visual C#]
protected void gvCart_RowEditing(object sender, GridViewEditEventArgs e) { // Set edit index gvCart.EditIndex = e.NewEditIndex; // Bind data BindData(); }
[Visual C#]
// Set edit index gvCart.EditIndex = e.NewEditIndex; // Bind data BindData();
10. Add code to the gvCart_RowCancelingEdit method, for resetting the edit index and bind the data by using the BindData method.
10
[Visual Basic]
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
[Visual C#]
protected void gvCart_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e) { // Reset edit index gvCart.EditIndex = -1; // Bind data BindData(); }
[Visual C#]
// Reset edit index gvCart.EditIndex = -1; // Bind data BindData();
11. Add code to the gvCart_RowUpdating method, for retrieving the existing cart from Session. [Visual Basic]
' Retrieve existing cart from session Dim cart As List(Of ShoppingCart) = CType(Session("_cart"), List(Of ShoppingCart))
[Visual C#]
// Retrieve existing cart from session List<ShoppingCart> cart = (List<ShoppingCart>) Session["_cart"];
11
[Visual C#]
// Retrieve existing cart from session List<ShoppingCart> cart = (List<ShoppingCart>) Session["_cart"];
12. Append code to the gvCart_RowUpdating method, for retrieving the current row from the GridView control. [Visual Basic]
' Get current row Dim row As GridViewRow = gvCart.Rows(e.RowIndex)
[Visual C#]
// Get current row GridViewRow row = gvCart.Rows[e.RowIndex];
[Visual C#]
// Get current row GridViewRow row = gvCart.Rows[e.RowIndex];
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]
' Find matching row in stored cart Dim cartToEdit As ShoppingCart = cart.Find(Function(cartToFind) cartToFind.ProductId = Integer.Parse(row.Cells(1).Text))
[Visual C#]
// Find matching row in stored cart ShoppingCart cartToEdit = cart.Find((cartToFind) => cartToFind.ProductId == int.Parse(row.Cells[1].Text));
[Visual C#]
// Find matching row in stored cart
12
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]
' Update values Dim qty As Quantity = CType(gvCart.Rows(e.RowIndex).FindControl("Quantity1"), Quantity) cartToEdit.Quantity = Integer.Parse(qty.Text)
[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]
' Save updated cart to session Session("_cart") = cart
[Visual C#]
// Save updated cart to session Session["_cart"] = cart;
13
[Visual C#]
// Save updated cart to session Session["_cart"] = cart;
16. Append code to the gvCart_RowUpdating method, for resetting the edit index and bind the data by using the BindData method. [Visual Basic]
' Reset edit index gvCart.EditIndex = -1 ' Bind data BindData()
[Visual C#]
// Reset edit index gvCart.EditIndex = -1; // Bind data BindData();
[Visual C#]
// Reset edit index gvCart.EditIndex = -1; // Bind data BindData();
17. Save and close the ShoppingCart code-behind file. a. b. In the AdventureWorks Microsoft Visual Studio window, on the File menu, click Save ShoppingCart.aspx.vb or Save ShoppingCart.aspx.cs. In the ShoppingCart.aspx.vb or ShoppingCart.aspx.cs window, click the Close button.
18. Build the project and fix any errors. In the AdventureWorks Microsoft Visual Studio window, on the Build menu, click Build AdventureWorks.
14
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.
<uc1:Quantity ID="Quantity1" runat="server"/>
b. Right-click the selection, and then click Cut. c. Place the cursor after the opening EditItemTemplate tag, and then press ENTER. d. Press CTRL+V. 3. Copy the Text attribute and value from the TextBox1 control to the Quantity1 control.
<uc1:Quantity ID="Quantity1" runat="server" Text='<%# Bind("Quantity") %>' />
a. In the ShoppingCart.aspx window, locate the TextBox1 control, and select the markup for the Text attribute.
Text='<%# Bind("Quantity") %>'
b. Right-click the selection, and then click Copy. c. Place the cursor in the Quantity1 element, after the runat attribute, and then press CTRL+V. 4. Delete the TextBox1 control. a. In the ShoppingCart.aspx window, locate and select the TextBox1 control.
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("Quantity") %>'></asp:TextBox>
b. 5.
Make the ProductId BoundField control read-only. In the ShoppingCart.aspx window, add the following markup to the BoundField element with a DataField attribute value of ProductId.
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}"
15
7.
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>
Set the PageSize property to 1 for GridView control. a. b. 3. In the ShoppingCart.aspx window, place the cursor in the opening tag for the GridView control. In the Properties window, in the PageSize box, type 1, and then press ENTER. Add an event handler for the PageIndexChanging event. a. b. c. 4. In the ShoppingCart.aspx window, click Design. In the Properties window, click the Events button. Double-click the text box for the PageIndexChanging event.
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. [Visual Basic]
' 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 ' Display error message Dim newPageIndex As Integer = e.NewPageIndex + 1 lblMessage.Text = "Update the item before moving to page " & newPageIndex.ToString() Else ' Clear message text lblMessage.Text = "" ' Set page index CType(sender, GridView).PageIndex = e.NewPageIndex BindData() End If
[Visual C#]
// Cancel paging operation if user attempts to navigate // to another page while in edit mode if (((GridView) sender).EditIndex != -1) { // Cancel paging operation e.Cancel = true; // Display error message
16
} else { // Clear message text lblMessage.Text = ""; // Set page index ((GridView) sender).PageIndex = e.NewPageIndex; BindData(); }
int newPageIndex = e.NewPageIndex + 1; lblMessage.Text = "Update the item before moving to page " + newPageIndex.ToString();
[Visual C#]
// Cancel paging operation if user attempts to navigate // to another page while in edit mode if (((GridView) sender).EditIndex != -1) { // Cancel paging operation e.Cancel = true; // Display error message int newPageIndex = e.NewPageIndex + 1; lblMessage.Text = "Update the item before moving to page " + newPageIndex.ToString(); } else { // Clear message text lblMessage.Text = ""; // Set page index ((GridView) sender).PageIndex = e.NewPageIndex; BindData(); }
5.
Save and close the ShoppingCart files. a. In the AdventureWorks Microsoft Visual Studio window, on the File menu, click Save All.
17
b. c. 6.
In the ShoppingCart.aspx.vb or ShoppingCart.aspx.cs window, click the Close button. In the ShoppingCart.aspx window, click the Close button.
Build the project and fix any errors. In the AdventureWorks Microsoft Visual Studio window, on the Build menu, click Build AdventureWorks.
On the Home page, in the Product Categories list, click Bike Stands, and then click Submit. On the Products page, in the Bike Stands list, click All-Purpose Bike Stand. On the Product Detail page, click Order. On the Shopping Cart page, click Edit. In the Quantity box, type 5, and then click Update. The Quantity and Total Price columns are updated. On the Shopping Cart page, click Continue Shopping. On the Home page, in the Product Categories list, click Cranksets, and then click Submit. On the Products page, in the Cranksets list, click HL Crankset.
10. On the Product Detail page, click Order. 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. 11. On the Shopping Cart page, in the GridView pager, click 2. The page index is changed and the content is updated appropriately. 12. Close Windows Internet Explorer. 13. Close Visual Studio 2010. In the AdventureWorks Microsoft Visual Studio window, click the Close button.
2. Open the AdventureWorks solution from the D:\Lab Files\VB\Lab 08\Starter\Exercise 03 or D:\Lab Files\CS\Lab 08\Starter\Exercise 03 folder.
a. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. In the Open Project dialog box, in the File name box, type D:\Lab Files\VB\Lab 08\Starter\Exercise 03\AdventureWorks.sln or D:\Lab Files\CS\Lab 08\Starter\Exercise 03\AdventureWorks.sln, and then click Open.
18
Open the SalesOrders.aspx content page in Design view. In Solution Explorer, right-click SalesOrders.aspx, and then click View Designer.
3. 4.
Place the cursor in the HTML p element at the bottom of the MainContent Content control. Add a ListView control named SalesOrdersListView to the p element. a. b. In the Toolbox, expand Data, and the double-click ListView. In the Properties window, in the (ID) box, type SalesOrdersListView.
5.
Add a new LinqDataSource control, by using the SalesOrdersListView Smart Tag. a. b. On the SalesOrdersListView control, click the Smart Tag. In the ListView Tasks dialog box, in the Choose Data Source list, click <New data source>.
6.
Use LINQ as the data source, and name the LinqDataSource control SalesOrdersLinqDataSource, by using the Data Source Configuration Wizard. In the Data Source Configuration Wizard, on the Choose a Data Source Type page, click LINQ, in the Specify an ID for the data source box, type SalesOrdersLinqDataSource, and then click OK.
7.
Select the AdventureWorks.AdventureWorksLT2008Entities object context from the existing Entity Data Model as the object context for the LinqDataSource control. In the Data Source Configuration Wizard, on the Choose a Context Object page, in the Choose your context object list, click AdventureWorks.AdventureWorksLT2008Entities, and then click Next.
8.
Select the SalesOrderHeaders table and include the SalesOrderID, OrderDate, DueDate, ShipDate and CustomerID fields for the LinqDataSource control. In the Data Source Configuration Wizard, on the Configure Data Selection page, in the Table list, click SalesOrderHeaders (ObjectSet<SalesOrderHeader>), and in the Select list, click SalesOrderID, OrderDate, DueDate, ShipDate, and CustomerID.
9.
Select only sales orders that have already shipped, by specifying a where clause, and compare ShipDate with the DateTime.Now method. a. b. In the Data Source Configuration Wizard, on the Configure Data Selection page, click Where. In the Configure Where Expression dialog box, in the Column list, click ShipDate, in the Operator list, click <=, in the Source list, click None, in the Parameter properties section, in the Value box, type DateTime.Now, and then click Add. In the Configure Where Expression dialog box, click OK.
c.
10. Order the sales orders by CustomerID and ShipDate, by specifying an Order By clause. a. b. In the Data Source Configuration Wizard, on the Configure Data Selection page, click OrderBy. In the Configure OrderBy Expression dialog box, in the Sort by area, in the list, click CustomerID, in the top most Then by area, in the list, click ShipDate, and then click OK.
11. Finish the Data Source Configuration Wizard. In the Data Source Configuration Wizard, on the Configure Data Selection page, click Finish.
19
12. Set the SalesOrderID field as the DataKeyNames property value. In the Property window, in the DataKeyNames box, type SalesOrderID.
13. Open the SalesOrders.aspx web form in Source view. In the SalesOrders.aspx window, click Source.
14. Remove the WhereParameters element from the LinqDataSource control. In the SalesOrders.aspx window, locate and delete the following markup.
<WhereParameters> <asp:Parameter DefaultValue="DateTime.Now" Name="ShipDate" Type="DateTime" /> </WhereParameters>
16. Open the SalesOrders.aspx web form in Design view. In the SalesOrders.aspx window, click Design.
17. Save the changes. In the SalesOrders.aspx window, on the File menu, click Save SalesOrders.aspx, or press CTRL+S.
18. Configure the SalesOrdersListView control, by using the SalesOrdersListView Smart Tag. Refresh the schema before configuring the control. a. b. On the SalesOrdersListView control, click the Smart Tag. In the ListView Tasks dialog box, click Refresh Schema, and then click Configure ListView.
19. Select the Grid layout and the Professional style for the SalesOrdersListView control. In the Configure ListView dialog box, in the Select a Layout list, click Grid, and in the Select a Style list, click Professional.
20. Enable paging for the SalesOrdersListView control. a. b. In the Configure ListView dialog box, select the Enable Paging check box, and then click OK. In the Microsoft Visual Studio dialog box, click Yes.
21. Disable editing and inserting a SalesOrderHeader item in the SalesOrdersListView control, by deleting the corresponding templates in Source view. a. b. In the SalesOrders.aspx window, click Source. Select and delete the EditItemTemplate and InsertItemTemplate elements and the content.
22. Add a Select button to the AlternatingItemTemplate and ItemTemplate elements. Use the Button server control and place it at the top of the HTML tr element.
<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
b.
In the SalesOrders.aspx window, insert the following markup at the top of the HTML tr element within the ItemTemplate element.
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>
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"
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
</asp:DetailsView>
On the Sales Orders page, click Select, for any item in the ListView control.
Note: Notice how the DetailsView containing the Sales Order Details is displayed below the ListView control. 3. Close Windows Internet Explorer.
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>
3.
Open the SalesOrderItemsHistory.aspx content page in Design view. In the SalesOrderItemsHistory.aspx window, click Design.
23
Set the Chart type to Bar by using the Smart Tag. a. b. With the SalesOrderItemsHistoryChart selected, click the Smart Tag. In the Chart Type list, click Bar.
6.
Use the SalesOrderItemsEntityDataSource control as the data source. By using the DataSourceID property, the X values should come from the SalesOrderItems field, the Y values should come from the OrderDate field. Refresh the schema, after selecting the data source control. a. b. c. d. e. With the SalesOrderItemsHistoryChart selected, click the Smart Tag. In the Choose Data Source list, click SalesOrderItemsEntityDataSource. Click Refresh Schema. In the X Value Member list, click SalesOrderItems. In the Y Value Member list, click OrderDate.
7.
Modify the default chart area, by setting the X and Y axis titles to # Sales Order Items and Order Date. Use the ChartArea Collection Editor, accessible from the Properties window. a. b. c. d. e. In the Properties window, in the ChartAreas box, click the ellipsis button. In the ChartArea Collection Editor, in the ChartArea1 properties list, in the Axes box, click the ellipsis button. In the Axis Collection Editor, in the X axis properties list, in the Title box, type # Sales Order Items. In the Members list, click Y (Value) axis, in the Y (Value) axis properties list, in the Title box, type Order Date, and then click OK. In the ChartArea Collection Editor, click OK.
Note: Notice how the Chart shows how the number of items per order is shown by order date. 2. 3. Close Windows Internet Explorer. Close Visual Studio 2010. In the AdventureWorks Microsoft Visual Studio window, click the Close button.
Task 6: Turn off the virtual machine and revert the changes
1. 2. 3. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert.
24
4.
25
Create an ASP.NET Dynamic Data Web application named AWDynamicData by using the New Project dialog box, and the ASP.NET Dynamic Data Entities Web Application project template. Place the project in the D:\Lab Files\VB\Lab 08\Starter\Exercise 04 or D:\Lab Files\CS\Lab 08\Starter\Exercise 04 folder. a. b. c. d. On the File menu, click New Project. In the New Project dialog box, in the left pane, click Visual Basic or Visual C#. In the middle pane, click ASP.NET Dynamic Data Entities Web Application. In the Name box, type AWDynamicData, in the Location box, type D:\Lab Files\VB\Lab 08\Starter\Exercise 04 or D:\Lab Files\CS\Lab 08\Starter\Exercise 04 and then click OK.
Generate the model from the AdventureWorksLT2008R2 database, on the .\SQLEXPRESS server, and select only the Customer (SalesLT), SalesOrderDetail (SalesLT), and SalesOrderHeader (SalesLT) tables. a. b. c. d. e. f. g. In the Entity Data Model Wizard, on the Choose Model Contents page, click Generate from database, and then click Next. On the Choose Your Data Connection page, click New Connection. In the Choose Data Source dialog box, in the Data source list, click Microsoft SQL Server, and then click Continue. In the Connection Properties dialog box, in the Server name box, type .\SQLEXPRESS. In the Select or enter a database name list, click AdventureWorksLT2008R2, and then click OK. In the Entity Data Model Wizard, on the Choose Your Data Connection page, click Next. On the Choose Your Database Objects page, on the Which database objects do you want to include in your model? list, expand Tables, click Customer (SalesLT), SalesOrderDetail (SalesLT), SalesOrderHeader (SalesLT), and then click Finish.
3.
26
a. b.
On the File menu of Visual Studio 2010, click Save AWEDM.edmx. In the AWEDM.edmx window, click the Close button.
[Visual Basic]
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 });
2.
Save and close the Global.asax.vb or Global.asax.cs file. a. b. On the File menu of Visual Studio 2010, click Save Global.asax.vb or Save Global.asax.cs. In the Global.asax.vb or Global.asax.cs window, click the Close button.
Note: The page displayed in the browser displays a list of the tables you added to the data model. 2. View the Customers page, showing all customers. In the Dynamic Data Site Windows Internet Explorer window, click Customers.
27
Note: The page displays the List view that contains the data from the Customers table. 3. View the Details view, for a customer. In the Customers - Windows Internet Explorer window, click Details, to the left of a customer.
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. 5. In the Customers - Windows Internet Explorer window, click Show all items.
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. 8. View the customers page. 9. In the SalesOrderHeaders - Windows Internet Explorer window, press BACKSPACE twice.
Create a new customer, by clicking Insert new item. In the Customers - Windows Internet Explorer window, at the end of the page, click Insert new item to create a new customer.
10. Save the new customer, with empty fields, and then cancel the new customer. In the Customers - Windows Internet Explorer window, at the end of the page, click Insert, and view the smart validation that has been added to the required fields, and then click Cancel.
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. 11. Edit the last customer displayed.
28
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. 12. Cancel the edit and close Windows Internet Explorer. a. b. In the Customers - Windows Internet Explorer window, at the end of the page, click Cancel to cancel the edit operation. In the Customers - Windows Internet Explorer window, click the Close button.
13. Close Microsoft Visual Studio 2010. In the AWDynamicData - Microsoft Visual Studio window, click the Close button.
Task 5: Turn off the virtual machine and revert the changes
1. 2. 3. 4. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. In the Revert Virtual Machine dialog box, click Revert.
Lab Answer Key: Ensuring Quality by Debugging, Unit Testing, and Refactoring
Module 9
Lab Answer Key: Ensuring Quality by Debugging, Unit Testing, and Refactoring
Contents:
Exercise 1: Configuring Error Handling Exercise 2: Debugging Code Exercise 3: Logging Exercise 4: Creating Unit Tests Exercise 5: Implementing the Test-First/Test-Driven Development Methodology 2 3 7 10 14
Lab Answer Key: Ensuring Quality by Debugging, Unit Testing, and Refactoring
Open the AdventureWorks solution from the D:\Lab Files\CS\Lab 09\Starter\Exercise 01 or D:\Lab Files\VB\Lab 09\Starter\Exercise 01 folder. a. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab 09\Starter\Exercise 01\AdventureWorks.sln or D:\Lab Files\VB\Lab 09\Starter\Exercise 01\AdventureWorks.sln, and then click Open.
Add the text CUSTOM ERROR PAGE to the CustomErrorPage Web Form. In the CustomErrorPage.aspx window, in the div element, type CUSTOM ERROR PAGE.
3.
Save the AdventureWorks project. In the AdventureWorks Microsoft Visual Studio window, on the File menu, click Save All, or press CTRL+SHIFT+S.
4.
Close the CustomErrorPage Web Form. In the CustomErrorPage.aspx window, click the Close button.
Task 3: Modify web.config to redirect to the generic error page when an unhandled
error occurs
1. Open the Web.config file. 2. In Solution Explorer, double-click Web.config.
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.
Save and close the Web.config file. a. b. In the AdventureWorks Microsoft Visual Studio window, on the File menu, click Save Web.config, or press CTRL+ S. In the Web.config window, click the Close button.
4.
Run the application. In Solution Explorer, click AdventureWorks, and then press CTRL+F5.
5.
Click the Submit button. In the Home Page Windows Internet Explorer window, click Submit.
Note: The custom error page is displayed. 6. Close Windows Internet Explorer. 7. In the http://localhost:xxxx/CustomErrorPage.aspx?aspxerrorpath=/Products.aspx Windows Internet Explorer window, click the Close button.
Close Visual Studio 2010. In the AdventureWorks Microsoft Visual Studio window, click the Close button.
Open the AdventureWorks solution from the D:\Lab Files\CS\Lab 09\Starter\Exercise 02 or D:\Lab Files\VB\Lab 09\Starter\Exercise 02 folder. a. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab 09\Starter\Exercise 02\AdventureWorks.sln or D:\Lab Files\VB\Lab 09\Starter\Exercise 02\AdventureWorks.sln, and then click Open.
Run the application in Debug mode. In Solution Explorer, click AdventureWorks, and then press F5.
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.
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. 3. In Visual Studio, place a breakpoint in Default.aspx.cs or Default.aspx.vb on the following line of code.
[Visual C#] string category = lbCategories.SelectedValue;
a. On the Windows taskbar, click AdventureWorks (Running) Microsoft Visual Studio. b. In Solution Explorer, right-click Default.aspx, and then click View Code. c. Place the cursor on the following line of code, and then press F9.
[Visual C#] string category = lbCategories.SelectedValue;
4.
Click the Back button on your browser. a. On the Windows taskbar, click http://localhost:xxxx/CustomErrorPage.aspx?aspxerrorpath=/Products.aspx Windows Internet Explorer. b. In the http://localhost:xxxx/CustomErrorPage.aspx?aspxerrorpath=/Products.aspx Windows Internet Explorer window, click the Back button.
Note: The Home page is displayed. 5. Click the Submit button. In the Home Page Windows Internet Explorer window, click Submit.
Note: Visual Studio is now shown, with the breakpoint highlighted. 6. 7. 8. Press F10 to step over the line of code that sets the local variable category to the selected value of the list. Hover the mouse over category and notice it is an empty string, which cannot be parsed by the code in the Products page. Press SHIFT+F5 to end debugging.
Lab Answer Key: Ensuring Quality by Debugging, Unit Testing, and Refactoring
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;
Note: If the breakpoint disappears after modifying the line of code, place the cursor on the line of code, and then press F9. 10. Run the application in Debug mode. In Solution Explorer, click AdventureWorks, and then press F5.
11. Click the Submit button. In the Home Page Windows Internet Explorer window, click Submit.
Note: Visual Studio is now shown, with the breakpoint highlighted. 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. Note: The Products page is displayed, showing a list of Mountain Bikes. 15. Close Windows Internet Explorer. In the http://localhost:xxxx/Products.aspx?id=5 Windows Internet Explorer window, click the Close button.
16. Remove all breakpoints by pressing CTRL+SHIFT+F9. In the Microsoft Visual Studio dialog box, click Yes.
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.
Lab Answer Key: Ensuring Quality by Debugging, Unit Testing, and Refactoring
In the Home Page Windows Internet Explorer window, click Select First.
Note: A dialog box with an alert message is now shown. 2. 3. In the Message from webpage message box, click OK three times. In Visual Studio, place a breakpoint in Default.aspx.js on the following line of code.
for (i = 0; i < 3; i++) {
a. b. c.
On the Windows taskbar, click AdventureWorks (Running) Microsoft Visual Studio. In Solution Explorer, double-click Default.aspx.js. Place the cursor on the following line of code, and then press F9.
for (i = 0; i < 3; i++) {
4.
Click the Back button in your browser. a. b. On the Windows taskbar, click http://localhost:xxxx/Products.aspx?id=5 Windows Internet Explorer. In the http://localhost:xxxx/Products.aspx?id=5 Windows Internet Explorer window, click the Back button.
Note: The Home page is displayed. 5. Click the Select First button. In the Home Page Windows Internet Explorer window, click Select First.
Note: Visual Studio is now shown, with the breakpoint highlighted. 6. 7. 8. 9. Press F10 to step over the statements of code, until a message box is displayed. In the Message from webpage message box, click OK. Repeat steps 6 and 7 twice. Press F5. Note: The Products page is displayed. 10. Close Windows Internet Explorer. In the http://localhost:xxxx/Products.aspx?id=5 Windows Internet Explorer window, click the Close button.
11. Close Visual Studio 2010. In the AdventureWorks Microsoft Visual Studio window, click the Close button.
Lab Answer Key: Ensuring Quality by Debugging, Unit Testing, and Refactoring
Exercise 3: Logging
Task 1: Open an existing ASP.NET web application
1. Open Microsoft Visual Studio 2010. 2. On the Start menu of 10264A-GEN-DEV, point to All Programs, click Microsoft Visual Studio 2010, and then click Microsoft Visual Studio 2010.
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. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. 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.
3.
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));
Lab Answer Key: Ensuring Quality by Debugging, Unit Testing, and Refactoring
[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 If Not Request("id") Is Nothing Then categoryID = Request("id") End If 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 Try
4.
Note: The custom error page is displayed. 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
a. b. c. d. 6.
On the Start menu, point to Administrative Tools, and then click Event Viewer. In the Event Viewer, in the left pane, expand Windows Logs, and then click Application. If needed, click Date and Time to sort by date and time. View the logged Application error, by double-clicking it in the middle pane.
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. 2. In Solution Explorer, double-click Web.config.
In the opening compilation tag, ensure that the value of the debug attribute is set to true.
<compilation debug="true" ...>
3.
Close the Web.config file. In the Web.config window, click the Close button.
10
Lab Answer Key: Ensuring Quality by Debugging, Unit Testing, and Refactoring
using System.Diagnostics;
3.
[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
4.
Build the project and fix any errors. In the AdventureWorks Microsoft Visual Studio window, on the Build menu, click Build AdventureWorks.
5.
Close Visual Studio 2010. In the AdventureWorks Microsoft Visual Studio window, click the Close button.
Open the MyClassLibrary solution from the D:\Lab Files\CS\Lab 09\Starter\Exercise 04 or D:\Lab Files\VB\Lab 09\Starter\Exercise 04 folder. a. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab 09\Starter\Exercise 04\MyClassLibrary.sln or D:\Lab Files\VB\Lab 09\Starter\Exercise 04\MyClassLibrary.sln, and then click Open.
Lab Answer Key: Ensuring Quality by Debugging, Unit Testing, and Refactoring
11
a. b.
In Solution Explorer, double-click Calculator.cs or Calculator.vb. Add the following code to Calculator class.
[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
2.
Save Calculator.cs or Calculator.vb. In the MyClassLibrary Microsoft Visual Studio window, on the File menu, click Save Calculator.cs, or Save Calculator.vb.
3.
Build the project and fix any errors. In the MyClassLibrary Microsoft Visual Studio window, on the Build menu, click Build ClassLibrary.
2.
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;
4.
5.
// TODO: Initialize to an appropriate value appropriate value appropriate value to an appropriate value
[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
2.
// TODO: Initialize to an appropriate value appropriate value appropriate value to an appropriate value
[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. 2. Close Visual Studio 2010. In the MyClassLibrary Microsoft Visual Studio window, click the Close button.
14
Lab Answer Key: Ensuring Quality by Debugging, Unit Testing, and Refactoring
Open the MyClassLibrary solution from the D:\Lab Files\CS\Lab 09\Starter\Exercise 05 or D:\Lab Files\VB\Lab 09\Starter\Exercise 05 folder. a. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab 09\Starter\Exercise 05\MyClassLibrary.sln or D:\Lab Files\VB\Lab 09\Starter\Exercise 05\MyClassLibrary.sln, and then click Open.
[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) Dim expected As Integer = 6 Dim unexpected As Integer = 5 Dim actual As Integer = target.Multiply(3, 2) Assert.AreEqual(expected, actual) Assert.AreNotEqual(unexpected, actual) End Sub <TestMethod()> Public Sub ClassSubtractMethodTest() Dim target As New Calculator() Assert.IsNotNull(target) Dim expected As Integer = 1 Dim unexpected As Integer = 6 Dim actual As Integer = target.Subtract(3, 2) Assert.AreEqual(expected, actual) Assert.AreNotEqual(unexpected, actual) End Sub
3.
Save the CalculatorTest.cs or CalculatorTest.vb file. In the MyClassLibrary Microsoft Visual Studio window, on the File menu, click Save CalculatorTest.cs or Save CalculatorTest.vb.
[Visual Basic] Public Function Multiply(ByVal p1 As Integer, ByVal p2 As Integer) As Integer Throw New NotImplementedException() End Function Public Function Subtract(ByVal p1 As Integer, ByVal p2 As Integer) As Integer Throw New NotImplementedException() End Function
3.
16
Lab Answer Key: Ensuring Quality by Debugging, Unit Testing, and Refactoring
In the MyClassLibrary Microsoft Visual Studio window, on the Build menu, click Build Solution or press CTRL+SHIFT+B.
Start the ClassMultiplyMethodTest test. In the CalculatorTest.cs, or CalculatorTest.vb window, right-click the ClassMultiplyMethodTest method declaration, and then click Run Tests.
Note: In the Test Result window, you can see that the ClassMultiplyMethodTest test failed. 3. Start the ClassSubtractMethodTest test. In the CalculatorTest.cs, or CalculatorTest.vb window, right-click the ClassSubtractMethodTest method declaration, and then click Run Tests.
Note: In the Test Result window, you can see that the ClassSubtractMethodTest test failed. 4. Close the CalculatorTest.cs or CalculatorTest.vb file. In the CalculatorTest.cs, or CalculatorTest.vb window, click the Close button.
[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
3.
Build the solution and fix any errors. In the MyClassLibrary Microsoft Visual Studio window, on the Build menu, click Build Solution or press CTRL+SHIFT+B.
Start the ClassMultiplyMethodTest test. In the CalculatorTest.cs, or CalculatorTest.vb window, right-click the ClassMultiplyMethodTest method declaration, and then click Run Tests.
Note: In the Test Result window, you can see that the ClassMultiplyMethodTest test passed. 3. Start the ClassSubtractMethodTest test. In the CalculatorTest.cs, or CalculatorTest.vb window, right-click the ClassSubtractMethodTest method declaration, and then click Run Tests.
Note: In the Test Result window, you can see that the ClassSubtractMethodTest test passed. 4. Close the CalculatorTest.cs or CalculatorTest.vb file. 5. In the CalculatorTest.cs, or CalculatorTest.vb window, click the Close button.
Close Visual Studio 2010. In the MyClassLibrary Microsoft Visual Studio window, click the Close button.
Task 7: Turn off the virtual machine and revert the changes
1. 2. 3. 4. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. In the Revert Virtual Machine dialog box, click Revert.
Module 10
Lab Answer Key: Securing a Web Application
Contents:
Exercise 1: Configuring ASP.NET Membership and Roles Exercise 2: Authentication Exercise 3: Authorization 2 3 8
Open the AdventureWorks solution from the D:\Lab Files\CS\Lab 10\Starter\Exercise 01 or D:\Lab Files\VB\Lab 10\Starter\Exercise 01 folder. a. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab 10\Starter\Exercise 01\AdventureWorks.sln or D:\Lab Files\VB\Lab 10\Starter\Exercise 01\AdventureWorks.sln, and then click Open.
In Solution Explorer, click the ASP.NET Configuration button. Change the authentication type from local to Internet (Windows to Forms), by using the Security page. In the ASP.Net Web Application Administration Windows Internet Explorer window, click Security.
5. 6.
Click Select authentication type. Click From the internet, and then click Done.
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 [email protected], in the Security Question box, type Favorite pet, in the Security Answer box, type Cat.
3. 4. 5.
Click Create User. Click Continue. Fill out the information to create a new user, using the following information.
Password Pa$$w0rd
E-mail [email protected]
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 [email protected], in the Security Question box, type High School, in the Security Answer box, type Central.
6. 7.
Click Enable roles. Click Create or Manage roles. In the New role name box, type Administration, and then click Add Role. If the AutoComplete dialog box appears, in the AutoComplete dialog box, click No.
5.
In the New role name box, type Contributor, and then click Add Role.
Type * in the for box, and then click Find User. Select the User Is In Role check box next to user Mary. Click Back. Click Manage for the Administration role. Next to the Administration role, click Manage.
6. 7. 8.
Type * in the for box, and then click Find User. Select the User Is In Role check boxes next to users John and Mary. Close the ASP.NET Web Site Administration Tool. In the ASP.Net Web Application Administration Windows Internet Explorer window, click the Close button.
9.
Close Visual Studio 2010. In the AdventureWorks Microsoft Visual Studio window, click the Close button.
Exercise 2: Authentication
f Task 1: Open an existing ASP.NET web application
1. Open Microsoft Visual Studio 2010.
2.
On the Start menu of 10264A-GEN-DEV, point to All Programs, click Microsoft Visual Studio 2010, and then click Microsoft Visual Studio 2010.
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. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. 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.
Ensure that the value of the mode attribute it set to Forms, in the self-closing authentication element.
<authentication mode="Forms" />
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 selfclosing authentication tag.
<authentication mode="Forms"> <forms loginUrl="~/Account/Login.aspx" timeout="2880" /> </authentication>
Examine the markup for the Login control, including the UserName and Password TextBox controls, as well as the RememberMe CheckBox control.
<asp:Login ID="LoginUser" runat="server" EnableViewState="false" RenderOuterTable="false"> <LayoutTemplate> <span class="failureNotification"> <asp:Literal ID="FailureText" runat="server"></asp:Literal> </span> <asp:ValidationSummary ID="LoginUserValidationSummary" runat="server" CssClass="failureNotification" ValidationGroup="LoginUserValidationGroup"/> <div class="accountInfo"> <fieldset class="login"> <legend>Account Information</legend> <p> <asp:Label ID="UserNameLabel" runat="server" AssociatedControlID="UserName">Username:</asp:Label>
<asp:TextBox ID="UserName" runat="server" CssClass="textEntry"></asp:TextBox> <asp:RequiredFieldValidator ID="UserNameRequired" runat="server" ControlToValidate="UserName" CssClass="failureNotification" ErrorMessage="User Name is required." ToolTip="User Name is required." 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.
using System.Web.Security;
At the top of the Login.aspx code-behind file, type the following code.
[Visual C#] using 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()); // Did we find the user? if (user != null) { // Check if the user password has expired after 90 days if (DateTime.Now.Subtract(user.LastPasswordChangedDate).TotalDays >= 90) { Response.Redirect("PasswordExpired.aspx"); } else { // Authenticate user if (Membership.ValidateUser(LoginUser.UserName.Trim(), LoginUser.Password.Trim())) e.Authenticated = true; } }
[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()) ' Did we find the user? If Not user Is Nothing Then ' Check if the user password has expired after 90 days If DateTime.Now.Subtract(user.LastPasswordChangedDate).TotalDays >= 90 Then Response.Redirect("PasswordExpired.aspx") Else ' Authenticate user If Membership.ValidateUser(LoginUser.UserName.Trim(), LoginUser.Password.Trim()) Then e.Authenticated = True End If
4.
Build the solution. On the Build menu, click Build Solution, or press CTRL+SHIFT+B.
5.
Close the Login.aspx code-behind file. In the Login.aspx.cs or Login.aspx.vb window, click the Close button.
6.
Close the Login.aspx Web Form. In the Login.aspx window, click the Close button.
Drag a PasswordRecovery server control from the Login section of the Toolbox to the EmailPassword.aspx Web Form, in the Content2 Content control. Keep the default settings.
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <asp:PasswordRecovery ID="PasswordRecovery1" runat="server"> </asp:PasswordRecovery> </asp:Content>
3.
a. b.
In the AdventureWorks Microsoft Visual Studio window, click Web.config. In the configuration element, add the following markup before the closing configuration tag.
<system.net> <mailSettings> <smtp from="[email protected]"> <network host="yourhost" userName="hostusername" password="hostpassword" /> </smtp> </mailSettings> </system.net>
4.
Build the solution and fix any errors. On the Build menu, click Build Solution, or press CTRL+SHIFT+B.
5.
Close Visual Studio 2010. In the AdventureWorks Microsoft Visual Studio window, click the Close button.
Exercise 3: Authorization
f Task 1: Open an existing ASP.NET web application
1. Open Microsoft Visual Studio 2010. 2. On the Start menu of 10264A-GEN-DEV, point to All Programs, click Microsoft Visual Studio 2010, and then click Microsoft Visual Studio 2010.
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. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. 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.
Add the following markup to the Web.config file, above the existing location element.
<location path="EmailPassword.aspx"> <system.web> <authorization> <allow users="*"/> </authorization> </system.web> </location>
3.
Save and close the Web.config file. a. b. Press CTRL+S. In the Web.config window, click the Close button.
Add a new Web Form named Home.aspx in the Contributors folder. The Web Form should be based on the Site.Master master page. a. b. c. Right-click Contributors, point to Add, and then click New Item. In the Add New Item AdventureWorks dialog box, in the middle pane, click Web Form using Master Page, in the Name box, type Home.aspx, and then click Add. In the Select a Master Page dialog box, in the Contents of folder list, click Site.Master, and then click OK.
3.
In the Home.aspx window, in the Content2 Content control, type the following markup.
<h2>Contributors Home section</h2>
4.
Save and close the Home.aspx file. a. b. Press CTRL+S. In the Home.aspx window, click the Close button.
5.
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>
7.
Save and close the Web.config file. a. b. Press CTRL+S. In the Web.config window, click the Close button.
3. 4.
On the Home page, click Log In. On the Login page, click Forgot Password?. Note: You have access to the EmailPassword Web Form as an anonymous user.
5.
Click the Back button in your browser. In the http://localhost:xxxx/Account/EmailPassword.aspx Windows Internet Explorer window, click the Back button.
10
6.
Log on using John as the username and Pa$$w0rd as the password. In the Username box, type John, in the Password box, type Pa$$w0rd, and then click Log In.
7.
Access the Contributors/Home.aspx Web Form. Type the following URL in the Windows Internet Explorer Address bar, and then press ENTER.
[Visual C#] http://localhost:4378/Contributors/Home.aspx
Note: You are denied access because the user John is not authorized to access the Contributors folder. 8. Log on using Mary as the username and Pa$$w0rd as the password. In the Username box, type Mary, in the Password box, type Pa$$w0rd, and then click Log In.
Note: You are now redirected to the Contributors/Home.aspx Web Form, because the user Mary is authorized to access the Contributors folder. 9. Close Windows Internet Explorer. In the http://localhost:xxxx/Contributors/Home.aspx Windows Internet Explorer window, click the Close button.
10. Close Visual Studio 2010. In the AdventureWorks Microsoft Visual Studio window, click the Close button.
f Task 5: Turn off the virtual machine and revert the changes
1. 2. 3. 4. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. In the Revert Virtual Machine dialog box, click Revert.
Module 11
Lab Answer Key: Applying Master Pages and CSS
Contents:
Exercise 1: Modify a Master Page Exercise 2: Create a Nested Master Page Exercise 3: Integrate a Master Page Exercise 4: Implement Control Skins Exercise 5: Apply Styles and Themes 2 4 7 11 12
Open the AdventureWorks solution from the D:\Lab Files\CS\Lab 11\Starter\Exercise 01 or D:\Lab Files\VB\Lab 11\Starter\Exercise 01 folder. a. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab 11\Starter\Exercise 01\AdventureWorks.sln or D:\Lab Files\VB\Lab 11\Starter\Exercise 01\AdventureWorks.sln, and then click Open.
In the Site.Master window, add the following markup to the div element with an ID attribute value of FooterContent.
<asp:ContentPlaceHolder ID="FooterContent" runat="server" />
In the About.aspx window, append the following markup to the existing markup.
In the About.aspx window, add the following markup to the Content control with an ID attribute value of PageFooterContent.
Copyright AdventureWorks
2.
Close Windows Internet Explorer. In the About Us Windows Internet Explorer window, click the Close button.
3.
Close Visual Studio 2010. In the AdventureWorks Microsoft Visual Studio window, click the Close button.
Open the AdventureWorks solution from the D:\Lab Files\CS\Lab 11\Starter\Exercise 02 or D:\Lab Files\VB\Lab 11\Starter\Exercise 02 folder. a. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab 11\Starter\Exercise 02\AdventureWorks.sln or D:\Lab Files\VB\Lab 11\Starter\Exercise 02\AdventureWorks.sln, and then click Open.
Rename each of the three Content controls to Header, Main, and Footer.
[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. b. c.
In the Nested.master window, locate the Content control with an ID attribute value of Content1, and change it to Header. Locate the Content control with an ID attribute value of Content2, and change it to Main. Locate the Content control with an ID attribute value of Content3, and change it to Footer.
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" %>
a. b.
In Solution Explorer, double-click Default.aspx. In the Default.aspx window, in the Page directive, change the value of the MasterPageFile attribute from ~/Site.Master to ~/Nested.master.
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">
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. 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.
b.
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>
In the Default.aspx window, in the Content control with an ID attribute value of RightBodyContent, type the following markup.
<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.
<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>
a. b.
In the Default.aspx window, locate and select the Content control with an ID attribute value of RightBodyContent, and then press CTRL+X. Place the cursor after the closing Content tag for the Content control with an ID attribute value of LeftBodyContent, and then press CTRL+V.
2.
Close Windows Internet Explorer. In the Home Page Windows Internet Explorer window, click the Close button.
3.
Close Visual Studio 2010. In the AdventureWorks Microsoft Visual Studio window, click the Close button.
Open the AdventureWorks solution from the D:\Lab Files\CS\Lab 11\Starter\Exercise 03 or D:\Lab Files\VB\Lab 11\Starter\Exercise 03 folder. a. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab 11\Starter\Exercise 03\AdventureWorks.sln or D:\Lab Files\VB\Lab 11\Starter\Exercise 03\AdventureWorks.sln, and then click Open.
In the Site.Master window, in the div element with a class attribute value of main, after the ContentPlaceHolder control, type the following markup.
<asp:Label ID="StatusMessageLabel" runat="server" />
[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
a. b.
In Solution Explorer, double-click About.aspx. In the About.aspx window, after the Page directive, add the following markup.
[Visual C#] <%@ MasterType TypeName="AdventureWorks.SiteMaster" %>
c. d.
In Solution Explorer, double-click Products.aspx. In the Products.aspx window, after the Page directive, add the following markup.
[Visual C#] <%@ MasterType TypeName="AdventureWorks.SiteMaster" %>
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
a. b. c.
In the AdventureWorks - Microsoft Visual Studio window, click About.aspx. In the About.aspx window, right-click anywhere, and then click View Code. In the Page_Load event handler method, type the following code.
[Visual C#] 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
lblCategory.Text = categoryName; var data = DataAccessLayer.Products.GetProductsByCategory(int.Parse(categoryId)); gvProducts.DataSource = data; gvProducts.DataBind(); } Master.StatusMessage = "You are on the Products page"; }
[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" If Not Request("id") Is Nothing Then categoryID = Request("id") End If 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 Master.StatusMessage = "You are on the Products page" End Sub
a. b. c.
In the AdventureWorks - Microsoft Visual Studio window, click Products.aspx. In the Products.aspx window, right-click anywhere, and then click View Code. In the Page_Load event handler method, append the following code.
[Visual C#] Master.StatusMessage = "You are on the Products page";
4. 5. 6.
Run the application by pressing CTRL+F5. On the Products page, scroll down to see the status message. Open the About page. In the http://localhost:xxxx/Products.aspx - Windows Internet Explorer window, click About.
7.
11
8.
Close Windows Internet Explorer. In the About Us Windows Internet Explorer window, click the Close button.
9.
Close Visual Studio 2010. In the AdventureWorks Microsoft Visual Studio window, click the Close button.
Open the AdventureWorks solution from the D:\Lab Files\CS\Lab 11\Starter\Exercise 04 or D:\Lab Files\VB\Lab 11\Starter\Exercise 04 folder. a. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab 11\Starter\Exercise 04\AdventureWorks.sln or D:\Lab Files\VB\Lab 11\Starter\Exercise 04\AdventureWorks.sln, and then click Open.
a. b.
In the Controls.skin window, press CTRL+A, and then press DELETE. Type the following markup.
<asp:ListBox runat="server" SkinID="BlueListBox" Height="270px" Width="186px" BackColor="AliceBlue" ForeColor="Black"/> <asp:ListBox runat="server" SkinID="RedListBox" Height="270px" Width="186px" BackColor="DarkCyan" ForeColor="White"/>
12
2.
Save and close the Controls.skin file. In the Controls.skin window, press CTRL+S, and then click the Close button.
In the Default.aspx window, in the Page directive, append the following markup.
Theme="Default"
3.
In the Default.aspx window, in the opening ListBox tag, append the following markup.
SkinID="BlueListBox"
4.
Note: Observe the light blue background color in the ListBox control. 5. Close Windows Internet Explorer. 6. In the Home Page Windows Internet Explorer window, click the Close button.
Close Visual Studio 2010. In the AdventureWorks Microsoft Visual Studio window, click the Close button.
Open the AdventureWorks solution from the D:\Lab Files\CS\Lab 11\Starter\Exercise 05 or D:\Lab Files\VB\Lab 11\Starter\Exercise 05 folder. a. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab 11\Starter\Exercise 05\AdventureWorks.sln or D:\Lab Files\VB\Lab 11\Starter\Exercise 05\AdventureWorks.sln, and then click Open.
13
c.
In the CSS Outline window, modify the .header class by using the Modify Style dialog box.
3.
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.
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
Move the StyleA.css file to the Blue folder. In Solution Explorer, under Styles, click and drag StyleA.css to App_Themes\Blue.
3.
Move the StyleB.css file to the Red folder. In Solution Explorer, under Styles, click and drag StyleB.css to App_Themes\Red.
4.
5.
Remove the SkinId attribute and value from the ListBox control.
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"
7.
Save and close the Default.aspx file. In the Default.aspx window, press CTRL+S, and then click the Close button.
Set the global page theme to the Red, by adding the pages element with the theme attribute to the system.web element.
<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"/>
15
3.
Save and close the Web.config file. In the Web.config window, press CTRL+S, and then click the Close button.
Note: Observe the new colors and slightly different layout. 2. Close Windows Internet Explorer. 3. In the Home Page Windows Internet Explorer window, click the Close button.
Close Visual Studio 2010. In the AdventureWorks Microsoft Visual Studio window, click the Close button.
f Task 7: Turn off the virtual machine and revert the changes
1. 2. 3. 4. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. In the Revert Virtual Machine dialog box, click Revert.
Module 12
Lab Answer Key: Developing Client-side Scripts and Services
Contents:
Exercise 1: Using jQuery Exercise 2: Using Advanced jQuery Exercise 3: Creating a WCF Service 2 6 8
Open the AdventureWorks solution from the D:\Lab Files\CS\Lab 12\Starter\Exercise 01 or D:\Lab Files\VB\Lab 12\Starter\Exercise 01 folder. a. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab 12\Starter\Exercise 01\AdventureWorks.sln or D:\Lab Files\VB\Lab 12\Starter\Exercise 01\AdventureWorks.sln, and then click Open.
Ensure that the jquery-1.4.1.js and jquery.tablesorter.min.js file are located in the Scripts folder. In Solution Explorer, expand Scripts. Locate the jquery-1.4.1.js and jquery.tablesorter.min.js files. In the head element of the Site.Master file, add the following script elements.
<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.
<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>
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.
Select the Bike Stands product category and click Submit. In the Home Page Windows Internet Explorer window, in the Product Categories list, click Bike Stands, and then click Submit.
3.
Select the All-Purpose Bike Stand product. In the http://localhost:xxxxx/Products.aspx?id=31 Windows Internet Explorer window, click All-Purpose Bike Stand.
4.
Add the product to the shopping cart. In the http://localhost:xxxxx/ProductDetail.aspx?id=879 Windows Internet Explorer window, click Order.
5.
View the source for the rendered page. In the http://localhost:xxxxx/ShoppingCart.aspx Windows Internet Explorer window, on the View menu, click Source.
6.
Locate the gvCart GridView control, and note the ID for the rendered server control.
<table cellspacing="0" rules="all" border="1" id="MainContent_gvCart" style="bordercollapse:collapse;">
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>
Update the Page_Load method to reflect the following code. (This ensures that the thead and tbody HTML elements are rendered with the GridView control.)
[Visual C#] protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack)
{ 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 If gvCart.Rows.Count > 0 Then gvCart.UseAccessibleHeader = True gvCart.HeaderRow.TableSection = TableRowSection.TableHeader gvCart.FooterRow.TableSection = TableRowSection.TableFooter End If End Sub
In the ShoppingCart.aspx window, in the ShoppingCart class, in the Page_Load method, append the following code.
[Visual C#] if (this.gvCart.Rows.Count > 0) { gvCart.UseAccessibleHeader = true; gvCart.HeaderRow.TableSection = TableRowSection.TableHeader; gvCart.FooterRow.TableSection = TableRowSection.TableFooter; }
[Visual Basic] If gvCart.Rows.Count > 0 Then gvCart.UseAccessibleHeader = True gvCart.HeaderRow.TableSection = TableRowSection.TableHeader gvCart.FooterRow.TableSection = TableRowSection.TableFooter
End If
3.
Run the application. In Solution Explorer, click AdventureWorks, and then press CTRL+F5.
4.
Select the Bike Stands product category, and then click Submit. In the Home Page Windows Internet Explorer window, in the Product Categories list, click Bike Stands, and then click Submit.
5.
Select the All-Purpose Bike Stand product. In the http://localhost:xxxxx/Products.aspx?id=31 Windows Internet Explorer window, click All-Purpose Bike Stand.
6.
Add the product to the shopping cart. In the http://localhost:xxxxx/ProductDetail.aspx?id=879 Windows Internet Explorer window, click Order.
7.
Continue shopping. In the http://localhost:xxxxx/ShoppingCart.aspx Windows Internet Explorer window, click Continue Shopping.
8.
Select the Bib-Shorts product category, and then click Submit. In the Home Page Windows Internet Explorer window, in the Product Categories list, click Bib-Shorts, and then click Submit.
9.
Select the Men's Bib-Shorts, L product. In the http://localhost:xxxxx/Products.aspx?id=22 Windows Internet Explorer window, click Men's Bib-Shorts, L.
10. Add the product to the shopping cart. In the http://localhost:xxxxx/ProductDetail.aspx?id=857 Windows Internet Explorer window, click Order.
11. View the source for the rendered page. In the http://localhost:xxxxx/ShoppingCart.aspx Windows Internet Explorer window, on the View menu, click Source.
12. Locate the gvCart GridView control, and note that the thead and tbody HTML elements are rendered.
<table cellspacing="0" rules="all" border="1" id="MainContent_gvCart" style="bordercollapse:collapse;"> <thead> <tr> <th scope="col">ID</th><th scope="col">Name</th><th scope="col">Price</th><th scope="col">Quantity</th> </tr> </thead><tbody> <tr> <td>879</td><td>All-Purpose Bike Stand</td><td>1</td><td>159</td> </tr> </tbody><tfoot>
14. Click the ID column header. In the on the different column headers and it will sort the data in ascending and descending order
Note: Notice how the rows are sorted ascending according to the value of the ID column for the individual rows. 15. Close Windows Internet Explorer. In the Home Page Windows Internet Explorer window, click the Close button.
16. Close Visual Studio 2010. In the AdventureWorks Microsoft Visual Studio window, click the Close button.
Open the AdventureWorks solution from the D:\Lab Files\CS\Lab 12\Starter\Exercise 02 or D:\Lab Files\VB\Lab 12\Starter\Exercise 02 folder. a. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab 12\Starter\Exercise 02\AdventureWorks.sln or D:\Lab Files\VB\Lab 12\Starter\Exercise 02\AdventureWorks.sln, and then click Open.
Locate the markup for the GridView control named gvProducts. In the Products.aspx window, locate the markup for the GridView control named gvProducts.
3.
Append a custom TemplateField column to the Columns element of the gvProducts GridView control.
<asp:BoundField DataField="ListPrice" HeaderText="List Price" DataFormatString="{0:c}" /> <asp:TemplateField HeaderText="Ad"> <ItemTemplate> <div style="display: none"> Advertisement for <%# Eval("Name") %> </div> </ItemTemplate> </asp:TemplateField> </Columns>
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>
5.
On the Products page, hover the mouse over the name of the product. Note: The custom advertisement message is displayed in the rightmost column. 6. Close Windows Internet Explorer. In the http://localhost:xxxxx/Products.aspx Windows Internet Explorer window, click the Close button.
2.
3.
On the Products page, hover the mouse over the name of the product. Note: The custom advertisement message is displayed in the rightmost column, but now it closes after a short period.
4.
Close Windows Internet Explorer. In the http://localhost:xxxxx/Products.aspx Windows Internet Explorer window, click the Close button.
5.
Close Visual Studio 2010. In the AdventureWorks Microsoft Visual Studio window, click the Close button.
Open the AdventureWorks solution from the D:\Lab Files\CS\Lab 12\Starter\Exercise 03 or D:\Lab Files\VB\Lab 12\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 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; } // Add more operations here and mark them with [OperationContract]
[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
[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()>
2.
[Visual Basic] Public Class ProductsService <OperationContract()> Public Function GetRandomProduct() As String Dim random = New Random() Using db = New AdventureWorksEntities() Dim randomNumber = random.[Next](1, db.Products.Count() + 1) Dim randomProduct = (From p In db.Products Where p.ProductID = randomNumber Select New With {p.Name, p.ListPrice, p.ProductNumber}).FirstOrDefault() Return New System.Web.Script.Serialization.JavaScriptSerializer().Serialize(randomProduct) End Using End Function End Class
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; using (var db = new AdventureWorksEntities()) { int count = 0; while (count == 0) { randomNumber = random.Next(500, 1000); var query = (from p in db.Products where p.ProductID == randomNumber select p); count = query.Count(); } 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] <OperationContract()> Public Function GetRandomProduct() As String Dim random = New Random() Dim randomNumber As Integer Using db = New AdventureWorksEntities() Dim count As Integer = 0 While count = 0 randomNumber = random.[Next](500, 1000) Dim query = (From p In db.Products Where p.ProductID = randomNumber Select p) count = query.Count() End While Dim randomProduct = (From p In db.Products Where p.ProductID = randomNumber Select New With {p.Name, p.ListPrice, p.ProductNumber}).FirstOrDefault() Return New System.Web.Script.Serialization.JavaScriptSerializer().Serialize(randomProduct) End Using
12
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.
Examine the configuration markup in the system.serviceModel element, which has been created by the Ajax-enabled WCF service project item template.
<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. 2. In Solution Explorer, double-click Site.Master.
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.
<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.
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; }); }
4.
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
</label> <br /> Product Number: <label id="ProductNumber"> </label> <br /> Product Price: $<label id="ProductPrice"></label> <br /> </div>
5.
6.
Close Windows Internet Explorer. In the Home Page Windows Internet Explorer window, click the Close button.
f Task 6: Turn off the virtual machine and revert the changes
1. 2. 3. 4. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. In the Revert Virtual Machine dialog box, click Revert.
Module 13
Lab Answer Key: Implementing Advanced Ajax in a Web Application
Contents:
Exercise 1: Using Microsoft Ajax in an MVC Page Exercise 2: Using jQuery in an MVC View Exercise 3: Handling Events 2 6 8
Lab 13: Implementing Advanced Ajax for the AdventureWorks Web Application
Exercise 1: Using Microsoft Ajax in an MVC Page
f Task 1: Open an existing ASP.NET web application
1. 2. Log on to the 10264A-GEN-DEV virtual machine as Student, with the password, Pa$$w0rd. Open Microsoft Visual Studio 2010. 3. On the Start menu of 10264A-GEN-DEV, point to All Programs, click Microsoft Visual Studio 2010, and then click Microsoft Visual Studio 2010.
Open the AdventureWorksMvc solution from the D:\Lab Files\CS\Lab 13\Starter\Exercise 01 or D:\Lab Files\VB\Lab 13\Starter\Exercise 01 folder. a. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab 13\Starter\Exercise 01\AdventureWorksMvc.sln or D:\Lab Files\VB\Lab 13\Starter\Exercise 01\AdventureWorksMvc.sln, and then click Open.
At the top of the Site.Master file, in the head element, add a reference to the Microsoft Ajax libraries.
<script src="<%= Url.Content("~/Scripts/MicrosoftAjax.debug.js") %>" type="text/javascript"></script> <script src="<%= Url.Content("~/Scripts/MicrosoftMvcAjax.debug.js") %>" type="text/javascript"></script>
In the Site.Master window, in the head element, append the following markup.
<script src="<%= Url.Content("~/Scripts/MicrosoftAjax.debug.js") %>" type="text/javascript"></script> <script src="<%= Url.Content("~/Scripts/MicrosoftMvcAjax.debug.js") %>" type="text/javascript"></script>
Return the product categories from the Index action method by modifying the existing code. [Visual C#]
public ActionResult Index(string CategoryID) { int id = int.Parse(CategoryID); var prodCategories = pr.GetCategories(); 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
In the ProductsController.cs or ProductsController.vb window, modify the content of the Index method from the following: [Visual C#]
int id = int.Parse(CategoryID); var products = pr.GetProductsByCategory(id); return View(products);
[Visual Basic]
Dim id As Integer = CInt(CategoryID) Dim products = pr.GetProductsByCategory(id) Return View(products)
[Visual Basic]
Dim prodCategories = pr.GetCategories() Return View(prodCategories)
2.
Insert the following markup and code in the _AjaxProductCategories.ascx file, after the Control directive. [Visual C#]
<% using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "productCategories" })) { %> <select size="4" id="CategoryID" name="CategoryID" style="height: 270px; width: 186px;"> <% foreach (var ProductCategory in Model) { %> <option value="<%= ProductCategory.ProductCategoryID %>"> <%= Html.Encode(ProductCategory.Name)%> </option> <% } %> </select> <div id="productCategories"> </div> <% } %>
[Visual Basic]
<% Using (Ajax.BeginForm(New AjaxOptions With {.UpdateTargetId = "productCategories" }))%> <select size="4" id="CategoryID" name="CategoryID" style="height: 270px; width: 186px;"> <% For Each ProductCategory In Model%> <option value="<%= ProductCategory.ProductCategoryID %>"> <%= Html.Encode(ProductCategory.Name)%> </option> <% Next%> </select> <div id="productCategories">
Delete the existing markup in the Content2 Content control. In the Index.aspx window, select the markup between the opening and closing Content tags, for the Content control with an ID attribute value of Content2, and then press DELETE.
3.
Add the following markup to the Index view, at the top of the Content2 Content control. [Visual C#]
<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)%>
4.
Delete the existing markup in the Content1 Content control. In the Index.aspx window, select the markup between the opening and closing Content tags, for the Content control with an ID attribute value of Content1, and then press DELETE.
5.
Add the following markup to the Index view, at the top of the Content1 Content control.
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>>"
[Visual Basic]
Inherits="System.Web.Mvc.ViewPage(Of IEnumerable (Of AdventureWorksMvc.ProductCategory))"
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]
System.Web.Mvc.ViewPage(Of IEnumerable (Of AdventureWorksMvc.ProductCategory))
7.
Build the solution and fix any errors. In the AdventureWorksMvc Microsoft Visual Studio window, press CTRL+SHIFT+B.
8.
Close Visual Studio 2010. In the AdventureWorksMvc Microsoft Visual Studio window, click the Close button.
Open the AdventureWorksMvc solution from the D:\Lab Files\CS\Lab 13\Starter\Exercise 02 or D:\Lab Files\VB\Lab 13\Starter\Exercise 02 folder. a. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab 13\Starter\Exercise 02\AdventureWorksMvc.sln or D:\Lab Files\VB\Lab 13\Starter\Exercise 02\AdventureWorksMvc.sln, and then click Open.
At the top of the Site.Master file, in the head element, add a reference to the Microsoft Ajax libraries.
<script src="<%= Url.Content("~/Scripts/jquery-1.4.1.min.js") %>" type="text/javascript"></script>
In the Site.Master window, in the head element, append the following markup.
<script src="<%= Url.Content("~/Scripts/jquery-1.4.1.min.js") %>" type="text/javascript"></script>
Create an action for the Ajax method to call. The following code returns a view populated with products. [Visual C#]
public ViewResult FeaturedProducts(string CategoryId)
[Visual Basic]
Public Function FeaturedProducts(ByVal CategoryId As String) As ViewResult Dim id As Integer = Integer.Parse(CategoryId) Dim products = pr.GetProductsByCategory(id) Return View("_FeaturedProducts", products) End Function
The Ajax method needs a place to put the results from the called function. Add a div element at the bottom of the page, before the closing Content tag.
<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>
4.
Run the application. In Solution Explorer, click AdventureWorksMvc, and then press CTRL+F5.
5.
In Windows Internet Explorer, click Submit. In the Welcome to AdventureWorks Windows Internet Explorer window, click Submit.
6.
In Windows Internet Explorer, in the Choose a category list, click Bib-shorts. In the Products Windows Internet Explorer window, in the Choose a category list, click Bibshorts.
Note: The products for the chosen category are displayed below the list.
7.
Close Windows Internet Explorer. In the Products Windows Internet Explorer window, click the Close button.
8.
Close Visual Studio 2010. In the AdventureWorksMvc Microsoft Visual Studio window, click the Close button.
Open the AdventureWorksMvc solution from the D:\Lab Files\CS\Lab 13\Starter\Exercise 03 or D:\Lab Files\VB\Lab 13\Starter\Exercise 03 folder. a. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab 13\Starter\Exercise 03\AdventureWorksMvc.sln or D:\Lab Files\VB\Lab 13\Starter\Exercise 03\AdventureWorksMvc.sln, and then click Open.
Before the featured-products div element, add a div to display the Ajax status messages.
<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(''); }); });
2.
Ensure that the Index view page matches the following. [Visual C#]
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<AdventureWorksMvc.Models.ProductCategor y>>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Products </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">
10
</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]
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of IEnumerable (Of AdventureWorksMvc.ProductCategory))" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Products </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(''); });
11
$('.error').ajaxError(function () { $(this).text('There was an error! Please try again later...'); }); }); </script> </asp:Content>
In Windows Internet Explorer, click Submit. In the Welcome to AdventureWorks Windows Internet Explorer window, click Submit.
3.
In Windows Internet Explorer, in the Choose a category list, click Bib-shorts. In the Products Windows Internet Explorer window, in the Choose a category list, click Bibshorts.
Note: The products for the chosen category are displayed below the list, but first you see the Loading... notice.
4.
Close Windows Internet Explorer. In the Products Windows Internet Explorer window, click the Close button.
5.
Close Visual Studio 2010. In the AdventureWorksMvc Microsoft Visual Studio window, click the Close button.
f Task 5: Turn off the virtual machine and revert the changes
1. 2. 3. 4. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. In the Revert Virtual Machine dialog box, click Revert.
Module 14
Lab Answer Key: ASP.NET Deployments
Contents:
Exercise 1: Creating a Profile for Deploying a Web Application Project Using One-Click Publish Exercise 2: Creating a Web Deployment Package 2 5
Create a new ASP.NET Web Application named Deployment in the D:\Lab Files\CS\Lab 14\Starter\Exercise 01 or D:\Lab Files\VB\Lab 14\Starter\Exercise 01 folder. a. b. In the Start Page Microsoft Visual Studio window, on the File menu, click New Project. In the New Project dialog box, in the left pane, click Visual C# or Visual Basic, in the middle pane, click ASP.NET Web Application, in the Name box, type Deployment, in the Location box, type D:\Lab Files\CS\Lab 14\Starter\Exercise 01 or D:\Lab Files\VB\Lab 14\Starter\Exercise 01, and then click OK.
On the Create New Account page, type the following information, and then click Create User. User Name: Student E-mail: [email protected] Password: Pa$$w0rd Confirm Password: Pa$$w0rd
3.
In the Register Windows Internet Explorer window, in the User Name box, type Student, in the E-mail box, type [email protected], in the Password box, type Pa$$w0rd, and in the Confirm Password box, type Pa$$w0rd. 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.
4.
Close Windows Internet Explorer. In the Home Page Windows Internet Explorer window, click the Close button.
2.
Select the Package/Publish Web tab. In the Deployment window, click Package/Publish Web.
3. 4. 5. 6.
Ensure that Active (Release) is selected in the Configuration list. Select the Exclude generated debug symbols check box. Ensure that the Include all databases configured in Package/Publish SQL tab check box is selected. Save the changes. Press CTRL+S.
Import the database settings from the Web.config file. a. b. In the Deployment window, click Import from Web.config. In the Microsoft Visual Studio dialog box, click OK.
3.
In the Connection string for destination database box, type Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\aspnetdb.mdf;Integrated Security=True;User Instance=True. You can optionally copy the connection string from the Connection string for source database box. Ensure that the Pull data and/or schema from an existing database check box is selected. Set the database scripting options to Schema and Data. In the Deployment window, in the Database scripting options list, click Schema and Data.
4. 5.
6.
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. In Solution Explorer, click Deployment, and then click the Show All Files button.
3.
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"
5.
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. 6. Save and close the Web.Release.config file. a. b. Press CTRL+S. In the Web.Release.config window, click the Close button.
Mark the web application as an IIS application on the destination server. In the Publish Web dialog box, select the Mark as IIS application on destination check box.
Note: If your hosting company advises you to allow untrusted certificates, select the Allow untrusted certificate check box.
3.
Enter the credentials for the local user admin. a. b. In the User name box, type admin, and then in the Password box, type Pa$$w0rd. Select the Save password check box.
4.
Set the service URL to localhost. In the Service URL box, type localhost.
5.
Set the site/application URL to Default Web Site/Deployment. In the Site/application box, type Default Web Site/Deployment.
6.
Save the profile and close the Publish Web dialog box. In the Publish Web dialog box, click Save, and then click Close.
7.
Close Visual Studio 2010. In the Deployment Microsoft Visual Studio window, click the Close button.
Open the Deployment solution from the D:\Lab Files\CS\Lab 14\Starter\Exercise 02 or D:\Lab Files\VB\Lab 14\Starter\Exercise 02 folder. a. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab 14\Starter\Exercise 02\Deployment.sln or D:\Lab Files\VB\Lab 14\Starter\Exercise 02\Deployment.sln, and then click Open.
2.
3.
In the connectionStrings element, add a connection string for the new database.
<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" />
4.
Save and close the Web.config file. In the Web.config window, press CTRL+S, and then click the Close button.
5.
Run the application. In Solution Explorer, click Deployment, and then press CTRL+F5.
6.
Click the Log In link. In the Home Page Windows Internet Explorer window, click Log In.
7.
Enter credentials for the user student with a password of Pa$$w0rd, and then log in. In the Log In Windows Internet Explorer window, in the Username box, type student, in the Password box, type Pa$$w0rd, and then click Log In.
8.
Close Windows Internet Explorer. In the Home Page Windows Internet Explorer window, click the Close button.
2. 3.
In the Deployment Microsoft Visual Studio window, in the right side, click Server Explorer.
In Server Explorer, right-click Data Connections, and then click Create New SQL Server Database. 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 Create New SQL Server Database dialog box, in the Server name box, type 10264a-gendev\SQLEXPRESS, in the New database name box, type DeploymentTest, and then click OK.
Select the Package/Publish Web tab. In the Deployment window, click Package/Publish Web.
3.
Ensure that the following settings have been specified: Active (Debug) is selected in the Configuration list. Only files needed to run this application is selected in the list in the Items to deploy (applies to all deployment methods) section. The Exclude generated debug symbols check box is cleared. The Exclude files from the App_Data folder check box is selected. The Include all databases configured in Package/Publish SQL tab check box is selected. The Create deployment package as a zip file check box is selected. The Location where package will be created box contains the following value.
obj\Debug\Package\Deployment.zip
4. 5.
In the IIS Web site/application name to use on the destination server box, type Default Web Site/Deployment. Save the changes. Press CTRL+S.
Ensure that All Configurations is selected in the Configuration list. Import the database settings from the Web.config file. a. b. In the Deployment window, click Import from Web.config. In the Microsoft Visual Studio dialog box, click OK.
4. 5. 6.
Ensure that Active (Debug) is selected in the Configuration list. Ensure that the ApplicationServices-Deployment row is selected in the Database Entries list. In Server Explorer, expand the Data Connections folder and select the 10264a-gendev\sqlexpress.DeploymentTest.dbo database. a. b. In the Deployment Microsoft Visual Studio window, in the right side, click Server Explorer. Under Data Connections, click 10264a-gen-dev\sqlexpress.DeploymentTest.dbo.
7.
Copy the value of the Connection String property from the Properties window. In the Properties window, in the Connection String box, select all of the text, and then press CTRL+C.
8.
In the Project Designer, in the Connection string for destination database box, paste the copied value, Data Source=10264A-GEN-DEV\SQLEXPRESS;Initial Catalog=DeploymentTest;Integrated Security=True;Pooling=False. Ensure that the Pull data and/or schema from an existing database check box is selected.
9.
10. Set the database scripting options to Schema and Data. In the Deployment window, in the Database scripting options list, click Schema and Data.
11. Ensure that the AW-Deployment row is selected in the Database Entries list. 12. In the Connection string for destination database box, paste the copied value, Data Source=10264A-GEN-DEV\SQLEXPRESS;Initial Catalog=DeploymentTest;Integrated Security=True;Pooling=False. 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.
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.
2.
Open the Replace dialog box. In the Deployment.csproj Notepad or Deployment.vbproj Notepad window, on the Edit menu, click Replace.
3.
In the Replace dialog box, search for Transacted="True" and replace with Transacted="False". Replace all instances. a. b. In the Replace dialog box, in the Find what box, type Transacted="True", in the Replace with box, type Transacted="False", and then click Replace All. In the Replace dialog box, click Cancel.
4.
Save the changes and close the project file. a. b. In the Deployment.csproj Notepad or Deployment.vbproj Notepad window, on the File menu, click Save. In the Deployment.csproj Notepad or Deployment.vbproj Notepad window, click the Close button.
5.
When Visual Studio asks if you want to reload the project, click the Reload button. In the File Modification Detected dialog box, click Reload.
3.
4.
Examine and delete the block of comments that contains a connectionStrings element.
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> -->
5.
6.
Save and close the Web.Debug.config file. a. b. Press CTRL+S. In the Web.Debug.config window, click the Close button.
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. 2. Open Internet Information Services (IIS) Manager as an administrator. 3. 4. 5. 6. On the Start menu, click Control Panel.
In Control Panel, click System and Security, and then click Administrative Tools. Right-click Internet Information Services (IIS) Manager, and then click Run as administrator. In the User Account Control dialog box, in the Password box, type Pa$$w0rd, and then press ENTER. In Internet Information Services (IIS) Manager, expand 10264A-GEN-DEV (10264A-GENDEV\Admin), expand Sites, and then click Default Web Site.
10
7. 8.
In the Actions pane, under Deploy, click Import Application. In the Import Application Package wizard, use the D:\Lab Files\CS\Lab 14\Starter\Exercise 02\Deployment\obj\Debug\Package\Deployment.zip or D:\Lab Files\VB\Lab 14\Starter\Exercise 02\Deployment\obj\Debug\Package\Deployment.zip package. In the Import Application Package wizard, in the Package path box, type the D:\Lab Files\CS\Lab 14\Starter\Exercise 02\Deployment\obj\Debug\Package\Deployment.zip or D:\Lab Files\VB\Lab 14\Starter\Exercise 02\Deployment\obj\Debug\Package\Deployment.zip, and then click Next.
9.
Accept the default selected contents of the package. In the Import Application Package wizard, on the Select the Contents of the Package page, click Next.
10. Accept the default application paths and connection strings. In the Import Application Package wizard, on the Enter Application Package Information page, click Next.
11. Click Finish. In the Import Application Package wizard, on the Installation Progress and Summary page, click Finish.
12. Close Internet Information Services (IIS) Manager. In the Internet Information Services (IIS) Manager window, click the Close button.
Note: The Default.aspx page is displayed. It looks the same as it does when you run it in Visual Studio 2010. a. b. On the Start menu, click Internet Explorer. In the Blank Page - Windows Internet Explorer window, in the address bar, type http://localhost/Deployment, and then press ENTER.
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. 4. Close Windows Internet Explorer. In the Home Page Windows Internet Explorer window, click the Close button.
11
5.
Close Visual Studio 2010. In the Deployment Microsoft Visual Studio window, click the Close button.
f Task 10: Turn off the virtual machine and revert the changes
1. 2. 3. 4. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. In the Revert Virtual Machine dialog box, click Revert.
Module 15
Lab Answer Key: Developing a Web Application by Using Silverlight
Contents:
Exercise 1: Creating a Silverlight Project Exercise 2: Creating a Silverlight WCF Service Exercise 3: Displaying Data by Using Silverlight Controls 2 3 5
Open the AdventureWorks solution from the D:\Lab Files\CS\Lab 15\Starter\Exercise 01 or D:\Lab Files\VB\Lab 15\Starter\Exercise 01 folder. a. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab 15\Starter\Exercise 01\AdventureWorks.sln or D:\Lab Files\VB\Lab 15\Starter\Exercise 01\AdventureWorks.sln, and then click Open.
c.
2.
Build the solution. In the AdventureWorks Microsoft Visual Studio window, press CTRL+SHIFT+B.
3.
Save the solution changes. In the AdventureWorks Microsoft Visual Studio window, press CTRL+SHIFT+S.
4.
Close Visual Studio 2010. In the AdventureWorks Microsoft Visual Studio window, click the Close button.
Open the AdventureWorks solution from the D:\Lab Files\CS\Lab 15\Starter\Exercise 02 or D:\Lab Files\VB\Lab 15\Starter\Exercise 02 folder. a. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab 15\Starter\Exercise 02\AdventureWorks.sln or D:\Lab Files\VB\Lab 15\Starter\Exercise 02\AdventureWorks.sln, and then click Open.
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; } // Add more operations here and mark them with [OperationContract]
[Visual Basic] <OperationContract()> Public Sub DoWork() ' Add your operation implementation here End Sub ' Add more operations here and mark them with <OperationContract()>
2.
Import the System.Collections.Generic namespace. In the ProductServiceSL.svc.cs or ProductServiceSL.svc.vb window, at the top of the file, add the following code.
[Visual C#] using 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]
<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
5.
Build the solution and fix any errors. In the AdventureWorks Microsoft Visual Studio window, press CTRL+SHIFT+B.
6.
Close Visual Studio 2010. In the AdventureWorks Microsoft Visual Studio window, click the Close button.
Open the AdventureWorks solution from the D:\Lab Files\CS\Lab 15\Starter\Exercise 03 or D:\Lab Files\VB\Lab 15\Starter\Exercise 03 folder. a. b. In the Start Page Microsoft Visual Studio window, on the File menu, click Open Project. In the Open Project dialog box, in the File name box, type D:\Lab Files\CS\Lab 15\Starter\Exercise 03\AdventureWorks.sln or D:\Lab Files\VB\Lab 15\Starter\Exercise 03\AdventureWorks.sln, and then click Open.
In the AdventureWorksSL project, add a service reference to the ProductServiceSL.svc WCF service, with a namespace of AdventureWorks. a. b. In Solution Explorer, right-click AdventureWorksSL, and then click Add Service Reference. In the Add Service Reference dialog box, click the Discover button.
c.
In the Services list, click ProductServiceSL.svc, in the Namespace box, type AdventureWorks, and then click OK.
From the Toolbox, drag a Silverlight DataGrid control to the left side of the page. In the Toolbox, under Common Silverlight Controls, drag a DataGrid control to the left side of the page.
3.
Change the height and width of the UserControl and the Grid control to the following values. Height: 400 Width: 600 a. b. In the Designer, select the Grid control, press and hold down CTRL, and then click the UserControl. In the Properties window, click the Alphabetical button, in the Height box, type 400, in the Width box, type 600, and then press ENTER.
4.
Make the following property changes to the DataGrid control. Name: CategoriesDataGrid Height: 156 Width: 100 AutoGenerateColumns: False a. b. c. In the Designer, select the DataGrid control. In the XAML view, in the opening DataGrid tag, set the value of the Name attribute to CategoriesDataGrid. In the Properties window, in the Height box, type 156, in the Width box, type 100, and ensure the AutoGenerateColumns check box is cleared.
5.
From the Toolbox, drag a Silverlight DataGrid control to the right of the CategoriesDataGrid control on the page. In the Toolbox, under Common Silverlight Controls, drag a DataGrid control to the right of the CategoriesDataGrid control on the page.
6.
Make the following property changes to the DataGrid control. Name: ProductsDataGrid Height: 300 Width: 370 AutoGenerateColumns: False a. b. In the Designer, select the new DataGrid control. In the XAML view, in the opening DataGrid tag, set the value of the Name attribute to ProductsDataGrid.
c. 7. 8.
In the Properties window, in the Height box, type 300, in the Width box, type 370, and ensure the AutoGenerateColumns check box is cleared.
Drag two Silverlight Label controls onto the page. Position them directly above the two DataGrid controls. Make the following changes to the left-most Labels control. Name: CategoryLabel Height: 14 Width: 100 Content: Categories a. b. c. In the Designer, select the left-most Label control. In the XAML view, in the opening Label tag, set the value of the Name attribute to CategoryLabel. 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. b. c. In the Designer, select the right-most Label control. In the XAML view, in the opening Label tag, set the value of the Name attribute to ProductLabel. 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.
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>
a.
In the XAML view, change the self-closing DataGrid element with the Name attribute value of CategoriesDataGrid, to an opening and closing element.
<sdk:DataGrid AutoGenerateColumns="False" Height="156" HorizontalAlignment="Left" Name="CategoriesDataGrid" VerticalAlignment="Top" Width="100" Margin="5,30,0,0"> </sdk:DataGrid>
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.
<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>
a.
In the XAML view, change the self-closing DataGrid element with the Name attribute value of CategoriesDataGrid, to an opening and closing element.
<sdk:DataGrid AutoGenerateColumns="False" Height="300" HorizontalAlignment="Left" Margin="106,30,0,0" Name="ProductsDataGrid" VerticalAlignment="Top" Width="370"> </sdk:DataGrid>
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 <sdk:DataGridTextColumn Number" /> <sdk:DataGridTextColumn <sdk:DataGridTextColumn </sdk:DataGrid.Columns> Binding="{Binding Name}" Header="Name" /> Binding="{Binding ProductNumber}" Header="Product Binding="{Binding Color}" Header="Color" /> Binding="{Binding Size}" Header="Size" />
10
[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 Protected productService As New AdventureWorks.ProductServiceSLClient() ...
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();
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); }
11
[Visual Basic] Public Sub New() InitializeComponent() AddHandler productService.GetProductCategoriesCompleted, AddressOf productService_GetProductCategoriesCompleted AddHandler productService.GetProductsByCategoryCompleted, AddressOf productService_GetProductsByCategoryCompleted End Sub
In the MainPage.xaml.cs or MainPage.xaml.vb window, append the following code to the constructor in the MainPage class.
[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) { } void productService_GetProductCategoriesCompleted(object sender, AdventureWorks.GetProductCategoriesCompletedEventArgs e) { }
[Visual Basic] Private Sub productService_GetProductCategoriesCompleted(ByVal sender As Object, ByVal e As AdventureWorks.GetProductCategoriesCompletedEventArgs) End Sub Private Sub productService_GetProductsByCategoryCompleted(ByVal sender As Object, ByVal e As AdventureWorks.GetProductsByCategoryCompletedEventArgs) End Sub
In the MainPage.xaml.cs or MainPage.xaml.vb window, append the following code to the MainPage class.
12
[Visual C#] void productService_GetProductsByCategoryCompleted(object sender, AdventureWorks.GetProductsByCategoryCompletedEventArgs e) { } void productService_GetProductCategoriesCompleted(object sender, AdventureWorks.GetProductCategoriesCompletedEventArgs e) { }
[Visual Basic] Private Sub productService_GetProductCategoriesCompleted(ByVal sender As Object, ByVal e As AdventureWorks.GetProductCategoriesCompletedEventArgs) End Sub Private Sub productService_GetProductsByCategoryCompleted(ByVal sender As Object, ByVal e As AdventureWorks.GetProductsByCategoryCompletedEventArgs) 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
In the MainPage.xaml.cs or MainPage.xaml.vb window, append the following code to the constructor in the MainPage class.
[Visual C#] productService.GetProductCategoriesAsync();
13
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
In the MainPage.xaml.cs or MainPage.xaml.vb window, add the following code to the productService_GetProductCategoriesCompleted method in the MainPage class.
[Visual C#] 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
In the MainPage.xaml.cs or MainPage.xaml.vb window, add the following code to the CategoriesDataGrid_SelectionChanged method in the MainPage class.
14
3.
The call to GetProductsByCategoryAsync returns to the productService_GetProductsByCategoryCompleted method, where the results returned by the service should be bound to the ItemsSource property of the grid.
[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
In the MainPage.xaml.cs or MainPage.xaml.vb window, add the following code to the productService_GetProductsByCategoryCompleted method in the MainPage class.
[Visual C#] ProductsDataGrid.ItemsSource = e.Result;
4.
15
private void CategoriesDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e) { AdventureWorks.ProductCategory category = CategoriesDataGrid.SelectedItem as AdventureWorks.ProductCategory; productService.GetProductsByCategoryAsync(category.ProductCategoryID); } void productService_GetProductsByCategoryCompleted(object sender, AdventureWorks.GetProductsByCategoryCompletedEventArgs e) { ProductsDataGrid.ItemsSource = e.Result; } 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() Public Sub New() InitializeComponent() AddHandler productService.GetProductCategoriesCompleted, AddressOf productService_GetProductCategoriesCompleted AddHandler productService.GetProductsByCategoryCompleted, AddressOf productService_GetProductsByCategoryCompleted productService.GetProductCategoriesAsync() End Sub Private Sub CategoriesDataGrid_SelectionChanged(ByVal sender As System.Object, ByVal e As System.Windows.Controls.SelectionChangedEventArgs) Dim category As AdventureWorks.ProductCategory = TryCast(CategoriesDataGrid.SelectedItem, AdventureWorks.ProductCategory) productService.GetProductsByCategoryAsync(category.ParentProductCategoryID) End Sub Private Sub productService_GetProductCategoriesCompleted(ByVal sender As Object, ByVal e As AdventureWorks.GetProductCategoriesCompletedEventArgs) CategoriesDataGrid.ItemsSource = e.Result End Sub Private Sub productService_GetProductsByCategoryCompleted(ByVal sender As Object, ByVal e As AdventureWorks.GetProductsByCategoryCompletedEventArgs) ProductsDataGrid.ItemsSource = e.Result End Sub 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
2.
Note: It might take a while to load the data from the WCF service. 3. Select the Bib-Shorts category. In the AdventureWorksSL Windows Internet Explorer window, in the Categories list, click BibShorts.
Note: Notice how the Products list is populated with all the products for the selected category. 4. Close Windows Internet Explorer. 5. In the AdventureWorksSL Windows Internet Explorer window, click the Close button.
Close Visual Studio 2010. In the AdventureWorks Microsoft Visual Studio window, click the Close button.
Task 7: Turn off the virtual machine and revert the changes
1. 2. 3. 4. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Turn Off. In the Turn Off Machine dialog box, click Turn Off. In Hyper-V Manager, in the Virtual Machines pane, right-click 10264A-GEN-DEV, and then click Revert. In the Revert Virtual Machine dialog box, click Revert.