Sie sind auf Seite 1von 763

MCT USE ONLY.

STUDENT USE PROHIBITED

O F F I C I A L

M I C R O S O F T

L E A R N I N G

P R O D U C T

20483A

Programming in Visual C#

MCT USE ONLY. STUDENT USE PROHIBITED

ii

Programming in Visual C#

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. 2012 Microsoft Corporation. All rights reserved.

Microsoft and the trademarks listed at http://www.microsoft.com/about/legal/en/us/IntellectualProperty/Trademarks/EN-US.aspx are trademarks of the Microsoft group of companies. All other trademarks are property of their respective owners.

Product Number: 20483A Part Number (if applicable): Released: xx/20xx

MCT USE ONLY. STUDENT USE PROHIBITED

MICROSOFT LICENSE TERMS OFFICIAL MICROSOFT LEARNING PRODUCTS MICROSOFT OFFICIAL COURSE Pre-Release and Final Release Versions

These license terms are an agreement between Microsoft Corporation and you. Please read them. They apply to the Licensed Content named above, which includes the media on which you received it, if any. These license terms also apply to any updates, supplements, internet based services and support services for the Licensed Content, unless other terms accompany those items. If so, those terms apply. BY DOWNLOADING OR USING THE LICENSED CONTENT, YOU ACCEPT THESE TERMS. IF YOU DO NOT ACCEPT THEM, DO NOT DOWNLOAD OR USE THE LICENSED CONTENT. If you comply with these license terms, you have the rights below. 1. DEFINITIONS.

a. Authorized Learning Center means a Microsoft Learning Competency Member, Microsoft IT Academy Program Member, or such other entity as Microsoft may designate from time to time. b. Authorized Training Session means the Microsoft-authorized instructor-led training class using only MOC Courses that are conducted by a MCT at or through an Authorized Learning Center.

c. Classroom Device means one (1) dedicated, secure computer that you own or control that meets or exceeds the hardware level specified for the particular MOC Course located at your training facilities or primary business location. d. End User means an individual who is (i) duly enrolled for an Authorized Training Session or Private Training Session, (ii) an employee of a MPN Member, or (iii) a Microsoft full-time employee. e. Licensed Content means the MOC Course and any other content accompanying this agreement. Licensed Content may include (i) Trainer Content, (ii) software, and (iii) associated media. f.

Microsoft Certified Trainer or MCT means an individual who is (i) engaged to teach a training session to End Users on behalf of an Authorized Learning Center or MPN Member, (ii) currently certified as a Microsoft Certified Trainer under the Microsoft Certification Program, and (iii) holds a Microsoft Certification in the technology that is the subject of the training session.

g. Microsoft IT Academy Member means a current, active member of the Microsoft IT Academy Program.

h. Microsoft Learning Competency Member means a Microsoft Partner Network Program Member in good standing that currently holds the Learning Competency status. i.

Microsoft Official Course or MOC Course means the Official Microsoft Learning Product instructorled courseware that educates IT professionals or developers on Microsoft technologies.

MCT USE ONLY. STUDENT USE PROHIBITED

j.

Microsoft Partner Network Member or MPN Member means a silver or gold-level Microsoft Partner Network program member in good standing.

k. Personal Device means one (1) device, workstation or other digital electronic device that you personally own or control that meets or exceeds the hardware level specified for the particular MOC Course. l. Private Training Session means the instructor-led training classes provided by MPN Members for corporate customers to teach a predefined learning objective. These classes are not advertised or promoted to the general public and class attendance is restricted to individuals employed by or contracted by the corporate customer.

m. Trainer Content means the trainer version of the MOC Course and additional content designated solely for trainers to use to teach a training session using a MOC Course. Trainer Content may include Microsoft PowerPoint presentations, instructor notes, lab setup guide, demonstration guides, beta feedback form and trainer preparation guide for the MOC Course. To clarify, Trainer Content does not include virtual hard disks or virtual machines. 2. INSTALLATION AND USE RIGHTS. The Licensed Content is licensed not sold. The Licensed Content is licensed on a one copy per user basis, such that you must acquire a license for each individual that accesses or uses the Licensed Content. 2.1 Below are four separate sets of installation and use rights. Only one set of rights apply to you.

a. If you are a Authorized Learning Center: i. If the Licensed Content is in digital format for each license you acquire you may either: 1. install one (1) copy of the Licensed Content in the form provided to you on a dedicated, secure server located on your premises where the Authorized Training Session is held for access and use by one (1) End User attending the Authorized Training Session, or by one (1) MCT teaching the Authorized Training Session, or 2. install one (1) copy of the Licensed Content in the form provided to you on one (1) Classroom Device for access and use by one (1) End User attending the Authorized Training Session, or by one (1) MCT teaching the Authorized Training Session. ii. You agree that: 1. you will acquire a license for each End User and MCT that accesses the Licensed Content, 2. each End User and MCT will be presented with a copy of this agreement and each individual will agree that their use of the Licensed Content will be subject to these license terms prior to their accessing the Licensed Content. Each individual will be required to denote their acceptance of the EULA in a manner that is enforceable under local law prior to their accessing the Licensed Content, 3. for all Authorized Training Sessions, you will only use qualified MCTs who hold the applicable competency to teach the particular MOC Course that is the subject of the training session, 4. you will not alter or remove any copyright or other protective notices contained in the Licensed Content,

5. you will remove and irretrievably delete all Licensed Content from all Classroom Devices and servers at the end of the Authorized Training Session, 6. you will only provide access to the Licensed Content to End Users and MCTs, 7. you will only provide access to the Trainer Content to MCTs, and 8. any Licensed Content installed for use during a training session will be done in accordance with the applicable classroom set-up guide.

b. If you are a MPN Member. i. If the Licensed Content is in digital format for each license you acquire you may either: 1. install one (1) copy of the Licensed Content in the form provided to you on (A) one (1) Classroom Device, or (B) one (1) dedicated, secure server located at your premises where the training session is held for use by one (1) of your employees attending a training session provided by you, or by one (1) MCT that is teaching the training session, or 2. install one (1) copy of the Licensed Content in the form provided to you on one (1) Classroom Device for use by one (1) End User attending a Private Training Session, or one (1) MCT that is teaching the Private Training Session. ii. You agree that: 1. you will acquire a license for each End User and MCT that accesses the Licensed Content, 2. each End User and MCT will be presented with a copy of this agreement and each individual will agree that their use of the Licensed Content will be subject to these license terms prior to their accessing the Licensed Content. Each individual will be required to denote their acceptance of the EULA in a manner that is enforceable under local law prior to their accessing the Licensed Content, 3. for all training sessions, you will only use qualified MCTs who hold the applicable competency to teach the particular MOC Course that is the subject of the training session, 4. you will not alter or remove any copyright or other protective notices contained in the Licensed Content, 5. you will remove and irretrievably delete all Licensed Content from all Classroom Devices and servers at the end of each training session, 6. you will only provide access to the Licensed Content to End Users and MCTs, 7. you will only provide access to the Trainer Content to MCTs, and 8. any Licensed Content installed for use during a training session will be done in accordance with the applicable classroom set-up guide. c. If you are an End User: You may use the Licensed Content solely for your personal training use. If the Licensed Content is in digital format, for each license you acquire you may (i) install one (1) copy of the Licensed Content in the form provided to you on one (1) Personal Device and install another copy on another Personal Device as a backup copy, which may be used only to reinstall the Licensed Content; or (ii) print one (1) copy of the Licensed Content. You may not install or use a copy of the Licensed Content on a device you do not own or control.

MCT USE ONLY. STUDENT USE PROHIBITED

d. If you are a MCT. i. For each license you acquire, you may use the Licensed Content solely to prepare and deliver an Authorized Training Session or Private Training Session. For each license you acquire, you may install and use one (1) copy of the Licensed Content in the form provided to you on one (1) Personal Device and install one (1) additional copy on another Personal Device as a backup copy, which may be used only to reinstall the Licensed Content. You may not install or use a copy of the Licensed Content on a device you do not own or control. ii.

Use of Instructional Components in Trainer Content. You may customize, in accordance with the most recent version of the MCT Agreement, those portions of the Trainer Content that are logically associated with instruction of a training session. If you elect to exercise the foregoing rights, you agree: (a) that any of these customizations will only be used for providing a training session, (b) any customizations will comply with the terms and conditions for Modified Training Sessions and Supplemental Materials in the most recent version of the MCT agreement and with this agreement. For clarity, any use of customize refers only to changing the order of slides and content, and/or not using all the slides or content, it does not mean changing or modifying any slide or content.

2.2 Separation of Components. The Licensed Content components are licensed as a single unit and you may not separate the components and install them on different devices.

2.3 Reproduction/Redistribution Licensed Content. Except as expressly provided in the applicable installation and use rights above, you may not reproduce or distribute the Licensed Content or any portion thereof (including any permitted modifications) to any third parties without the express written permission of Microsoft.

2.4 Third Party Programs. The Licensed Content may contain third party programs or services. These license terms will apply to your use of those third party programs or services, unless other terms accompany those programs and services. 2.5 Additional Terms. Some Licensed Content may contain components with additional terms, conditions, and licenses regarding its use. Any non-conflicting terms in those conditions and licenses also apply to that respective component and supplements the terms described in this Agreement. 3.

PRE-RELEASE VERSIONS. If the Licensed Content is a pre-release (beta) version, in addition to the other provisions in this agreement, then these terms also apply: a. Pre-Release Licensed Content. This Licensed Content is a pre-release version. It may not contain the same information and/or work the way a final version of the Licensed Content will. We may change it for the final version. We also may not release a final version. Microsoft is under no obligation to provide you with any further content, including the final release version of the Licensed Content.

b. Feedback. If you agree to give feedback about the Licensed Content to Microsoft, either directly or through its third party designee, you give to Microsoft without charge, the right to use, share and commercialize your feedback in any way and for any purpose. You also give to third parties, without charge, any patent rights needed for their products, technologies and services to use or interface with any specific parts of a Microsoft software, Microsoft product, or service that includes the feedback. You will not give feedback that is subject to a license that requires Microsoft to license its software, technologies, or products to third parties because we include your feedback in them. These rights

MCT USE ONLY. STUDENT USE PROHIBITED

MCT USE ONLY. STUDENT USE PROHIBITED

survive this agreement.

c. Term. If you are an Authorized Training Center, MCT or MPN, you agree to cease using all copies of the beta version of the Licensed Content upon (i) the date which Microsoft informs you is the end date for using the beta version, or (ii) sixty (60) days after the commercial release of the Licensed Content, whichever is earliest (beta term). Upon expiration or termination of the beta term, you will irretrievably delete and destroy all copies of same in the possession or under your control. 4. INTERNET-BASED SERVICES. Microsoft may provide Internet-based services with the Licensed Content, which may change or be canceled at any time.

a. Consent for Internet-Based Services. The Licensed Content may connect to computer systems over an Internet-based wireless network. In some cases, you will not receive a separate notice when they connect. Using the Licensed Content operates as your consent to the transmission of standard device information (including but not limited to technical information about your device, system and application software, and peripherals) for internet-based services.

b. Misuse of Internet-based Services. You may not use any Internet-based service in any way that could harm it or impair anyone elses use of it. You may not use the service to try to gain unauthorized access to any service, data, account or network by any means. 5. SCOPE OF LICENSE. The Licensed Content is licensed, not sold. This agreement only gives you some rights to use the Licensed Content. Microsoft reserves all other rights. Unless applicable law gives you more rights despite this limitation, you may use the Licensed Content only as expressly permitted in this agreement. In doing so, you must comply with any technical limitations in the Licensed Content that only allows you to use it in certain ways. Except as expressly permitted in this agreement, you may not: install more copies of the Licensed Content on devices than the number of licenses you acquired; allow more individuals to access the Licensed Content than the number of licenses you acquired; publicly display, or make the Licensed Content available for others to access or use; install, sell, publish, transmit, encumber, pledge, lend, copy, adapt, link to, post, rent, lease or lend, make available or distribute the Licensed Content to any third party, except as expressly permitted by this Agreement. reverse engineer, decompile, remove or otherwise thwart any protections or disassemble the Licensed Content except and only to the extent that applicable law expressly permits, despite this limitation; access or use any Licensed Content for which you are not providing a training session to End Users using the Licensed Content; access or use any Licensed Content that you have not been authorized by Microsoft to access and use; or transfer the Licensed Content, in whole or in part, or assign this agreement to any third party.

6.

RESERVATION OF RIGHTS AND OWNERSHIP. Microsoft reserves all rights not expressly granted to you in this agreement. The Licensed Content is protected by copyright and other intellectual property laws and treaties. Microsoft or its suppliers own the title, copyright, and other intellectual property rights in the Licensed Content. You may not remove or obscure any copyright, trademark or patent notices that appear on the Licensed Content or any components thereof, as delivered to you.

MCT USE ONLY. STUDENT USE PROHIBITED

7.

EXPORT RESTRICTIONS. The Licensed Content is subject to United States export laws and regulations. You must comply with all domestic and international export laws and regulations that apply to the Licensed Content. These laws include restrictions on destinations, End Users and end use. For additional information, see www.microsoft.com/exporting. LIMITATIONS ON SALE, RENTAL, ETC. AND CERTAIN ASSIGNMENTS. You may not sell, rent, lease, lend or sublicense the Licensed Content or any portion thereof, or transfer or assign this agreement. SUPPORT SERVICES. Because the Licensed Content is as is, we may not provide support services for it.

8.

9. 10.

TERMINATION. Without prejudice to any other rights, Microsoft may terminate this agreement if you fail to comply with the terms and conditions of this agreement. Upon any termination of this agreement, you agree to immediately stop all use of and to irretrievable delete and destroy all copies of the Licensed Content in your possession or under your control.

11.

LINKS TO THIRD PARTY SITES. You may link to third party sites through the use of the Licensed Content. The third party sites are not under the control of Microsoft, and Microsoft is not responsible for the contents of any third party sites, any links contained in third party sites, or any changes or updates to third party sites. Microsoft is not responsible for webcasting or any other form of transmission received from any third party sites. Microsoft is providing these links to third party sites to you only as a convenience, and the inclusion of any link does not imply an endorsement by Microsoft of the third party site. ENTIRE AGREEMENT. This agreement, and the terms for supplements, updates and support services are the entire agreement for the Licensed Content.

12.

13.

APPLICABLE LAW. a. United States. If you acquired the Licensed Content in the United States, Washington state law governs the interpretation of this agreement and applies to claims for breach of it, regardless of conflict of laws principles. The laws of the state where you live govern all other claims, including claims under state consumer protection laws, unfair competition laws, and in tort. b. Outside the United States. If you acquired the Licensed Content in any other country, the laws of that country apply.

14.

LEGAL EFFECT. This agreement describes certain legal rights. You may have other rights under the laws of your country. You may also have rights with respect to the party from whom you acquired the Licensed Content. This agreement does not change your rights under the laws of your country if the laws of your country do not permit it to do so.

15.

DISCLAIMER OF WARRANTY. THE LICENSED CONTENT IS LICENSED "AS-IS," "WITH ALL FAULTS," AND "AS AVAILABLE." YOU BEAR THE RISK OF USING IT. MICROSOFT CORPORATION AND ITS RESPECTIVE AFFILIATES GIVE NO EXPRESS WARRANTIES, GUARANTEES, OR CONDITIONS UNDER OR IN RELATION TO THE LICENSED CONTENT. YOU MAY HAVE ADDITIONAL CONSUMER RIGHTS UNDER YOUR LOCAL LAWS WHICH THIS AGREEMENT CANNOT CHANGE. TO THE EXTENT PERMITTED UNDER YOUR LOCAL LAWS, MICROSOFT CORPORATION AND ITS RESPECTIVE AFFILIATES EXCLUDE ANY IMPLIED WARRANTIES OR CONDITIONS, INCLUDING THOSE OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.

MCT USE ONLY. STUDENT USE PROHIBITED

16.

LIMITATION ON AND EXCLUSION OF REMEDIES AND DAMAGES. TO THE EXTENT NOT PROHIBITED BY LAW, YOU CAN RECOVER FROM MICROSOFT CORPORATION AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO USD$5.00. YOU AGREE NOT TO SEEK TO RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES FROM MICROSOFT CORPORATION AND ITS RESPECTIVE SUPPLIERS.

This limitation applies to o anything related to the Licensed Content, services made available through the Licensed Content, or content (including code) on third party Internet sites or third-party programs; and o claims for breach of contract, breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by applicable law. It also applies even if Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your country may not allow the exclusion or limitation of incidental, consequential or other damages.

Please note: As this Licensed Content is distributed in Quebec, Canada, some of the clauses in this agreement are provided below in French. Remarque : Ce le contenu sous licence tant distribu au Qubec, Canada, certaines des clauses dans ce contrat sont fournies ci-dessous en franais.

EXONRATION DE GARANTIE. Le contenu sous licence vis par une licence est offert tel quel . Toute utilisation de ce contenu sous licence est votre seule risque et pril. Microsoft naccorde aucune autre garantie expresse. Vous pouvez bnficier de droits additionnels en vertu du droit local sur la protection dues consommateurs, que ce contrat ne peut modifier. La ou elles sont permises par le droit locale, les garanties implicites de qualit marchande, dadquation un usage particulier et dabsence de contrefaon sont exclues. LIMITATION DES DOMMAGES-INTRTS ET EXCLUSION DE RESPONSABILIT POUR LES DOMMAGES. Vous pouvez obtenir de Microsoft et de ses fournisseurs une indemnisation en cas de dommages directs uniquement hauteur de 5,00 $ US. Vous ne pouvez prtendre aucune indemnisation pour les autres dommages, y compris les dommages spciaux, indirects ou accessoires et pertes de bnfices. Cette limitation concerne: tout ce qui est reli au le contenu sous licence , aux services ou au contenu (y compris le code) figurant sur des sites Internet tiers ou dans des programmes tiers ; et les rclamations au titre de violation de contrat ou de garantie, ou au titre de responsabilit stricte, de ngligence ou dune autre faute dans la limite autorise par la loi en vigueur.

Elle sapplique galement, mme si Microsoft connaissait ou devrait connatre lventualit dun tel dommage. Si votre pays nautorise pas lexclusion ou la limitation de responsabilit pour les dommages indirects, accessoires ou de quelque nature que ce soit, il se peut que la limitation ou lexclusion ci-dessus ne sappliquera pas votre gard.

EFFET JURIDIQUE. Le prsent contrat dcrit certains droits juridiques. Vous pourriez avoir dautres droits prvus par les lois de votre pays. Le prsent contrat ne modifie pas les droits que vous confrent les lois de votre pays si celles-ci ne le permettent pas. Revised December 2011

MCT USE ONLY. STUDENT USE PROHIBITED

Programming in Visual C#

MCT USE ONLY. STUDENT USE PROHIBITED


xi

Programming in Visual C#

Acknowledgments

Microsoft Learning wants to acknowledge and thank the following for their contribution toward developing this title. Their effort at various stages in the development has ensured that you have a good classroom experience.

Lin Joyner Content Developer

Lin Joyner is an experienced .NET Framework application developer and SQL Server expert. She has been working with the .NET Framework since it was first released and specializes in data access solutions with ADO.NET, LINQ, and the Entity Framework. Lin has been writing training courses and other instructional content for Microsoft for over 12 years.

John Sharp Subject Matter Expert

John Sharp gained an honors degree in Computing from Imperial College, London. He has been developing software and writing training courses, guides, and books for over 25 years. John has experience in a wide range of technologies, from database systems and UNIX through to C, C++ and C# applications for the .NET Framework, together with Java and JavaScript development. He has authored several books for Microsoft Press, including six editions of C# Step By Step, Windows Communication Foundation Step By Step, and the J# Core Reference.

Jason Lee Subject Matter Expert

Jason Lee is a Principal Technologist with Content Master where he has been working with Microsoft products and technologies, especially SharePoint, Visual C#, and ASP.NET, for several years. Jason holds a PhD in computing and is currently MCPD and MCTS certified

Antony Norris Subject Matter Expert

Antony Norris is a Senior Technologist with Content Master where he has been working with Microsoft products and technologies, especially Visual C# and ASP.NET MVC, for several years. Antony is an experienced developer who has contributed to many successful solutions. Antony has also authored Microsoft Learning courses on a variety of technologies, such as Windows Mobile, Windows Communication Foundation (WCF), and Visual C#. Antony is currently MCTS certified.

Carsten Thomsen Technical Reviewer

Carsten Thomsen is currently doing SharePoint 2010 development, but his interests are varied when it comes to IT and includes development of ASP.NET, Windows Forms, Windows Store, Windows Phone and other types of applications and components. He has authored a number of development books as well as over 20 Microsoft Learning courses.

MCT USE ONLY. STUDENT USE PROHIBITED

xii

Programming in Visual C#

Contents
Module 1: Review of Visual C# Syntax
Lesson 1: Overview of Writing Applications by Using Visual C# Lesson 2: Data Types, Operators, and Expressions Lesson 3: Visual C# Programming Language Constructs Lab: Developing the Class Enrollment Application page 3 page 11 page 25 page 38

Module 2: Creating Methods, Handling Exceptions, and Monitoring Applications


Lesson 1: Creating and Invoking Methods Lesson 2: Creating Overloaded Methods and Using Optional and Output Parameters Lesson 3: Handling Exceptions Lesson 4: Monitoring Applications Lab: Extending the Class Enrollment Application Functionality page 3 page 13 page 20 page 27 page 36

Module 3: Developing the Code for a Graphical Application


Lesson 1: Implementing Structs and Enums Lesson 2: Organizing Data into Collections Lesson 3: Handling Events Lab: Writing the Code for the Grades Prototype Application page 3 page 17 page 31 page 41

Module 4: Creating Classes and Implementing Type-Safe Collections


Lesson 1: Creating Classes Lesson 2: Defining and Implementing Interfaces Lesson 3: Implementing Type-Safe Collections Lab: Adding Data Validation and Type-Safety to the Application page 3 page 18 page 31 page 49

Module 5: Creating a Class Hierarchy by Using Inheritance


Lesson 1: Creating Class Hierarchies Lesson 2: Extending .NET Framework Classes Lab: Refactoring Common Functionality into the User Class page 3 page 17 page 29

Module 6: Reading and Writing Local Data


Lesson 1: Reading and Writing Files Lesson 2: Serializing and Deserializing Data Lesson 3: Performing I/O by Using Streams Lab: Generating the Grades Report page 3 page 17 page 33 page 44

Module 7: Accessing a Database


Lesson 1: Creating and Using Entity Data Models Lesson 2: Querying Data by Using LINQ page 3 page 16

MCT USE ONLY. STUDENT USE PROHIBITED


xiii

Programming in Visual C#

Lab: Retrieving and Modifying Grade Data

page 28

Module 8: Accessing Remote Data


Lesson 1: Accessing Data Across the Web Lesson 2: Accessing Data in the Cloud Lab: Retrieving and Modifying Grade Data in the Cloud page 3 page 19 page 34

Module 9: Designing the User Interface for a Graphical Application


Lesson 1: Using XAML to Design a User Interface Lesson 2: Binding Controls to Data Lesson 3: Styling a User Interface Lab: Customizing Student Photographs and Styling the Application page 3 page 19 page 30 page 39

Module 10: Improving Application Performance and Responsiveness


Lesson 1: Implementing Multitasking Lesson 2: Performing Operations Asynchronously Lesson 3: Synchronizing Concurrent Access to Data Lab: Improving the Responsiveness and Performance of the Application page 3 page 20 page 36 page 46

Module 11: Integrating with Unmanaged Code


Lesson 1: Creating and Using Dynamic Objects Lesson 2: Managing the Lifetime of Objects and Controlling Unmanaged Resources Lab: Upgrading the Grades Report page 3 page 12 page 20

Module 12: Creating Reusable Types and Assemblies


Lesson 1: Examining Object Metadata Lesson 2: Creating and Using Custom Attributes Lesson 3: Generating Managed Code Lesson 4: Versioning, Signing, and Deploying Assemblies Lab: Specifying the Data to Include in the Grades Report page 3 page 16 page 26 page 36 page 49

Module 13: Encrypting and Decrypting Data


Lesson 1: Implementing Symmetric Encryption Lesson 2: Implementing Asymmetric Encryption Lab: Encrypting and Decrypting the Grades Report page 3 page 15 page 26

Lab Answer Keys


Module 1 Lab: Developing the Class Enrollment Application Module 2 Lab: Extending the Class Enrollment Application Module 3 Lab: Writing the Code for the Grades Prototype Application page 1 page 1 page 1

MCT USE ONLY. STUDENT USE PROHIBITED

xiv

Programming in Visual C#

Module 4 Lab: Adding Data Validation and Type-Safety to the Application Module 5 Lab: Refactoring Common Functionality into the User Class Module 6 Lab: Generating the Grades Report Module 7 Lab: Retrieving and Modifying Grade Data Module 8 Lab: Retrieving and Modifying Grade Data in the Cloud Module 9 Lab: Customizing Student Photographs and Styling the Application Module 10 Lab: Improving the Responsiveness and Performance of the Application Module 11 Lab: Upgrading the Grades Report Module 12 Lab: Specifying the Data to Include in the Grades Report Module 13 Lab: Encrypting and Decrypting the Grades Report

page 1 page 1 page 1 page 1 page 1 page 1 page 1 page 1 page 1 page 1

MCT USE ONLY. STUDENT USE PROHIBITED


i

About This Course

About This Course


Course Description

This section provides a brief description of the course, audience, suggested prerequisites, and course objectives.

Note: This first release (A) MOC version of course 20483A has been developed on RTM software. Microsoft Learning will release a B version of this course with enhanced PowerPoint slides, copyedited content, and Course Companion content on Microsoft Learning site.

This training course teaches developers the programming skills that are required for developers to create Windows applications using the Visual C# language. During their five days in the classroom students review the basics of Visual C# program structure, language syntax, and implementation details, and then consolidate their knowledge throughout the week as they build an application that incorporates several features of the .NET Framework 4.5.

Audience

This course is intended for experienced developers who already have programming experience in C, C++, JavaScript, Objective-C, Microsoft Visual Basic, or Java and understand the concepts of object-oriented programming. The developers targeted by this training are professional developers who have 3-6 months of experience creating software applications for a production environment and who have a basic understanding of Windows client application development. Students should have a minimum of the following experience: 3 months of experience creating .NET Framework applications. 1 month of experience using Visual Studio 2010 or Visual Studio 2012.

This course is not designed for students who are new to programming; it is targeted at professional developers with at least one month of experience programming in an object-oriented environment.

Student Prerequisites
Before attending this course, students must have at least three months professional development experience.

Additionally, developers attending this should already have gained some limited experience using Visual C# to complete basic programming tasks. More specifically, students should have hands-on experience using Visual C# that demonstrates their understanding of the following: How to name, declare, initialize and assign values to variables within an application. How to use: o o o

Arithmetic operators to perform arithmetic calculations involving one or more variables. Relational operators to test the relationship between two variables or expressions. Logical operators to combine expressions that contain relational operators.

How to create the code syntax for simple programming statements using Visual C# language keywords and recognize syntax errors by using the Visual Studio IDE.

MCT USE ONLY. STUDENT USE PROHIBITED

ii

About This Course

How to create a simple branching structure using an if statement.

How to create a simple looping structure using a for statement to iterate through a data array. How to use the Visual Studio IDE to locate simple logic errors. How to create a method that accepts arguments and returns a value of a specified type. How to design and build a simple user interface by using standard controls from the Visual Studio toolbox. How to connect to a SQL Server database and the basics of how to retrieve and store data. How to sort data in a loop. How to recognize the classes and methods used in a program.

Course Objectives
After completing this course, students will be able to: Describe the core syntax and features of Visual C#.

Create methods, handle exceptions, and describe the monitoring requirements of large-scale applications. Implement the basic structure and essential elements of a typical desktop application. Create classes, define and implement interfaces, and create and use generic collections. Use inheritance to create a class hierarchy and to extend a .NET Framework class.

Read and write data by using file input/output and streams, and serialize and deserialize data in different formats. Create and use an entity data model for accessing a database and use LINQ to query data.

Access and query remote data by using the types in the System.Net namespace and WCF Data Services. Build a graphical user interface by using XAML.

Improve the throughput and response time of applications by using tasks and asynchronous operations. Integrate unmanaged libraries and dynamic components into a Visual C# application.

Examine the metadata of types by using reflection, create and use custom attributes, generate code at runtime, and manage assembly versions. Encrypt and decrypt data by using symmetric and asymmetric encryption.

Course Outline
The course outline is as follows: Module 1, Review of Visual C# Syntax" Module 2, Creating Methods, Handling Exceptions, and Monitoring Applications" Module 3, Developing the Code for a Graphical Application" Module 4, Creating Classes and Implementing Type-Safe Collections"

MCT USE ONLY. STUDENT USE PROHIBITED


iii

About This Course

Module 5, Creating a Class Hierarchy by Using Inheritance" Module 6, Reading and Writing Local Data" Module 7, Accessing a Database" Module 8, Accessing Remote Data" Module 9, Designing the User Interface for a Graphical Application" Module 10, Improving Application Performance and Responsiveness" Module 11, Integrating with Unmanaged Code" Module 12, Creating Reusable Types and Assemblies" Module 13, Encrypting and Decrypting Data"

Course Materials

The following materials are included with your kit:

Course Handbook: a succinct classroom learning guide that provides the critical technical information in a crisp, tightly-focused format, which is essential for an effective in-class learning experience.

Lessons: guide you through the learning objectives and provide the key points that are critical to the success of the in-class learning experience. Labs: provide a real-world, hands-on platform for you to apply the knowledge and skills learned in the module. Module Reviews and Takeaways: provide on-the-job reference material to boost knowledge and skills retention. Lab Answer Keys: provide step-by-step lab solution guidance.

Course Companion Content: searchable, easy-to-browse digital content with integrated premium online resources that supplement the Course Handbook.

Modules: include companion content, such as questions and answers, detailed demo steps and additional reading links, for each lesson. Additionally, they include Lab Review questions and answers and Module Reviews and Takeaways sections, which contain the review questions and answers, best practices, common issues and troubleshooting tips with answers, and real-world issues and scenarios with answers.

Resources: include well-categorized additional resources that give you immediate access to the most current premium content on TechNet, MSDN, or Microsoft Press. Note: For this version of the Courseware on Prerelease Software, Companion Content is not available. However, the Companion Content will be published when the next (B) version of this course is released, and students who have taken this course will be able to download the Companion Content at that time from the http://www.microsoft.com/learning/companionmoc site. Please check with your instructor when the B version of this course is scheduled to release to learn when you can access Companion Content for this course.

Student Course files: includes the Allfiles.exe, a self-extracting executable file that contains all

MCT USE ONLY. STUDENT USE PROHIBITED

iv

About This Course

required files for the labs and demonstrations.

Note: For this version of the Courseware on Prerelease Software, Allfiles.exe file is not available. However, this file will be published when the next (B) version of this course is released, and students who have taken this course will be able to download the Allfiles.exe at that time from the http://www.microsoft.com/learning/companionmoc site.

Course evaluation: at the end of the course, you will have the opportunity to complete an online evaluation to provide feedback on the course, training facility, and instructor. To provide additional comments or feedback on the course, send an email to support@mscourseware.com. To inquire about the Microsoft Certification Program, send an email to mcphelp@microsoft.com.

MCT USE ONLY. STUDENT USE PROHIBITED


v

About This Course

Virtual Machine Environment


Virtual Machine Configuration

This section provides the information for setting up the classroom environment to support the business scenario of the course.

In this course, you will use Microsoft Hyper-V to perform the labs. Important: At the end of each lab, you must close the virtual machine and must not save any changes. To close a virtual machine (VM) without saving the changes, perform the following steps: 1. On the virtual machine, on the Action menu, click Close. 2. In the Close dialog box, in the What do you want the virtual machine to do? list, click Turn off and delete changes, and then click OK. The following table shows the role of each virtual machine that is used in this course: Virtual machine MSL-TMG1 20483A-SEA-DEV11-<Module #> Role Gateway computer for Internet access Development computer used for building web applications. Each module uses a different copy of this virtual machine, called 20483A-SEA-DEV-01 for module 1, 20483A-SEA-DEV11-02 for module 2, and so on.

Software Configuration
The following software is installed on each VM:

Microsoft Windows 8 Enterprise Microsoft Visual Studio 2012 Ultimate Microsoft Office Professional Plus 2010

Course Files
The files associated with the labs in this course are located in the E:\Labfiles folder on each virtual machine.

Classroom Setup
Each classroom computer will have the same virtual machines configured in the same way.

Course Hardware Level

To ensure a satisfactory student experience, Microsoft Learning requires a minimum equipment configuration for trainer and student computers in all Microsoft Certified Partner for Learning Solutions (CPLS) classrooms in which Official Microsoft Learning Product courseware is taught.

MCT USE ONLY. STUDENT USE PROHIBITED

vi

About This Course

Hardware Level 6+

Intel Virtualization Technology (Intel VT) or AMD Virtualization (AMD-V) processor Dual 120 GB hard disks 7200 RM SATA or better* 8GB or higher DVD drive Network adapter with Internet connectivity Super VGA (SVGA) 17-inch monitor Microsoft Mouse or compatible pointing device Sound card with amplified speakers

*Striped

In addition, the instructor computer must be connected to a projection display device that supports SVGA 1024 x 768 pixels, 16 bit colors.

1-1

Module 1
Review of Visual C# Syntax
Contents:
Module Overview Lesson 1: Overview of Writing Application by Using Visual C# Lesson 2: Data Types, Operators, and Expressions Lesson 3: Visual C# Programming Language Constructs Lab: Developing the Class Enrollment Application Module Review and Takeaways 1-2 1-3 1-11 1-25 1-38 1-50

1-2

Review of f Visual C# Syntax

Modu ule Ove erview

ive development platform that you The Microsoft .NET Framew work version 4 4.5 provides a comprehensi can use to build d, deploy, and manage app plications and services. By using the .NET T Framework, y you can cre eate visually c compelling ap pplications, enable seamless s communicat tion across tec chnology bou undaries, and provide sup pport for a wid de range of b business proce esses. you will learn about some of the core fe eatures provid ded by the .NE ET Framework k and In this module, y Mi icrosoft Visual Studio. Yo ou will also lea arn about som me of the core Visual C# c constructs tha at enable you to start dev veloping .NET Framework a applications.

Ob bjectives
Aft ter completing this module e, you will be able to: e of .NET Fram mework applic cations and th he features tha at Visual Stud dio 2012 Describe the architecture C provide. and Visual C# Use basic Visual V C# data types, operat tors, and expr ressions. Use standar rd Visual C# constructs. c

Programming g in Visual C#

1-3 3

Lesson 1

Over rview of Writin ng App plication n by Us sing Vis sual C#

The .NET Fram T mework 4.5 an nd Visual Stud dio provide many features that t you can use u when dev veloping your a applications. In this lesson, you will learn I n about the fe eatures that Visual Studio 2 2012 and the . .NET Framewo ork 4.5 p provide that e enable you to create your o own applicatio ons.

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Describe the purpose o of the .NET Fr ramework. Describe the key features of Visual S Studio 2012. Describe the project te emplates prov vided in Visual Studio 2012. Create a . .NET Framewo ork applicatio on.

1-4

Review of f Visual C# Syntax

W What Is the e .NET Framework?

The .NET Frame ework 4.5 prov vides a compr rehensive dev velopment pla atform that of ffers a fast and d efficient wa ay to build applications and d services. By using Visual S Studio 2012, you y can use th he .NET Frame ework 4.5 to create a wide e range of solu utions that op perate across a broad range e of computin ng devices. The .NET Frame ework 4.5 prov vides three pr rincipal eleme ents: The Commo on Language Runtime (CLR R). The .NET Fr ramework clas ss library. A collection n of developm ment framewo orks.

Th he Common n Language e Runtime


The .NET Frame ework provide es an environm ment called th he CLR. The CL LR manages the execution of code and simplifies th he developme ent process by y providing a robust and hi ighly secure e execution environment tha at includes: anagement. Memory ma Transaction ns. Multithread ding.

Th he .NET Fra amework Cl lass Library y


The .NET Frame ework provide es a library of reusable class ses that you ca an use to buil ld application ns. The cla asses provide a foundation of common f functionality and a constructs s that help to simplify application de evelopment by y, in part, elim minating the n need to consta antly reinvent logic. For exa ample, the Sy ystem.IO.File class contains s functionality y that enables s you to manip pulate files on n the Window ws file sys stem. In addit tion to using t the classes in t the .NET Fram mework class library, you ca an extend thes se classes by y creating your own librarie es of classes.

De evelopmen nt Framewo orks


The .NET Frame ework provide es several deve elopment fram meworks that you can use to t build comm mon ap pplication type es, including: Desktop clie ent applicatio ons, by using W Windows Pres sentation Foundation (WPF F).

Programming in Visual C# 1-5

Windows 8 desktop applications, by using XAML. Server-side web applications, by using Active Server Pages (ASP.NET) Web Forms or ASP.NET MVC. Service-oriented web applications, by using Windows Communication Foundation (WCF). Long-running applications, by using Windows services.

Each framework provides the necessary components and infrastructure to get you started. Additional Reading: For more information about the .NET Framework, see the Overview of the .NET Framework page at http://go.microsoft.com/fwlink/?LinkID=267639.

1-6

Review of f Visual C# Syntax

Ke ey Feature es of Visua al Studio 2012

Vis sual Studio 20 012 provides a single development envir ronment that enables you t to rapidly design, implement, build, test, and deploy various types of applications and components by using a ran nge of pro ogramming la anguages. Some of the key y features of V Visual Studio 2 2012 are: Intuitive int tegrated deve elopment envi ironment (IDE E). The Visual Studio 2012 IDE provides a all of the features and d tools that are necessary t to design, imp plement, build d, test, and de eploy applicat tions and component ts. Rapid application develo opment. Visua al Studio 2012 2 provides des sign views for graphical com mponents that enable e you to easily y build comple ex user interfa aces. Alternatively, you can use the Code e Editor views, which provide mo ore control but are not as ea asy to use. Vis sual Studio 20 012 also provi ides wizards that help sp peed up the d development o of particular components. c Server and data access. Visual V Studio 2 2012 provides s the Server Ex xplorer, which h enables you to log on to servers and explore th heir databases s and system s services. It also o provides a f familiar way to o create, access, and modify datab bases that you ur application uses by using g the new tab ble designer. Internet Inf formation Serv vices (IIS) Express. Visual Studio 2012 pro ovides a lightw weight version of IIS as the default web server fo or debugging your web app plications. Debugging features. Visu ual Studio 201 12 provides a debugger tha at enables you u to step thro ough local or remote c code, pause at t breakpoints, , and follow e execution path hs. Error handling. Visual Stu udio 2012 pro ovides the Error List windo ow, which disp plays any errors, warnings, o or messages th hat are produced as you ed dit and build y your code. Help and do ocumentation n. Visual Studi io 2012 provid des help and guidance thro ough Microso oft IntelliSense, code snipp pets, and the integrated he elp system, wh hich contains documentatio on and samples.

Additiona al Reading: F For more infor rmation about what is new in Visual Stud dio 2012, see the e What's New w in Visual St tudio 2012 p page at http:// /go.microsoft. .com/fwlink/? ?LinkID=26776 68.

Programming g in Visual C#

1-7 7

T Templates s in Visual Studio 2 2012

Visual Studio 2012 support V ts the develop pment of diffe erent types of applications such as Windows-based c client applicat tions, web-based applicatio ons, services, and a libraries. T To help you get g started, Visual Studio 2 2012 provides s application t templates tha at provide a st tructure for th he different ty ypes of applica ations. These t templates: Provide starter code th hat you can bu uild on to quickly create fu unctioning app plications. Include su upporting com mponents and d controls tha at are relevant t to the projec ct type. Configure e the Visual St tudio 2012 ID DE to the type of application that you are e developing. Add refer rences to any initial assemb blies that this type of applic cation usually y requires.

T Types of Te emplates
The following table describ T bes some of th he common application tem mplates that y you might use e when you d develop .NET Framework applications by y using Visual l Studio 2012. . Template Console Application Descript tion Provides s the environm ment settings, , tools, projec ct references, a and starter co ode to devel lop an applica ation that runs in a comma and-line interf face. This type e of applicat tion is conside ered lightweig ght because th here is no graphical user interface e. Provides s the environm ment settings, , tools, projec ct references, a and starter co ode to build a graphical W Windows Form ms application n. Provides s the environm ment settings, , tools, projec ct references, a and starter co ode to build a rich graphical Windows application. A WPF applica ation enables you Windows applications, with much more to create e the next generation of W control over user inte erface design. Provides s the environm ment settings, , tools, projec ct references, a and starter co ode to build a rich graphical application targeted at the Windows s 8 operating ns enable you to reuse skills s obtained fro om system. Windows Store application velopment by y using XAML and Visual C# #, but also fro om web WPF dev develop pment by using HTML 5, CS SS 3.0, and Jav vaScript.

Windows Fo orms Application WPF Applic cation

Windows St tore

1-8

Review of Visual C# Syntax

Template Class Library

Description Provides the environment settings, tools, and starter code to build a .dll assembly. You can use this type of file to store functionality that you might want to invoke from many other applications. Provides the environment settings, tools, project references, and starter code to create a server-side, compiled ASP.NET web application. Provides the environment settings, tools, project references, and starter code to create a Model-View-Controller (MVC) Web application. An ASP.NET MVC web application differs from the standard ASP.NET web application in that the application architecture helps you separate the presentation layer, business logic layer, and data access layer. Provides the environment settings, tools, project references, and starter code to build Service Orientated Architecture (SOA) services.

ASP.NET Web Application ASP.NET MVC 4 Application

WCF Service Application

Programming g in Visual C#

1-9 9

C Creating a .NET Fra amework A Applicatio on

The applicatio T on templates provided in Visual V Studio 2 2012 enable you to start cre eating an app plication with m minimal effort. You can the en add your code and custo omize the pro oject to meet your own req quirements. T following steps describ The be how to crea ate a console application: 1 1. 2 2. 3 3. Open Visual Studio 2012. In Visual Studio, on the e File menu, p point to New, and then clic ck Project. In the Ne ew Project dia alog box, do the t following: : a. b. c. d. 4 4. 5 5. Expand Template es, Visual C#, and then click k Windows. Click the Console Application template. In the e Name box, specify a nam me for the pro oject. In the e Location bo ox, specify the e path where you want to s save the proje ect.

Click OK. The Code e Editor window now show ws the default Program class, which contains the entr ry point method f for the applica ation.

The following code example shows the d T default Progr ram class that t Visual Studio o provides when you use t Console A the Application t template. P Program Clas ss
using Syste em; using Syste em.Collectio ons.Generic; using Syste em.Linq; using Syste em.Text; using Syste em.Threading g.Tasks; namespace C ConsoleApplication1 { class Pr rogram { stat tic void Main(string[] args) { } }

1-10

Review of Visual C# Syntax

After you create a project, you can then use the features that Visual Studio provides to create your application.

Programmer Productivity Features


Visual Studio 2012 provides a host of features that can help you to write code. When writing code, you need to recall information about many program elements. Instead of manually looking up information by searching help files or other source code, the IntelliSense feature in Visual Studio provides the information that you need directly from the editor. IntelliSense provides the following features: The Quick Info option displays the complete declaration for any identifier in your code. Move the mouse so that the pointer rests on an identifier to display Quick Info for that identifier, which appears in a yellow pop-up box. The Complete Word option enters the rest of a variable, command, or function name after you have typed enough characters to disambiguate the term. Type the first few letters of the name and then press Alt+Right Arrow or Ctrl+Spacebar to complete the word.

Programming in i Visual C#

1-11 1

Lesson 2

Data Types, , Opera ators, an nd Expr ressions

All application A ns use data. This data migh ht be supplied d by the user t through a use er interface, fro om a d database, from m a network s service, or from some other r source. To st tore and use data d in your applications, a y must fam you miliarize yourse elf with how t to define and use variables and how to create c and use e expressions w the varie with ety of operators that Visual C# provides. In this lesson, you will learn I n how to use some s of the fu undamental constructs c in V Visual C#, such as variables, t type member rs, casting, and d string manip pulation.

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Describe the data type es provided by y Visual C#. Create an nd use express sions. Declare a and assign var riables. Access type members. Cast data a from one typ pe to another. Concaten nate and validate strings.

1-12 Review of Visual C# Syntax x

W What are Data D Types s?

A variable v holds s data of a spe ecific type. When you decla are a variable to store data in an applica ation, you ne eed to choose an appropria ate data type for f that data. Visual C# is a type-safe lan nguage, which h means tha at the compile er guarantees s that values stored in varia ables are alway ys of the appr ropriate type.

Co ommonly Used U Data T Types


. The following ta able shows the commonly u used data typ pes in Visual C#, C and their characteristics c T Type i int l long f float d double Desc cription Who ole numbers Who ole numbers (bigger range) Floa ating-point mbers num Dou uble precision (more accurate) ting-point float num mbers Mon netary values Sing gle character Boolean Mom ments in time Sequ uence of char racters Size (b bytes) 4 8 4 8 Range 2,147,483,648 to 2,147 7,483,647 9,223,372,036,854,775 5,808 to 9,223,372,036,854,775,807 +/3.4 1 10^38 +/1.7 1 10^308

d decimal c char b bool D DateTime s string

16 2 1 8 2 per character

28 signific cant figures N/A True or false 0:00:00 on n 01/01/2001 to 23:59:59 o on 12/31/9999 N/A

Programming in Visual C# 1-13

Additional Reading: For more information about data types, see the Reference Tables for Types (C# Reference) page at http://go.microsoft.com/fwlink/?LinkID=267770.

1-14 Review of Visual C# Syntax x

Ex xpressions s and Ope erators in V Visual C#

Expressions are a central com mponent of pr ractically every y Visual C# ap pplication, bec cause express sions are the e fundamenta al constructs t that you use to evaluate an nd manipulate e data. Express sions are colle ections of op perands and o operators, whic ch you can de efine as follow ws: Operands a are values, for example, num mbers and str rings. They can n be constant t (literal) value es, variables, properties, or r return values from method calls. define operati ions to perfor rm on operand ds, for examp ple, addition o or multiplicatio on. Operators d Operators e exist for all of the basic mat thematical op perations, as w well as for more advanced o operations such as logical compariso on or the man nipulation of t the bits of dat ta that constit tute a value.

All l expressions are a evaluated to a single va alue when you ur application n runs. The typ pe of value that an expression prod duces depends on the types s of the opera ands that you use and the o operators that t you use. There is no limit t to the length h of expressio ons in Visual C C# application ns, although in n practice, you u are lim mited by the m memory of your computer and a your patience when ty yping. Howeve er, it is usually y advisable to use shorter expressions an nd assemble th he results of expression-pro e ocessing piece emeal. This m makes it easier for you to o see what your code is doing, as well as s making it easier to debug g your code.

Op perators in Visual C#
Op perators comb bine operands s together into expressions s. Visual C# pr rovides a wide e range of ope erators that you can use to p perform most t fundamental mathematica al and logical operations. O Operators fall into the fol llowing three categories: Unary. This type of opera ator operates on a single operand. For e example, you can c use the - operator as e it immediately before a numeric a unary ope erator. To do this, you place n opera and, and it converts the value of the e operand to its current val lue multiplied d by 1. Binary. This s type of opera and operates on two value es. This is the m most common n type of operator, for example, *, which multip plies the value e of two opera ands. Ternary. There is only on ne ternary ope erator in Visua al C#. This is the ? : operato or that is used d in conditional expressions.

The following ta able shows the operators th hat you can use in Visual C# #, grouped by y type. T Type Operators

Programming in Visual C# 1-15

Type Arithmetic Increment, decrement Comparison String concatenation Logical/bitwise operations Indexing (counting starts from element 0) Casting Assignment Bit shift Type information Delegate concatenation and removal Overflow exception control Indirection and Address (unsafe code only) Conditional (ternary operator)

Operators +, -, *, /, % ++, -==, !=, <, >, <=, >=, is + &, |, ^, !, ~, &&, || [] ( ), as =, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, ?? <<, >> sizeof, typeof +, checked, unchecked *, ->, [ ], & ?:

Expression Examples
You can combine the basic building blocks of operators and operands to make expressions as simple or as complex as you like. The following code example shows how to use the + operator. + Operator
a + 1

The + operator can operate on different data types, and the result of this expression depends on the data types of the operands. For example, if a is an integer, the result of the expression is an integer with the value 1 greater than a. If a is a double, the result is a double with the value 1 greater than a. The difference is subtle but important. In the second case (a is a double), the Visual C# compiler has to generate code to convert the constant integer value 1 into the constant double value 1 before the expression can be evaluated. The rule is that the type of the expression is the same as the type of the operands, although one or more of the operands might need to be converted to ensure that they are all compatible. The following code example shows how to use the / operator to divide two int values. / Operator
5 / 2

The value of the result is the integer value 2 (not 2.5). If you convert one of the operands to a double, the Visual C# compiler will convert the other operand to a double, and the result will be a double.

1-16

Review of Visual C# Syntax

The following code example shows how to use the / operator to divide a double value by an int value. / Operator
5.0 / 2

The value of the result now is the double value 2.5. You can continue building up expressions with additional values and operators. The following code example shows how use the + and operators in an expression. + and Operators
a + b - 2

This expression evaluates to the sum of variables a and b with the value 2 subtracted from the result. Some operators, such as +, can be used to evaluate expressions that have a range of types. The following code example shows how to use the + operator to concatenate two string values. + Operator
"ApplicationName: " + appName.ToString()

The + operator uses an operand that is a result of a method call, ToString(). The ToString() method converts the value of a variable into a string, whatever type it is. The .NET Framework class library contains many additional methods that you can use to perform mathematical and string operations on data, such as the System.Math class. Additional Reading: For more information about operators, see the C# Operators page at http://go.microsoft.com/fwlink/?LinkID=267771.

Programming in i Visual C#

1-17 7

D Declaring and Assig gning Var riables

Before you ca B an use a variab ble, you must declare it so that you can specify its nam me and characteristics. The e n name of a var riable is referr red to as an id dentifier. Visua al C# has spec cific rules concerning the id dentifiers that t y can use: you An identifier can only contain c letters, digits, and underscore u ch haracters. An identifier must start t with a letter r or an unders score. An identifier for a varia able should no ot be one of the t keywords that Visual C# # reserves for r its own use.

Visual C# is ca V ase sensitive. If you use the e name MyDa ata as the iden ntifier of a var riable, this is not n the same a myData. You can declar as re two variables at the same time called MyData and myData and Visual C# w not confu will use them, altho ough this is not good coding practice. When declarin W ng variables y you should use e meaningful names for yo our variables, because b this c can make y your code eas sier to understand. You sho ould also adop pt a naming c convention an nd use it!

D Declaring a and Assigni ing Variable


When you declare a variable, you reserv W ve some storag ge space for t that variable in n memory and the type of ill hold. You c d data that it wi can declare multiple variabl les in a single declaration by b using the comma s separator; all v variables decl lared in this w way have the s same type. T following example sho The ows how to de eclare a new v variable. D Declaring aV Variable
// DataType e variableNa ame; int price; // OR // DataType e variableNa ame1, variableName2; int price, tax;

After you declare a variable A e, you can ass sign a value to o it by using a an assignment t statement. Y You can c change the va alue in a variable as many t times as you w want during th he running of f the application. The a assignment operator = assigns a value to o a variable. T following code example shows how to use the = operator to assign The a a value to a variable. .

1-18

Review of Visual C# Syntax

Assigning a Variable
// variableName = value; price = 10;

The value on the right side of the expression is assigned to the variable on the left side of the expression. You can declare a variable and assign a value to it at the same time. The following code example declares an int named price and assigns the value 10. Declaring and Assigning Variables
int price = 10;

When you declare a variable, it contains a random value until you assign a value to it. This behavior was a rich source of bugs in C and C++ programs that created a variable and accidentally used it as a source of information before giving it a value. Visual C# does not allow you to use an unassigned variable. You must assign a value to a variable before you can use it; otherwise, your program might not compile.

Implicitly Typed Variables


When you declare variables, you can also use the var keyword instead of specifying an explicit data type such as int or string. When the compiler sees the var keyword, it uses the value that is assigned to the variable to determine the type. In the following example shows how to use the var keyword to declare a variable. Declaring a Variable by Using the var Keyword
var price = 20;

In this example, the price variable is an implicitly typed variable. However, the var keyword does not mean that you can later assign a value of a different type to price. The type of price is fixed, in much the same way as if you had explicitly declared it to be an integer variable. Implicitly typed variables are useful when you do not know, or it is difficult to establish explicitly, the type of an expression that you want to assign to a variable.

Object Variables
When you declare an object variable, it is initially unassigned. To use an object variable, you must create an instance of the corresponding class, by using the new operator, and assign it to the object variable. The new operator does two things: it causes the CLR to allocate memory for your object, and it then invokes a constructor to initialize the fields in that object. The version of the constructor that runs depends on the parameters that you specify for the new operator. The following code example shows how to create an instance of a class by using the new operator. The new Operator
ServiceConfiguration config = new ServiceConfiguration();

Additional Reading: For more information about declaring and assigning variables, see the Implicitly Typed Local Variables (C# Programming Guide) page at http://go.microsoft.com/fwlink/?LinkID=267772.

Programming in i Visual C#

1-19 9

A Accessing g Type Me embers

To access a m T member of an instance of a type, use the name of the instance, follo owed by a per riod, followed d b the name of by o the membe er. This is know wn as dot not tation. Consid der the followi ing rules and guidelines w when you acc cess a member of an instance: To access s a method, us se parenthese es after the na ame of the me ethod. In the parentheses, p p pass the values for r any paramet ters that the m method requires. If the met thod does not t take any par rameters, the parenthes ses are still required. To access s a public prop perty, use the e property nam me. You can then get the value of that p property or set the va alue of that pr roperty.

The following code example shows how to invoke the T e members th hat the Service eConfigurati ion class e exposes. I Invoking Me embers
var config = new ServiceConfiguration(); // Invoke t the LoadConf figuration method. var loadSuc ccessful = config.LoadC c onfiguration n(); // Get the value from the ApplicationName pro operty. var applica ationName = config.ApplicationName; ; // Set the .DatabaseSe erverName property. config.Data abaseServerN Name = "78.45.81.23"; // Invoke t the SaveConf figuration method. var saveSuc ccessful = config.SaveC c onfiguration n();

Additio onal Reading: For more inf formation abo out using prop perties, see th he Properties s (C# Programming Guide) pag P ge at http://go o.microsoft.co om/fwlink/?Lin nkID=267773. Additio onal Reading: For more inf formation abo out using met thods, see the e Methods (C C# Programming Guide) pag P ge at http://go o.microsoft.co om/fwlink/?Lin nkID=267774 4.

1-20 Review of Visual C# Syntax x

Ca asting Bet tween Dat ta Types

Wh hen you are d developing an n application, y you will often n need to conv vert data from m one type to another typ pe, for examp ple, when a value of one typ pe is assigned to a variable of a different t type. Consid der the sce enario where a user enters a number into a text box. T To use this nu umber in a numerical calculation, you will need to con nvert the string value 99 tha at you have re ead from the text box into the integer va alue 99 so tha at you can sto ore it in an int teger variable. The process of converting g a value of on ne data type to t another typ pe is called type conversion n or casting. There are two ty ypes of conve ersions in the . .NET Framewo ork: Implicit con nversion, whic ch is automatically performed by the CLR R on operations that are gu uaranteed g information to succeed without losing n. h requires you u to write cod de to perform a conversion that otherwis se could Explicit conversion, which lose information or produce an error.

Explicit conversi ion reduces th he possibility of bugs in your code and m makes your co ode more effic cient. Visual C# # prohibits implicit conversi ions that lose precision. Ho owever, be aw ware that some e explicit conv versions can yield unexp pected results.

Im mplicit Conv versions


An n implicit conv version occurs s when a value is converted d automatically from one d data type to an nother. The any special sy conversion does s not require a yntax in the so ource code. Vi isual C# only allows safe im mplicit conversions, suc ch as the wide ening of an integer. The following co ode example shows how da f an integer to a long, which w is ata is converted implicitly from ter rmed widening g. Im mplicit Conversion
int a = 4; long b; b = a;

// Implici it conversio on of int to long.

This conversion always succeeds and never results in a loss of information. However, you canno ot implicitly convert a long v value to an in nt, because this conversion risks losing in nformation (th he long value e might be ou utside the rang ge supported by the int typ pe). The follow wing table sho ows the implicit type conve ersions that are e supported in n Visual C#.

Programming in Visual C# 1-21

From sbyte byte short ushort int uint long, ulong float char

To short, int, long, float, double, decimal short, ushort, int, uint, long, ulong, float, double, decimal int, long, float, double, decimal int, uint, long, ulong, float, double, decimal long, float, double, decimal long, ulong, float, double, decimal float, double, decimal double ushort, int, uint, long, ulong, float, double, decimal

Explicit Conversions
In Visual C#, you can use a cast operator to perform explicit conversions. A cast specifies the type to convert to, in round brackets before the variable name. The following code example shows how to perform an explicit conversion. Explicit Conversion
int a; long b = 5; a = (int) b;

// Explicit conversion of long to int.

You can also perform an explicit conversion by using the as operator, but only for reference type objects. The advantage of using the as operator is that if the conversion fails due to the types being incompatible, instead of the CLR throwing an InvalidCastException, the cast operation will return null, which you can then check for in your code. The following code example shows how to use the as operator to cast between two data types. Conversions by Using the as Operator
int a; long b = 5; a = b as int; if (a != null) { // Cast successful. }

You can only perform meaningful conversions in this way, such as converting a long to an int. You cannot use a cast if the format of the data has to physically change, such as if you are converting a string to an integer. To perform these types of conversions, you can use the methods of the System.Convert class.

Using the System.Convert Class


The System.Convert class provides methods that can convert a base data type to another base data type. These methods have names such as ToDouble, ToInt32, ToString, and so on. All languages that target

1-22

Review of Visual C# Syntax

the CLR can use this class. You might find this class easier to use for conversions than implicit or explicit conversions because IntelliSense helps you to locate the conversion method that you need. The following code example converts a string to an int. Conversions by Using the ToInt32 Method
string possibleInt = "1234"; int count = Convert.ToInt32(possibleInt);

Some of the built-in data types in Visual C# also provide a TryParse method, which enables you to determine whether the conversion will succeed before you perform the conversion. The following code example shows how to convert a string to an int by using the int.TryParse() method. TryParse Conversion
int number = 0; string numberString = "1234"; if (int.TryParse(numberString, out number)) { // Conversion succeeded, number now equals 1234. } else { // Conversion failed, number now equals 0. }

Additional Reading: For more information about casting variables, see the Casting and Type Conversions (C# Programming Guide) page at http://go.microsoft.com/fwlink/?LinkID=267775.

Programming in i Visual C#

1-23 3

M Manipulat ting String gs

S Strings are a v very useful da ata type that enable e you to capture and store alphanu umeric data.

C Concatenat ting Strings s


Concatenating C g multiple strings in Visual C# is simple t to achieve by y using the + o operator. How wever, this is c considered ba ad coding pra actice because e strings are im mmutable. This means that t every time yo ou c concatenate a string, you c create a new s string in memory and the o old string is discarded. T following code example creates five The e string values s as it runs. C Concatenatio on by Using t the + Operat tor
string addr ress = "23"; address = a address + ", Main Street"; address = a address + ", Buffalo";

An alternative A e approach is to use the Str ringBuilder class, c which en nables you to build a string g dynamically a much mo and ore efficiently. . T following code example shows how to use the St The tringBuilder class. c C Concatenatio on by Using t the StringBuilder Class
StringBuild der address = new StringBuilder(); address.App pend("23"); address.App pend(", Main n Street"); address.App pend(", Buff falo"); string conc catenatedAdd dress = address.ToString g();

V Validating Strings
When acquiring input from W m the user inte erface of an application, da ata is often pro ovided as strin ngs that you n need to valida ate and then convert c into a format that y your applicati ion logic expe ects. For exam mple, a text b control in box n a WPF applic cation will ret turn its conten nts as a string g, even if a use er specified an integer v value. It is imp portant that y you validate su uch input so t that you minim mize the risk of o errors, such h as I InvalidCastEx xceptions. Regular expre R essions provide a mechanism that enable es you to valid date input. Th he .NET Frame ework p provides the S System.Text.RegularExpr ressions name espace that in ncludes the Re egex class. Yo ou can use the e

1-24

Review of Visual C# Syntax

Regex class in your applications to test a string to ensure that it conforms to the constraints of a regular expression. The following code example shows how to use the Regex.IsMatch method to see if a string value contains any numerical digits. Regex.IsMatch Method
var textToTest = "hell0 w0rld"; var regularExpression = "\\d"; var result = Regex.IsMatch(textToTest, regularExpression, RegexOptions.None); if (result) { // Text matched expression. }

Regular expressions provide a selection of expressions that you can use to match to a variety of data types. For example, the \d expression will match any numeric characters. Additional Reading: For more information about using regular expressions, see the Regex Class page at http://go.microsoft.com/fwlink/?LinkID=267776.

Programming in i Visual C#

1-25 5

Lesson 3

Visua al C# Pr rogram mming L Language Con nstructs s

When develop W ping an applic cation, you will often need to execute lo ogic based on a condition, o or to r repeatedly execute a sectio on of logic until a condition n is met. You may m also want to store a co ollection of r related data in n a single vari iable. Visual C C# provides a number of co onstructs than n enable you m model c complex beha avior in your a applications. In this lesson, you will learn I n how to implement decisio on and iteratio on statements and how to store c collections of related data. You will also learn how to structure the API of your application a by y using n namespaces, a how to use some of th and he debugging features that Visual Studio o provides.

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Use conditional statem ments. Use iterat tion statemen nts. Create an nd use arrays. Describe the purpose o of namespace es. Describe some of the f features provided by the Vi isual Studio debugger.

1-26 Review of Visual C# Syntax x

Im mplementing Condi itional Log gic

Ap pplication logi ic often needs s to run differ rent sections o of code depen nding on the s state of data i in the ap pplication. For example, if a user requests s to close a file, they may b be asked whet ther they wish h to save they do, the a any changes. If t application must execute co ode to save th he file. If they dont, the ap pplication log gic can simply y close the file e. Visual C# us ses conditiona al statements to determine which code s section to run n. The primary con nditional state ement in Visual C# is the if statement. Th here is also a switch statem ment that you can use for more comple ex decisions.

Co onditional S Statements s
Yo ou use if statements to test the truth of a statement. If f the statemen nt is true, the e block of code ass sociated with the if statement is execute ed, if the state ement is false, control passes over the block. The following co ode shows ho ow to use an if statement to o determine if ntains the valu ue f a string con co onnection_failed. if Statement S
s string respon nse = "."; if (response == "connect tion_failed") { // Block of code to execute if the value of f the respon nse variable e is "connection_f failed". }

if statements s ca an have associ iated else clau uses. The else e block execut tes when the if statement is false. The following co ode example shows how to o use an if els se statement t to execute cod de when a condition is fal lse. if else e Stateme ents
s string respon nse = "."; if (response == "connect tion_failed") { // Block of code exe ecutes if th he value of t the response e variable is "connection_f failed". }

Programming in Visual C# 1-27

else { // Block of code executes if the value of the response variable is not "connection_failed". }

if statements can also have associated else if clauses. The clauses are tested in the order that they appear in the code after the if statement. If any of the clauses returns true, the block of code associated with that statement is executed and control leaves the block of code associated with the entire if construct. The following code example shows how to use an if statement with an else if clause. else if Statements
string response = "."; if (response == "connection_failed") { // Block of code executes if the value of the response variable is "connection_failed". } else if (response == "connection_error") { // Block of code executes if the value of the response variable is "connection_error". } else { // Block of code executes if the value of the response variable is not "connection_failed" or "connection_error". }

Selection Statements
If there are too many if/else statements, code can become messy and difficult to follow. In this scenario, a better solution is to use a switch statement. The switch statement simply replaces multiple if/else statements. The following sample shows how you can use a switch statement to replace a collection of else if clauses. switch Statement
string response = "."; switch (response) { case "connection_failed": // Block of code executes break; case "connection_success": // Block of code executes break; case "connection_error": // Block of code executes break; default: // Block executes if none break; }

if the value of response is "connection_failed".

if the value of response is "connection_success".

if the value of response is "connection_error".

of the above conditions are met.

In each case statement, notice the break keyword. This causes control to jump to the end of the switch after processing the block of code. If you omit the break keyword, your code will not compile. Notice that there is an else block labeled default:. This block of code will execute when none of the other blocks match.

1-28

Review of Visual C# Syntax

Additional Reading: For more information about selection statements, see the Selection Statements (C# Reference) page at http://go.microsoft.com/fwlink/?LinkID=267777.

Programming in i Visual C#

1-29 9

I Implemen nting Itera ation Logi ic

Iteration prov I vides a conven nient way to execute e a bloc ck of code mu ultiple times. F For example, i iterating over a collection of f items in an a array or just e executing a function multip ple times. Visual C# provide es a number o standard co of onstructs know wn as loops that you can u use to implem ment iteration logic.

F Loops For
The for loop e T executes a blo ock of code re epeatedly unt til the specifie ed expression evaluates to f false. You can d define a for lo oop as follows s. f ([initializer for rs]; [expression]; [iterators]) { [body] } When using a for loop, you W u first initialize e a value as a counter. On each loop, yo ou check that t the value of t counter is the s within the ra ange to execute the for loo op, and if so, e execute the bo ody of the loo op. T following code example shows how to use a for loop The l to execu ute a code blo ock 10 times. f Loop for
for (int i = 0 ; i < 10; 1 i++) { // Code e to execute e. }

I this example, i = 0; is the In e initializer, i < 10; is the expression, and d i++; is the i iterator.

F Each Lo For oops


terating over a collection While a for lo W oop is easy to use, it can be e tricky to get right. For exa ample, when it o an array, yo or ou have to kn now how many elements th he collection or o array contains. In many c cases this is s straightforwar rd, but somet times it can be e easy to get wrong. w Theref fore, it is sometimes better r to use a f foreach loop. . T following code example shows how to use a fore The each loop to iterate a string array.

1-30

Review of Visual C# Syntax

foreach Loop
string[] names = new string[10]; // Process each name in the array. foreach (string name in names) { // Code to execute. }

While Loops
A while loop enables you to execute a block of code while a given condition is true. For example, you can use a while loop to process user input until the user indicates that they have no more data to enter. The following code example shows how to use a while loop. while Loop
bool dataToEnter = CheckIfUserWantsToEnterData(); while (dataToEnter) { // Process the data. dataToEnter = CheckIfUserHasMoreData(); }

Do Loops
A do loop is very similar to a while loop, with the exception that a do loop will always execute at least once. Whereas if the condition is not initially met, a while loop will never execute. For example, you can use a do loop if you know that this code will only execute in response to a user request to enter data. In this scenario, you know that the application will need to process at least one piece of data, and can therefore use a do loop. The following code example shows how to use a do loop. do Loop
do { // Process the data. moreDataToEnter = CheckIfUserHasMoreData(); } while (moreDataToEnter);

Additional Reading: For more information about loops, see the Iteration Statements (C# Reference) page at http://go.microsoft.com/fwlink/?LinkID=267778.

Programming in i Visual C#

1-31 1

C Creating a and Using g Arrays

An array is a s A set of objects that are grouped together r and manage ed as a unit. Yo ou can think o of an array as a sequence of f elements, all l of which are the same typ pe. You can bu uild simple arrays that have e one d dimension (a list), two dime ensions (a tab ble), three dim mensions (a cu ube), and so on. Arrays in Visual C# have t following features: the Every elem ment in the array contains a value. Arrays are e zero-indexe ed, that is, the first item in t the array is ele ement 0. The size o of an array is the t total num mber of elemen nts that it can n contain. Arrays can be single-dimensional, m multidimension nal, or jagged d. The rank of an array is the number of o dimensions s in the array.

Arrays of a pa A articular type can c only hold d elements of that type. If y you need to m manipulate a se et of unlike o objects or valu ue types, cons sider using on ne of the colle ection types th hat are define ed in the S System.Colle ections names space.

C Creating Ar rrays
When you declare an array W y, you specify the type of da ata that it con ntains and a n name for the a array. D Declaring an array a brings the array into scope, but do oes not actually allocate any y memory for r it. The CLR p physically crea ates the array y when you us se the new ke eyword. At this s point, you should specify the size of t array. the T following list describes The s how to creat te single-dime ensional, mult tidimensional, , and jagged a arrays: Single-dim mensional arr rays. To declar re a single-dim mensional arr ray, you specif fy the type of elements in the array and use brackets, [] to indicate that a va ariable is an array. Later, yo ou specify the size of the array whe en you allocat te memory for the array by y using the ne ew keyword. T The size of an array can be any integ ger expression n. The followin ng code example shows how w to create a single-dimen nsional array of integers with elements zero throu ugh nine.
int[] arrayName a = new int[10];

Multidimensional array ys. An array ca an have more e than one dim mension. The number of dimensions correspon nds to the num mber of index xes that are us sed to identify y an individua al element in the array.

1-32

Review of Visual C# Syntax

You can specify up to 32 dimensions, but you will rarely need more than three. You declare a multidimensional array variable just as you declare a single-dimensional array, but you separate the dimensions by using commas. The following code example shows how to create an array of integers with three dimensions.
int[ , , ] arrayName = new int[10,10,10];

Jagged arrays. A jagged array is simply an array of arrays, and the size of each array can vary. Jagged arrays are useful for modeling sparse data structures where you might not always want to allocate memory for every item if it is not going to be used. The following code example shows how to declare and initialize a jagged array. Note that you must specify the size of the first array, but you must not specify the size of the arrays that are contained within this array. You allocate memory to each array within a jagged array separately, by using the new keyword.
int[][] jaggedArray = new int[10][]; jaggedArray[0] = new Type[5]; // Can specify different sizes. jaggedArray[1] = new Type[7]; ... jaggedArray[9] = new Type[21];

Accessing Data in an Array


You can access data in an array in several ways, such as by specifying the index of a specific element that you require or by iterating through the entire collection and returning each element in sequence. The following code example uses an index to access the element at index two. Accessing Data by Index
int[] oldNumbers = { 1, 2, 3, 4, 5 }; int number = oldNumbers[2];

Note: Arrays are zero-indexed, so the first element in any dimension in an array is at index zero. The last element in a dimension is at index N-1, where N is the size of the dimension. If you attempt to access an element outside this range, the CLR throws an IndexOutOfRangeException exception. You can iterate through an array by using a for loop. You can use the Length property of the array to determine when to stop the loop. The following code example shows how to use a for loop to iterate through an array. Iterating Over an Array
int[] oldNumbers = { 1, 2, 3, 4, 5 }; for (int i = 0; i < oldNumbers.Length; i++) { int number = oldNumbers[i]; ... }

Additional Reading: For more information about arrays, see the Arrays (C# Programming Guide) page at http://go.microsoft.com/fwlink/?LinkID=267779.

Programming in i Visual C#

1-33 3

R Referenci ng Names spaces

The Microsoft T t .NET Framew work consists o of many namespaces that organize o its cl lasses into log gically related h hierarchies. Yo ou can use na amespaces in y your own app plications to similarly organ nize your class ses into h hierarchies. Namespaces function N f as bo oth an interna al system for o organizing your application n and as an ex xternal way to o a avoid name clashes betwee en your code and other applications. Eac ch namespace e contains typ pes that you c use in you can ur program, such as classes s, structures, e enumerations, , delegates, an nd interfaces. Because d different class ses can have the t same nam me, you use na amespaces to differentiate the t same nam med class into t two different hierarchies to o avoid interoperability issu ues.

. .NET Frame ework Class s Library Na amespaces s


The most imp T portant names space in the .N NET Framewo ork is the Syste em namespac ce, which contains the c classes that m most applicatio ons use to inte eract with the e operating sy ystem. A few o of the namesp paces p provided by the .NET Fram mework throug gh the System m namespace are listed in the following t table: Namespace System.Win ndows System.IO System.Data a System.Web b Definit tion Provides the classes s that are usef ful for building g WPF applica ations. Provides classes for reading and w writing data t to files. Provides classes for data access. Provides classes that are useful fo or building we eb application ns.

U User-Defin ed Namesp paces


User-defined namespaces are U a namespac ces defined in your code. It is good pract tice to define all your c classes in nam mespaces. The Visual Studio o environment t follows this recommendation by using the name of y your project a as the top-level namespace e in a project. The following code example shows how to define a n T namespace wit th the name F FourthCoffee e.Console, w which contain ns the Program class.

1-34

Review of Visual C# Syntax

Defining a Namespace
namespace FourthCoffee.Console { class Program { static void Main(string[] args) { } } }

When you create a Visual C# project in Visual Studio, the most common base class assemblies are already referenced. However, if you need to use a type that is in an assembly that is not already referenced in your project, you will need to add a reference to the assembly by using the Add Reference dialog box. Then at the top of your code file, you list the namespaces that you use in that file, prefixed with the using directive. The using directive is a shortcut that instructs your application that the types in the namespace can be referenced directly, without using the fully qualified name. The following code example shows how to import the System namespace and use the Console class. Importing a Namespace
using System; Console.WriteLine("Hello, World");

Additional Reading: For more information about namespaces, see the namespace (C# Reference) page at http://go.microsoft.com/fwlink/?LinkID=267780.

Programming in i Visual C#

1-35 5

D Debuggin ng by Usin ng Visual S Studio 2012

Debugging is an essential p D part of applica ation develop pment. You may notice erro ors as you writ te code, but s some errors, e especially logi ic errors, may only occur in n circumstance es that you do o not predict. Users may r report these e errors to you a and you will have h to correc ct them. Visual Studio 2012 provide V es several tools to help you debug code. You might us se these while e you develop p c code, during a test phase, o or after the ap pplication has s been release ed. You will us se the tools in the same w regardles way ss of the circumstances. You can run an Y a application n with or witho out debugging enabled. W When debugging is enabled, your a application is said to be in Debug mode e. To access th he numerous d debug functio ons, including g the ability to o s step through code line by line, l you can use u the items on the Debu ug menu, the buttons b on th he Debug t toolbar, or keyboard shortc cuts.

D Debug Con ntrols


The following table lists the T e key items on n the Debug menu and the e Debug toolbar, and the c corresponding g keyboard sh hortcuts. Menu item Start Debug gging To oolbar button n St tart/continue Key yboard shortc cut F5 De escription Th his button is available when n yo our application n is not running and wh hen you are in break mode. It will start yo our application n in Debug mode or resume the pplication if yo ou are in ap br reak mode. Th his button cau uses ap pplication processing to pa ause and brea ak mode to be e en ntered. The bu utton is av vailable when an ap pplication is ru unning. Th his button stops

Break All

Br reak all

Ctrl+Alt+Break

Stop Debug gging

St top

Sh hift+F5

1-36

Review of Visual C# Syntax

Menu item

Toolbar button

Keyboard shortcut

Description debugging. It is available when an application is running or is in break mode.

Restart

Restart

Ctrl+Shift+F5

This button is equivalent to stop followed by start. It will cause your application to be restarted from the beginning. It is available when an application is running or is in break mode. This button is used for stepping into method calls. This button is used for stepping over method calls. This button is used for executing the remaining code in the method and returning to the next statement in the calling method.

Step Into Step Over Step Out

Step into Step over Step out

F11 F10 Shift+F11

Additional Reading: For more information about debugging, see the Debugging in Visual Studio page at http://go.microsoft.com/fwlink/?LinkID=267781.

Programming in i Visual C#

1-37 7

D Demonstr ration: De eveloping the Class s Enrollme ent Applic cation Lab b

I this demon In nstration, you will learn abo out the tasks t that you will p perform in the e lab for this module. m

1-38 Review of Visual C# Syntax x

Lab: D Develop ping the e Class Enrollm ment Applicat A tion

Sc cenario
Yo ou are a Visual C# develope er working for r a software development c company that t is writing app plications for r The School o of Fine Arts, an elementary school for gif fted children. The school adm ministrators req quire an appli ication that th hey can use to o enroll studen nts in a class. The ap pplication mus st enable an a administrator t to add and re emove students from classe es, as well as to update the e details of stu udents. Yo ou have been asked to write e the code tha at implements the business s logic for the e application. ring the labs f for the first tw wo modules in n this course, you y will write code for this Note: Dur cla ass enrollment t application. Wh hen The Scho ool of Fine Arts ask you to extend e the application func ctionality, you realize that you y will need to test t proof of con ncept and obtain client feed dback before writing the fin nal application, so in the lab for r Module 3, yo ou will begin d developing a prototype ap pplication and continue with thi is until then end of Module e 8. In the lab for Module 9, after r gaining signoff for the final application n, you will dev velop the user r int terface for the e production version v of the e application, w which you wil ll work on for the remainde er of the course.

Ob bjectives
Aft ter completing this lab, you u will be able to: al C# code tha at implements s the logic nec cessary to edit t the details o of a student. Write Visua Write Visua al C# code tha at implements s the logic nec cessary to add d new student ts. Write Visua al C# code tha at implements s the logic nec cessary to rem move students s from a class. Perform sim mple data tran nsformations for f displaying information.

timated Time: : 45 minutes Est Virtual Mac chines: 20483-SEA-DEV11-0 01, MSL-TMG1

Programming in Visual C# 1-39

User Name: Student Password: Pa$$w0rd

1-40

Review of Visual C# Syntax

Exercise 1: Implementing Edit Functionality for the Students List


Scenario
In this exercise, you will write the code that enables an administrator using the application to edit a students details. A list of students is displayed in the user interface of the application. When the user selects a student and then presses a key on the keyboard, you will check whether the key they pressed was Enter. If they did press Enter, you will write code to display the students details in a separate form, which the user can use to modify the details. When the user closes the form, you will copy the updated details back to the list box displaying the list of students. Finally, you will run the application to verify that your code functions as expected, and then use the debugging tools to examine code as it runs. The main tasks for this exercise are as follows: 1. Detect whether the user has pressed the Enter key 2. Initialize the StudentForm window and populate it with the details of the currently selected student 3. Display the StudentForm window and copy the updated student details entered back to the Student object 4. Run the application and verify that the edit functionality works as expected 5. Use the Visual Studio Debugger to step through the code.

X Task 1: Detect whether the user has pressed the Enter key
1. 2. 3. 4. 5. Start the MSL-TMG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-01 virtual machine and log on as Student with the password Pa$$w0rd. Start Visual Studio and from the E:\Labfiles\Starter\Exercise 1 folder, and then open the School.sln solution. In the code for the MainWindow.xaml.cs window, find the studentsList_KeyDown method. In this method, add a switch statement to detect whether the user has pressed Enter.

Note: The second argument passed to this method is a KeyEventArgs object named e. This object has a Key property which returns the keyboard key associated with the event. You can use this in conjunction with the Key enumeration to determine which key initiated the KeyDown event. 6. If the user has pressed Enter, store the selected student in a Student object variable.

Note: Later in this lab, you will be adding code to detect whether the user presses the Insert or Delete keys, so a switch statement is recommended.

Programming in Visual C# 1-41

X Task 2: Initialize the StudentForm window and populate it with the details of the currently selected student
1. 2. If the user has pressed the Enter key, create a new instance of the StudentForm window and set the Title property of the window to Edit Student Details. Populate the following text boxes on the form with the corresponding properties of the current student: a. b. c. 3. firstName lastName dateOfBirth

Display the date of birth by using the standard short date format without the time element by using the d format specifier. Note: To store data in a text box in a window, set the Text property of the text box.

X Task 3: Display the StudentForm window and copy the updated student details entered back to the Student object
1. 2. At the end of the case Key.Enter block, display the StudentForm window by using the ShowDialog method of the form. If the user clicks OK in the StudentForm window, copy the updated student details from the StudentForm window back to the Student object.

Note: You can detect whether the user clicked the OK button by examining the return value of the ShowDialog method. If the Value property is true, the user clicked OK, otherwise they clicked Cancel. Note: You can use the DateTime.Parse method to convert the date of birth string from the text box to a DateTime type. 3. If the user clicks OK, also enable the Save Changes button in the user interface. Note: To enable an item in a user interface, set the IsEnabled property of the item to true.

X Task 4: Run the application and verify that the edit functionality works as expected
1. 2. Build the solution and resolve any compilation errors. Run the application and verify that it displays the initial list of students.

1-42

Review of Visual C# Syntax

The initial students list should look like this:

FIGURE 01.1: THE INITIAL STUDENTS LIST 3. Edit the row for Kevin Liu and verify that the Edit Student Details window appears and displays the correct details: The Edit Student Details window should look similar to the following:

FIGURE 01.2: EDIT STUDENT DETAILS FORM 4. 5. 6. Change the last name of Kevin Liu to Cook and verify that the updated data is copied back to the students list. Verify that the Save Changes button is now enabled. Close the application.

X Task 5: Use the Visual Studio Debugger to step through the code.
1. 2. 3. 4. In Visual Studio, in the studentsList_KeyDown method, insert a breakpoint at the statement that sets the Title property of the StudentForm. Debug the application. Edit the row for George Li. When Visual Studio enters break mode, open the Watch 1 window and populate the grid with a row for each of the following: o o sf.Title sf.firstName.Text

Programming in Visual C# 1-43

o o

sf.lastName.Text sf.dateOfBirth.Text

Note: When Visual Studio enters break mode, the Watch window automatically appears in the tab group in the bottom left window. 5. 6. Step over the next code statement four times. Use the Immediate Window to view the value of sf.firstName.Text and to verify that it contains the value George.

Note: When Visual Studio enters break mode, the Immediate Window automatically appears in the tab group in the bottom middle window 7. 8. 9. In the Watch 1 window, change the value George to Dominik. In the Immediate Window, enter sf.lastName.Text and verify that the value "Li" is displayed. Enter code to change the sf.lastName.Text value to "Dubicki", and then verify that value changes in the Watch 1 window.

10. Continue debugging and verify that the following information is displayed in the Edit Student Details form: Field First Name Last Name Date of Birth Value Dominik Dubicki 8/10/2005

11. Stop debugging the application. 12. In Visual Studio, on the Debug menu, click Delete All Breakpoints, and then close the solution.

Results: After completing this exercise, users will be able to edit the details of a student.

1-44

Review of Visual C# Syntax

Exercise 2: Implementing Insert Functionality for the Students List


Scenario
In this exercise, you will write code that enables an administrator using the application to add a new student to the students list. A list of students is displayed in the user interface of the application. When the user presses a key on the keyboard, you will check whether the key they pressed was Insert. If they did press Insert, you will write code to display a form in which the user can enter the details of a new student, including their first name, last name, and date of birth. When the user closes the form, you will add the new student to the list of students and display the details in the list box. Finally, you will run the application to verify that your code functions as expected. The main tasks for this exercise are as follows: 1. Add logic to the key down method to detect if the Insert key has been pressed. 2. Initialize the student form 3. Display the StudentForm window and enable the user to provide the details of the new student 4. Assign the new student to a class and enable the user to save the details of the new student 5. Run the application and verify that the insert functionality works as expected

X Task 1: Add logic to the key down method to detect if the Insert key has been pressed.
1. 2. 3. In Visual Studio, from the E:\Labfiles\Starter\Exercise 2 folder, open the School.sln solution. In the code for the MainWindow.xaml.cs window, locate the studentsList_KeyDown method. In this method, add a statement to detect whether the user has pressed Insert.

X Task 2: Initialize the student form


1. 2. If the user has pressed Insert, create a new instance of the StudentForm window. Set the Title property of the window to New Student for Class appended to the Class property of the teacher object.

Note: You can use code similar to the following to create the string for the Title property. "New Student for Class " + teacher.Class

X Task 3: Display the StudentForm window and enable the user to provide the details of the new student
1. 2. Display the StudentForm window by using the ShowDialog method. If the user clicks the OK button in the StudentForm window, create a new student object and copy the student details from the StudentForm window to the new student object.

X Task 4: Assign the new student to a class and enable the user to save the details of the new student
1. If the user clicks the OK button in the StudentForm window, use the Students.Add method of the current teacher to assign the new student to a class.

Programming in Visual C# 1-45

Note: You can use the this.Teacher property to access the current teacher. 2. 3. Add the new student object to the list of students displayed on the form. Enable the Save Changes button in the user interface.

X Task 5: Run the application and verify that the insert functionality works as expected
1. 2. 3. 4. Build the solution and resolve any compilation errors. Run the application and verify that it displays the initial list of students. Display the new student window and verify that it contains no data. Insert the details for Darren Parker, date of birth is 02/03/2006, and verify that the new student is added to the students list. Note: The ID of any new student will be 0 until they are saved to the database. 5. 6. 7. Verify that the Save Changes button is now enabled. Close the application. In Visual Studio, close the solution.

Results: After completing this exercise, users will be able to add new students to a class.

1-46

Review of Visual C# Syntax

Exercise 3: Implementing Delete Functionality for the Students List


Scenario
In this exercise, you will write code that enables an administrator to remove a student from the students list. A list of students is displayed in the user interface of the application. If the user selects a student and then presses a key on the keyboard, you will check whether the key they pressed was Delete. If they did press Delete, you will write code to prompt the user to confirm that they want to remove the selected student from the class. If they do, the student will be deleted from the students list for the appropriate class, otherwise nothing changes. Finally, you will run the application to verify that your code functions as expected. The main tasks for this exercise are as follows: 1. Add logic to the key down method to detect if the Delete key has been pressed. 2. Prompt the user to confirm that they want to remove the selected student from the class 3. Remove the student and enable the user to save the changes 4. Run the application and verify that the delete functionality works as expected

X Task 1: Add logic to the key down method to detect if the Delete key has been pressed.
1. 2. 3. In Visual Studio, from the E:\Labfiles\Starter\Exercise 3 folder, open the School.sln solution. In the code for the MainWindow.xaml.cs window, find the studentsList_KeyDown method. In this method, add a statement to detect whether the user has pressed Delete.

X Task 2: Prompt the user to confirm that they want to remove the selected student from the class
1. If the user presses Delete, find the details of the student that the user has selected and display a message box showing the selected students name. Ask the user to confirm that they want to remove the student. The confirmation prompt should look like this.

FIGURE 01.3: PROMPT TO CONFIRM THE DELETION OF A STUDENT.

X Task 3: Remove the student and enable the user to save the changes
1. If the user confirms that they want to delete the student, delete the current student object from the schoolContext.Students collection and enable the Save Changes button in the user interface.

Programming in Visual C# 1-47

X Task 4: Run the application and verify that the delete functionality works as expected
1. 2. 3. 4. 5. 6. Build the solution and resolve any compilation errors. Run the application and verify that it displays the initial list of students. Delete the student Jon Orton from class 4B. Verify that the prompt window appears, the student is removed from the list, and that the Save Changes button is enabled. Close the application. In Visual Studio, close the solution.

Results: After completing this exercise, users will be able to remove students from classes.

1-48

Review of Visual C# Syntax

Exercise 4: Displaying a Students Age


Scenario
In this exercise, you will update the application to display a students age instead of their date of birth. You will write code in the AgeConverter class that is linked to the grid column displaying student ages. In this class, you will write code to work out the difference between the current date and the date of birth of the student, and then convert this value into years. Then you will run the application to verify that the Age column now displays age in years instead of the date of birth. The main tasks for this exercise are as follows: 1. Examine the MainWindow XAML 2. Add logic to the AgeConverter class to calculate a students age from their date of birth 3. Run the application and verify that the students age now appears correctly

X Task 1: Examine the MainWindow XAML


1. 2. 3. 4. In Visual Studio, open the School.sln solution from the E:\Labfiles\Starter\Exercise 4 folder. Build the solution. View the MainWindow.xaml code. Note how the Age column in the GridView uses databinding with a value converter (AgeConverter).

X Task 2: Add logic to the AgeConverter class to calculate a students age from their date of birth
1. 2. 3. 4. In the code for the MainWindow.xaml.cs window, find the Convert method in the AgeConverter class. In this method, add code that checks that the value parameter of the method contains data. If it does not, return an empty string. If the value parameter is not null, convert the value parameter to a DateTime object. Calculate the difference between the current date and the students date of birth, and then convert the result into a number of years.

Note: You can use the DateTime.Now.Subtract method to subtract the date of birth from the current date and store the result in a TimeSpan object. You can use the TimeSpan.Days method to retrieve the difference in days and then use the following formula to calculate the age in years from this difference. Age in years = difference in days / 365.25 5. Convert the number of years into a string and return it to the calling method.

X Task 3: Run the application and verify that the students age now appears correctly
1. 2. Build the solution and resolve any compilation errors. Run the application and verify it displays the initial list of students, with their ages.

Programming in Visual C# 1-49

The student list should now look similar to the following:

FIGURE 01.4: THE STUDENT LIST DISPLAYING THEIR AGES. 3. 4. 5. Add yourself as a student and verify that your age displays correctly in the student list. Close the application. In Visual Studio, close the solution.

Results: After completing this exercise, the application will display a students age in years.

1-50 Review of Visual C# Syntax x

Modu ule Revi iew and d Takea aways

M Module Revie ew
In this module, y you learned about a some of f the core features provided by the .NET T Framework a and Mi icrosoft Visual Studio. Yo ou also learned d about some e of the core Visual V C# co onstructs that enable you to start develop ping .NET Fram mework applic cations. Test Your Know wledge Q Question W What Visual Studio templa ate would you u use to creat te a .dll? S Select the cor rrect answer. Conso ole application n Windo ows Forms application WPF a application Class library WCF S Service applica ation Ve erify the correc ctness of the statement by placing a ma ark in the column to the rig ght. S Statement When using the as operato W or to perform a cast, if the cast c is not pos ssible, the a operator will as w return a -1 1. Is this statem ment true or f false? Test Your Know wledge Q Question G Given the follo owing for loo op statement, , what is the value v of the c count variable once the Answer

Programming in Visual C# 1-51

Question loop has finished executing? var count = 0; for (int i = 5; i < 12; i++) { count++; } Select the correct answer. 3 5 7 9 11

2-1

Module 2
Creating Methods, Handling Exceptions, and Monitoring Applications
Contents:
Module Overview Lesson 1: Creating and Invoking Methods Lesson 2: Creating Overloaded Methods and Using Optional and Output Parameters Lesson 3: Handling Exceptions Lesson 4: Monitoring Applications Lab: Extending the Class Enrollment Application Functionality Module Review and Takeaways 2-2 2-3 2-13 2-20 2-27 2-36 2-44

2-2

Creating Methods, Handling Exceptions, and Mo onitoring Applications

Modu ule Ove erview

Ap pplications oft ten consist of logical units o of functionalit ty that perform specific fun nctions, such a as pro oviding access to data or tr riggering som me logical proc cessing. Visua al C# is an object-orientated d language and uses the concept of meth hods to encap psulate logical units of func ctionality. A method m can be e as simple or as complex as you like, and d therefore it is important to consider w what happens to the state o of your ap pplication whe en an exceptio on occurs in a method. In this module, y you will learn how to creat te and use me ethods and ho ow to handle exceptions. e Yo ou will also lea e logging and arn how to use d tracing to re ecord the deta ails of any exc ceptions that o occur.

Ob bjectives
Aft ter completing this module e, you will be able to: ods. Create and invoke metho Create over rloaded metho optional param meters. ods and use o Handle exce eptions. Monitor applications by using logging g, tracing, and d profiling.

Programming g in Visual C#

2-3 3

Lesson 1

Creat ting an nd Invoking M Methods s

A key part of developing any application n is dividing the solution in nto logical com mponents. In objecto oriented languages such as s Visual C#, a method is a u unit of code th hat performs a discrete pie ece of work. I this lesson, you will learn In n how to creat te and invoke e methods.

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Describe the purpose o of methods. Create methods. Invoke methods. Debug m methods.

2-4

Creating Methods, Handling Exceptions, and Mo onitoring Applications

W What Is a M Method?

The ability to de efine and call methods is a fundamental component o of object-oriented program mming, be ecause method ds enable you u to encapsula ate operations s that protect data that is stored s inside a type. Typically, any ap pplication tha at you develop p by using the e Microsoft .N NET Framewor rk and Visual C# C will have many methods, each wi ith a specific p purpose. Some methods ar re fundamenta al to the oper ration of an ap pplication. For example, all V Visual C# desktop applications must hav ve a method c called Main th hat defines the e entry point for the applic cation. When t the user runs a Visual C# application, the e common lan nguage run ntime (CLR) ex xecutes the Main M method for that application. Me ethods can be e designed for internal use by a type, and as such are hidden from other types. P Public me ethods may be designed to o enable other types to request that an o object perform ms an action, and are exposed outside e of the type. r ework itself is built from classes that expo ose methods t that you can c call from your The .NET Frame ap pplications to i interact with the t user and the t computer r.

Programming g in Visual C#

2-5 5

C Creating M Methods

A method com mprises of two o elements: 1 1. 2 2. The meth hod specificati ion. The meth hod body.

The method s T specification defines d the na ame of the me ethod, the par rameters that the method can c take, the r return type of f the method, and the acce essibility of the e method. The e combination of the name e of the m method and its parameter list are referre ed to as the m method signat ture. The defin nition of the r return value o a method is not regarde of ed as part of the signature. Each method d in a class mu ust have a uniq que s signature.

N Naming Me ethods
A method nam me has the same syntactic restrictions as s a variable na ame. A metho od must start with w a letter o an undersc or core and can o only contain letters, unders scores, and nu umeric characters. Visual C# # is case s sensitive, so a class can con ntain two met thods that hav ve the same n name and diffe er only in the casing of o or more lettersalthough this is no one ot a good coding practice. T following guidelines ar The re recommend ded best prac ctices when yo ou choose the e name of a m method: Use verbs s or verb phra ases to name m methods. This s helps other developers d to o understand t the structure of your co ode. Use Pasca al case. Do no ot start public method names with an un nderscore or a lowercase let tter.

I Implement ting a Meth hod Body


The body of a method is a block of code T e that is imple emented by using any of th he available Visual C# p programming g constructs. T The body is en nclosed in braces. You can defin Y ne variables inside a method d body, in wh hich case they exist only wh hile the metho od is running. W When the me ethod finishes, , it is no longe er in scope. The following code example shows the b T body for the S StopService m method, which contains a v variable n named isServ viceRunning. The isService eRunning var riable is only a available insid de the StopSe ervice code b block. If you t try to refer to the isService eRunning vari iable outside the scope of t the method, t the compiler w raise a compile error w will with the messa age The name e 'isServiceRu unning' does s not exist in the current c context.

2-6

Creating Methods, Handling Exceptions, and Monitoring Applications

Variable Method Scope


void StopService() { var isServiceRunning = FourthCoffeeServices.Status; ... }

Specifying Parameters
Parameters are local variables that are created when the method runs and are populated with values that are specified when the method is called. All methods must have a list of parameters. You specify the parameters in parentheses following the method name. Each parameter is separated by a comma. If a method takes no parameters, you specify an empty parameter list. For each parameter, you specify the type and the name. By convention, parameters are named by using camel case. The following code example shows a method that accepts an int parameter and a Boolean parameter. Passing Parameters to a Method
void StartService(int upTime, bool shutdownAutomatically) { // Perform some processing here. }

When defining the parameters that a method accepts, you can also prefix the parameter definition with the ref keyword. By using the ref keyword, you instruct the CLR to pass a reference to the parameter and not just the value of the parameter. You must initialize the ref parameter, and any changes to the parameter inside the method body will then be reflected in the underlying variable in the calling method. The following code example shows how to define a parameter by using the ref keyword. Defining a Parameter by Using the ref Keyword
void StopAllServices(ref int serviceCount) { serviceCount = FourthCoffeeServices.ActiveServiceCount; }

Additional Reading: For more information about the ref keyword, see the ref (C# Reference) page at http://go.microsoft.com/fwlink/?LinkID=267782.

Specifying a Return Type


All methods must have a return type. A method that does not return a value has the void return type. You specify the return type before the method name when you define a method. When you declare a method that returns data, you must include a return statement in the method block. The following code example shows how to return a string from a method.

Programming in Visual C# 2-7

Returning Data from a Method


string GetServiceName() { return "FourthCoffee.SalesService"; }

The expression that the return statement specifies must have the same type as the method. When the return statement runs, this expression is evaluated and passed back to the statement that called the method. The method then finishes, so any other statements that occur after a return statement has been executed will not run.

2-8

Creating Methods, Handling Exceptions, and Mo onitoring Applications

In nvoking M Methods

Yo ou call a method to run the code in that method from m part of your application. Y You do not ne eed to un nderstand how w the code in a method wo orks. You may not even hav ve access to th he code, if it is s in a class in an assembly for f which you u do not have the source, su uch as the .NE ET Framework k class library. o call a method d, you specify y the method name and pro ovide any arg guments that c correspond to o the To me ethod parame eters in bracke ets. The following co ode example shows how to o invoke the StartService S m method, passing int and Bo oolean variables to satisfy the param meter requirem ments of the m methods signature. Inv voking a Met thod Passing g Parameters s
v var upTime = 2000; v var shutdownA Automaticall ly = true; S StartService(upTime, shu utdownAutoma atically); / // StartServi ice method. v void StartService(int up pTime, bool shutdownAuto omatically) { // Perform m some proce essing here. }

If t the method re eturns a value e, you specify how to handl le this value, t typically by as ssigning it to a variable of the same type, in your calling code. The following co ode example shows how to o capture the return value of o the GetSer rviceName m method in a variable named serviceName e. Ca apturing a Me ethod Return n Value
v var serviceNa ame = GetSer rviceName(); s string GetServiceName() { return "Fo ourthCoffee. .SalesServic ce"; }

Additiona al Reading: F For more infor rmation about methods, se ee the Method ds (C# Pro ogramming G Guide) page at t http://go.mi icrosoft.com/f fwlink/?LinkID D=267774.

Programming in Visual C# 2-9

2-10 Creating g Methods, Handling Exceptions, and M Monitoring Applicatiions

Debugging g Methods s

de one statem Wh hen you are d debugging your application n, you can step through cod ment at a time e. This is an ext tremely usefu ul feature beca ause it enable es you to test t the logic that t your applicat tion uses one step at a tim me. Vis sual Studio pr rovides a num mber of debug gging tools tha at enable you u to step throu ugh code in exactly the wa ay you want to o. For example, you can ste ep through ea ach line in eac ch method tha at is executed, or you can ignore the s statements ins side a method d that you kno ow are workin ng correctly. Y You can also s step over code completely y, preventing some statements from exe ecuting. Wh hen debuggin ng methods, y you can use th he following t three debug fe eatures to con ntrol whether r you step ov ver, step into, o or step out of f a method: The Step Into feature exe ecutes the statement at the e current exec cution position n. If the statem ment is a method call, the current execution po osition will mo ove to the cod de inside the method. m After r you have stepped int to a method you y can contin nue executing g statements inside the met thod, one line e at a time. You can also use the Step p Into button to start an ap pplication in d debug mode. If you do this s, the application will enter bre eak mode as s soon as it start ts. The Step Ov ver feature ex xecutes the sta atement at th he current execution positio on. However, t this feature does not ste ep into code inside a meth hod. Instead, the code inside the method d executes and d the executing p position move es to the statement after the method call. The exceptio on to this is if f the code for the met thod or prope erty contains a breakpoint. If this is the ca ase, execution n will continue e up to the breakpoint. . The Step Out feature ena ables you to e execute the re emaining code e in a method d. Execution will w continue to the state ement that cal lled the metho od, and then pause at that point.

Additiona al Reading: F For more infor rmation about stepping thr rough code, see s the Code Ste epping Overview page at h http://go.micro osoft.com/fwl link/?LinkID=267783.

Programming in i Visual C#

2-11 1

D Demonstr ration: Cr reating, In nvoking, and Debug gging Met thods

I this demon In nstration, you will create a m method, invok ke the method d, and then debug the met thod.

D Demonstra ation Steps


1 1. 2 2. 3 3. Start the MSL-TMG1 vi irtual machine e if it is not already running g. Start the 20483A-SEA-DEV11-02 vir rtual machine. . Log on to o Windows 8 as a Student with the passwo rd. ord Pa$$w0r Note: If f necessary, click Switch Us ser to display the list of use ers. 4 4. 5 5. 6 6. 7 7. 8 8. 9 9. Switch to the Windows s 8 Start wind dow. Click Visu ual Studio 201 12. In Visual Studio, on the e File menu, p point to Open n, and then click Project/Solution. In the Op pen Project dia alog box, brow wse to the E:\ \Democode\Starter\FourthC Coffee.Metho odTestHarness s folder, click FourthCoff fee.MethodTe estHarness.sln, and then clic ck Open. In Visual Studio, on the e View menu, , click Task Li ist. In the Tas sk List windo ow, in the Cate egories list, click Commen nts.

1 Double-c 10. click the TODO O: 01: Define the t Initialize m method. task. 1 In the cod 11. de editor, click in the blank k line below th he comment, and then type e the followin ng code:
bool Ini itialize() { var p path = GetAp pplicationPa ath(); retur rn !s string.IsNul llOrEmpty(pa ath); }

1 In the Tas 12. sk List window w, double-click the TODO: 0 02: Invoke the e Initialize me ethod. task. 1 In the cod 13. de editor, click in the blank k line below th he comment, and then type e the followin ng code:

2-12

Creating Methods, Handling Exceptions, and Monitoring Applications

var isInitialized= Initialize();

14. Right-click the call to the Initialize method, point to Breakpoint, and then click Insert Breakpoint. 15. On the Build menu, click Build Solution. 16. On the Debug menu, click Start Debugging. 17. Press F11 to step into the Initialize method. 18. Press F10 to step to the GetApplicationPath method call. 19. Press F10 to step over the GetApplicationPath method call. 20. Press Shift+F11 to step out of the Initialize method. 21. Press F10 to step over the Initialize method call. 22. Hover over the isInitialized variable, and verify that the value returned is true. 23. On the Debug menu, click Stop Debugging. 24. On the File menu, click Close Solution.

Programming in i Visual C#

2-13 3

Lesson 2

Creat ting Ov verload ded Met thods a and Using Opt tional a and Outp put Para ameter rs

You have seen Y n that you can n define a me ethod that acc cepts a fixed number n of par rameters. How wever, s sometimes yo ou might write e one generic method that requires diffe erent sets of p parameters de epending on t context in the n which it is us sed. You can c create overloa aded methods s with unique e signatures to o support this n need. In other r scenarios, yo ou may want t to define a method that ha as a fixed num mber of param meters, but e enables an ap pplication to specify arguments for only the paramete ers that it need ds. You can do o this by d defining a me ethod that tak kes optional parameters p and then using named argum ments to satisf fy the p parameters by y name. In this lesson, you will learn I n how to creat te overloaded d methods, de efine and use optional para ameters, n named argum ments, and out tput paramete ers.

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Create an n overloaded method. Use optio onal paramete ers. Use name ed arguments s. Define ou utput paramet ters.

2-14 Creating g Methods, Handling Exceptions, and M Monitoring Applicatiions

Cr reating Ov verloaded d Methods s

Wh hen you defin ne a method, y you might rea alize that it re equires differe ent sets of info ormation in di ifferent cir rcumstances. Y You can define overloaded methods to c create multipl le methods with the same fun nctionality tha at accept diffe erent paramet ters dependin ng on the context in which they are calle ed. Ov verloaded met thods have th he same name e as each othe er to emphasiz ze their comm mon intent. Ho owever, each overloaded d method mu ust have a uniq que signature e, to differentiate it from the other overlo oaded versions of the m method in the e class. The signature of a method in ncludes its nam me and its par rameter list. T The return typ pe is not part o of the sig gnature. There efore, you can nnot define ov verloaded methods that dif ffer only in their return type. The following co ode example shows three v versions of the e StopService e method, all with a unique e signature. Ov verloaded Me ethods
v void StopServ vice() { ... } v void StopServ vice(string serviceName e) { ... } v void StopServ vice(int ser rviceId) { ... }

Wh hen you invok ke the StopSe ervice method d, you have choice of which overloaded version you u use. You sim mply provide the t relevant a arguments to satisfy a particular overload d, and then th he compiler w works out wh hich version to o invoke based on the argu uments that yo ou passed.

Programming in i Visual C#

2-15 5

C Creating M Methods that t Use Optional O P Parameter rs

By defining ov B verloaded me ethods, you ca an implement t different vers sions of a met thod that take e different p parameters. W When you build an applicat tion that uses overloaded m methods, the compiler c dete ermines which h s specific instan nce of each method it shou uld use to satis sfy each meth hod call. There are other languages and technolo T ogies that developers can use for building applications and c components t that do not fo ollow these rules. A key feat ture of Visual C# is the abil lity to interop perate with a applications a and components that are written w by usin ng other techn nologies. One of the princip pal that Windows t technologies t s uses is the C Component Object Model ( (COM). COM d does not supp port o overloaded m methods, but in nstead uses methods m that c can take optio onal paramete ers. To make it i easier to i incorporate C COM libraries a and compone ents into a Vis sual C# solutio on, Visual C# also supports optional p parameters. Optional para O ameters are also useful in o other situation ns. They provid de a compact t and simple solution when i is not possib it ble to use ove erloading beca ause the type es of the param meters do not t vary sufficien ntly to enable e t compiler t the to distinguish h between imp plementations s. The following code example shows how to define a m T method that accepts one mandatory para ameter and t two optional parameters. D Defining aM Method with Optional O Par rameters
void StopSe ervice(bool forceStop, string servi iceName = nu ull, int serviceId =1) { ... }

When defining a method that accepts optional param W meters, you must specify all mandatory p parameters b before any op ptional parameters. The following code example shows a me T ethod definitio on that uses o optional param meters that th hrows a c compile error r.

2-16

Creating Methods, Handling Exceptions, and Monitoring Applications

Incorrect Optional Parameter Definition


void StopService(string serviceName = null, bool forceStop, int serviceId = 1) { ... }

You can call a method that takes optional parameters in the same way that you call any other method. You specify the method name and provide any necessary arguments. The difference with methods that take optional parameters is that you can omit the corresponding arguments, and the method will use the default value when the method runs. The following code example shows how to invoke the StopService method, passing only an argument for the forceStop mandatory parameter. Invoking a Method Specifying Only Mandatory Arguments.
var forceStop = true; StopService(forceStop);

The following code example shows how to invoke the StopService method, passing an argument for the forceStop mandatory parameter, and an argument for the serviceName parameter. Invoking a Method Specifying Mandatory and Optional Arguments
var forceStop = true; var serviceName = "FourthCoffee.SalesService"; StopService(forceStop, serviceName);

Programming in i Visual C#

2-17 7

C Calling aM Method b by Using Named N Ar rguments

Traditionally, when calling a method, the T e order and p position of arg guments in the e method call l corresponds t the order of to o parameters in the metho od signature. If the arguments are misalig gned and the e types m mismatched, y you receive a compile error. In Visual C#, y I you can specif fy parameters s by name, and therefore su upply argume ents in a seque ence that d differs from th hat defined in n the method signature. To use named arguments, yo ou supply the parameter n name and cor rresponding value v separate ed by a colon. . The following code example shows how to invoke the T e StopService e method by using u named arguments to o p pass the servi iceName para ameter. U Using Named d Arguments s
StopService e(true, serv viceName: "FourthCoffee. .SalesServic ce");

When using n W named arguments in conjun nction with op ptional param meters, you can easily omit parameters. A optional parameters will Any w receive the eir default valu ue. However, if you omit an ny mandatory y parameters, y your code will not compile. You can mix p Y positional and d named arguments. Howev ver, you must t specify all po ositional arguments before a named ar any rguments. Additio onal Reading: For more inf formation abo out using nam med argument ts, see the Named and Optional Arguments (C a C# Programm ming Guide) pa age at h http://go.micr rosoft.com/fw wlink/?LinkID= =267784.

2-18 Creating g Methods, Handling Exceptions, and M Monitoring Applicatiions

Cr reating M Methods th hat Use Ou utput Para ameters

A method m can pass p a value back to the cod de that calls it t by using a re eturn stateme ent. If you nee ed to ret turn more tha an a single value to the calling code, you u can use outp put parameters to return ad dditional data from the m method. When n you add an output param meter to a met thod, the met thod body is e expected to ass sign a value to o that parame eter. When the method com mpletes, the v value of the output parame eter is ass signed to a va ariable that is specified as the correspond ding argumen nt in the meth hod call. To o define an ou utput paramet ter, you prefix x the paramete er in the meth hod signature e with the out t keyword. The following co ode example shows how to o define a met thod that use es output para ameters De efining Outpu ut Parameter rs
b bool IsServic ceOnline(str ring service eName, out st tring status sMessage) { var isOnl line = Fourt thCoffeeServ vices.GetStat tus(serviceN Name); if (isOnl line) { statu usMessage = "Services is currently running."; } else { statu usMessage = "Services is currently stopped."; } return is sOnline; }

A method m can have h as many output param meters as requ uired. When you declare an n output param meter, you mu ust assign a va alue to the pa arameter befo ore the metho od returns, oth herwise the co ode will not co ompile. To o use an outpu ut parameter, you must pro ovide a variab ble for the corresponding argument whe en you call the e method, and d prefix that a argument with h the out key yword. If you a attempt to spe ecify an argum ment that is no ot a variable or if you omit t the out keyword, your cod de will not com mpile. The following co ode example shows how to o invoke a me ethod that acc cepts an outpu ut parameter. .

Programming in Visual C# 2-19

Invoking a Method that Accepts an Output Parameter


var statusMessage = string.Empty; var isServiceOnline = IsServiceOnline("FourthCoffee.SalesService", out statusMessage);

Additional Reading: For more information about output parameters, see the out parameter modifier (C# Reference) page at http://go.microsoft.com/fwlink/?LinkID=267785.

2-20 Creating g Methods, Handling Exceptions, and M Monitoring Applicatiions

Lesson 3

Handl ling Exc ception ns

Exc ception handling is an imp portant concep pt to ensure a good user ex xperience and d to limit data a loss. Ap pplications sho ould be designed with exce eption handlin ng in mind. In this lesson, yo ou will learn h how to implem ment effective e exception ha andling in you ur applications and how you can use exc ceptions in your methods to o elegantly indicate an erro or condition to the code th hat calls your methods.

Le esson Obje ectives


Aft ter completing this lesson, you will be ab ble to: . Describe the purpose of an exception. eptions by using a try/catch block. Handle exce Use a finally y block to run n code after an n exception. Throw an ex xception.

Programming in i Visual C#

2-21 1

W What Is an n Exceptio on?

Many things c M can go wrong g as an applica ation runs. Some errors may occur due to flaws in the e application l logic, but others may be du ue to conditio ons outside th he control of your y applicatio on. For examp ple, your a application ca annot guarant tee that a file exists on the file system or r that a requir red database is i online. W When you design an applic cation, you sh hould consider r how to ensu ure that your a application ca an recover g gracefully whe en such probl lems arise. It is common pr ractice to simp ply check the return values from m methods to ensure that the ey have execu uted correctly, , however, this methodolog gy is not alway ys sufficient t handle all e to errors that ma ay occur because: Not all methods m return n a value. You need d to know why y the method call has failed d, not just that it has failed. . Unexpect ted errors such as running o out of memory cannot be handled in this way.

Traditionally, applications u T used the conc cept of a global error objec ct. When a pie ece of code ca aused an e error, it would d set the data in this object t to indicate th he cause of th he error and then return to the caller. It w the respo was onsibility of the calling code e to examine the error obje ect and determ mine how to handle h it. H However, this approach is n not robust, be ecause it is too o easy for a p programmer to o forget to ha andle errors a appropriately .

H How Excep ptions Propagate


The .NET Fram T mework uses e exceptions to help overcom me these issue es. An exceptio on is an indica ation of an e error or excep ptional condit tion. A method d can throw an a exception w when it detect ts that something u unexpected h has happened, , for example, , the application tries to op pen a file that does not exis st. When a method throws an exception, th W he calling code must be pre epared to dete ect and handle this e exception. If t the calling cod de does not d detect the exce eption, the co ode is aborted d and the exce eption is a automatically propagated to t the code th hat invoked th he calling cod de. This proces ss continues until u a section o code takes responsibility of y for handling g the exception. Execution c continues in this section of code after t exception the n-handling log gic has comple eted. If no cod de handles th he exception, then t the proc cess will t terminate and d display a me essage to the user.

T Except The tion Type


When an exce W eption occurs, , it is useful to o include infor rmation about the original cause so that t the method t that handles t the exception can take the appropriate c corrective acti ion. In the .NE ET Framework k, exceptions

2-22

Creating Methods, Handling Exceptions, and Monitoring Applications

are based on the Exception class, which contains information about the exception. When a method throws an exception, it creates an Exception object and can populate it with information about the cause of the error. The Exception object is then passed to the code that handles the exception. The following table describes some of the exception classes provided by the .NET Framework. Exception Class Exception Namespace System Description Represents any exception that is raised during the execution of an application. Represents all exceptions raised by the CLR. The SystemException class is the base class for all the exception classes in the System namespace. Represents all non-fatal exceptions raised by applications and not the CLR. Represents an exception that is caused when trying to use an object that is null. Represents an exception caused when a file does not exist. Represents an exception that occurs during the serialization or deserialization process.

SystemException

System

ApplicationException

System

NullReferenceException

System

FileNotFoundException

System.IO

SerializationException

System.Runtime.Serialization

Additional Reading: For more information about the Exception class, see the Exception Class page at http://go.microsoft.com/fwlink/?LinkID=267786.

Programming in i Visual C#

2-23 3

H Handling Exception n by Using g a Try/Ca atch Block k

The try/catch block is the key T k programm ming construct t that enables s you to imple ement Structu ured E Exception Han ndling (SEH) in your applica ations. You w wrap code that t may fail and cause an exception in a t block, and add one or more try m catch blo ocks to handle any exceptions that may occur. T following code example shows the s The syntax for def fining a try/catch block. T Try/Catch Sy yntax
try { // Try block. } catch ([cat tch specific cation 1]) { // Catc ch block 1. } catch ([cat tch specific cation n]) { // Catc ch block n. }

The statements that are enclosed in the braces in the try block can be any Visua T al C# statemen nts, and can i invoke metho ods in other ob bjects. If any of o these statements cause an a exception to be thrown, , execution p passes to the appropriate c catch block. The catch spec cification for e each block det termines whic ch exceptions i will catch an it nd the variabl le, if any, in w which to store the exception n. You can spe ecify catch blo ocks for practice to inc d different type es of exception ns. It is good p clude a catch block for the general Exce eption type at t t end of the the e catch blocks s to catch all e exceptions tha at have not be een handled otherwise. o In the followin I ng code exam mple, if the cod de in the try b block causes a NullReferen nceException n exception, t code in th the he correspond ding catch blo ock runs. If any y other type o of exception occurs, o the cod de in the c catch block fo or the Excepti ion type runs.

2-24

Creating Methods, Handling Exceptions, and Monitoring Applications

Handling NullReferenceException and Exception exceptions


try { } catch (NullReferenceException ex) { // Catch all NullReferenceException exceptions. } catch (Exception ex) { // Catch all other exceptions. }

When defining more than one catch block, you must ensure that you place them in the correct order. When an exception is thrown, the CLR attempts to match the exception against each catch block in turn. You must put more specific catch blocks before less specific catch blocks, otherwise your code will not compile. Additional Reading: For more information about try/catch blocks, see the try-catch (C# Reference) page at http://go.microsoft.com/fwlink/?LinkID=267787.

Programming in i Visual C#

2-25 5

U Using a Fi inally Bloc ck

Some method S ds may contain critical code e that must al lways be run, even if an unhandled exception occurs. F example, a method ma For ay need to ens sure that it clo oses a file that t it was writing to or releases some o other resource es before it te erminates. A finally block en nables you to o handle this situation. s You specify a finally block after Y a any catch handlers in a try/catch block. It specifi ies code that must be p performed wh hen the block finishes, irres spective of wh hether any exc ceptions, hand dled or unhan ndled, occur. I an exception is caught an If nd handled, th he exception handler in the e catch block will run befor re the finally b block. You can also add Y a a finally b block to code that has no catch c blocks. In this case, all exceptions a are u unhandled, bu ut the finally block b will always run. T following code example shows how to implemen The nt a try/catch/ /finally block. nally Blocks T Try/Catch/Fi
try { } catch (Null lReferenceEx xception ex) { // Catc ch all NullR ReferenceException excep ptions. } catch (Exce eption ex) { // Catc ch all other r exceptions. } finally { // Code that always s runs. }

Additio onal Reading: For more inf formation abo out try/catch/ /finally blocks, , see the trycatch-finally ( c (C# Reference e) page at http p://go.microso oft.com/fwlink k/?LinkID=267788.

2-26 Creating g Methods, Handling Exceptions, and M Monitoring Applicatiions

Th hrowing E Exceptions s

Yo ou can create a an instance of f an exception n class in your r code and throw the excep ption to indica ate that an exc ception has o occurred. Whe en you throw an a exception, execution of the current b block of code terminates and the CLR pas sses control to o the first available exceptio on handler th hat catches the e exception. o throw an exc ception, you use u the throw w keyword and d specify the e exception object to throw. To The following co ode example shows how to o create an ins stance of the NullReferenc ceException class and the en throw the ex object. Creating and T Throwing an Exception
v var ex = new NullReferen nceException n("The 'Name' parameter is null."); t throw ex;

A common c strat tegy is for a m method or blo ock of code to o catch any exceptions and attempt to ha andle them. If t the catch bloc ck for an exce eption cannot resolve the error, it can ret throw the exc ception to pro opagate it to the caller. The following co ode example shows how to o rethrow an e exception that has been caught in a catc ch block. Re ethrowing an n Exception
t try { } c catch (NullRe eferenceExce eption ex) { // Catch all NullRef ferenceExcep ption excepti ions. } c catch (Except tion ex) { // Attemp pt to handle e the except tion ... // If thi is catch han ndler cannot t resolve the e exception, , // throw it to the c calling code e throw; }

Lesson 4

Programming in i Visual C#

2-27 7

Monitoring Applic cations

When you dev W velop real-wo orld applicatio ons, writing co ode is just one e part of the process. p You are a likely to s spend a signif ficant amount t of time resolving bugs, tro oubleshooting g problems, a and optimizing g the p performance of your code. Visual Studio o and the .NET T Framework provide various tools that can c help you t perform these tasks mor to re effectively. In this lesson, you will learn I n how to use a range of too ols and techni iques to moni itor and troub bleshoot your a applications.

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Use loggi ing and tracin ng in your cod de. Use application profilin ng in Visual St tudio. Use perfo ormance coun nters to monit tor the perform mance of you ur application. .

2-28 Creating g Methods, Handling Exceptions, and M Monitoring Applicatiions

Us sing Logg ging and T Tracing

Logging and tra acing are similar, but distinc ct, concepts. W When you implement logg ging in your ap pplication, you add code th hat writes info ormation to a destination lo og, such as a t text file or the e Windows ev vent log. Logging enables you to prov vide users and administrato ors with more information a about what yo our code is do oing. For exam mple, if your application han ndles an exception, you mi ight write the details to the e Windows eve ent log to ena able the user or a system administrator to t resolve any y underlying p problems. By y contrast, dev velopers use tracing to mon nitor the execution of an ap pplication. Wh hen you imple ement tra acing, you add d code that w writes message es to a trace lis stener, which in turn direct ts your output t to a spe ecified target. By default, y your trace mes ssages are sho own in the Ou utput window w in Visual Stu udio. You typ pically use tracing to provid de information about variable values or condition results, to help you y find out wh hy your applic cation behave es in a particul lar way. You can c also use tr racing techniq ques to interru upt the exe ecution of an application in n response to conditions th hat you define e.

W Writing to th he Window ws Event Log g


Wr riting to the W Windows even nt log is one o of the more co ommon logging requireme ents you migh ht encounter. The System.Diag gnostics.Even ntLog class pro ovides various static metho ods that you c can use to wr rite to the Win ndows event log. In particular, the Event tLog.WriteEn ntry method includes sever ral ov verloads that y you can use to o log various c combinations s of informatio on. To write to o the Window ws event log g, you need to o provide a m minimum of th hree pieces of information: The event lo og. This is the name of the Windows eve ent log you wa ant to write to o. In most cases you will write to the e Application n log. The event source. This ide entifies where e the event ca ame from, and d is typically th he name of yo our application. When you cr reate an even nt source, you associate it w with an event l log. The messag ge. This is the text that you want to add t to the log.

Yo ou can also use e the WriteEn ntry method to specify a ca ategory, an ev vent ID, and a an event sever rity if req quired. al Reading: W Writing to the Windows eve ent log requir res a high leve el of Additiona pe ermissions. If your y applicatio on does not run with suffic cient permissio ons, it will thro ow a Se ecurityExcept tion when you u attempt to create c an event source or w write to the ev vent log.

Programming in Visual C# 2-29

The following example shows how to write a message to the event log: Writing to the Windows Event Log
string eventLog = "Application"; string eventSource = "Logging Demo"; string eventMessage = "Hello from the Logging Demo application"; // Create the event source if it does not already exist. If (!EventLog.SourceExists(eventSource)) EventLog.CreateEventSource(eventSource, eventLog); // Log the message. EventLog.WriteEntry(eventSource, eventMessage);

Additional Reading: For more information on writing to the Windows event log, see the How to write to an event log by using Visual C# page at http://go.microsoft.com/fwlink/?LinkID=267789.

Debugging and Tracing


The System.Diagnostics namespace includes two classes, Debug and Trace, which you can use to monitor the execution of your application. These two classes work in a similar way and include many of the same methods. However, Debug statements are only active if you build your solution in Debug mode, whereas Trace statements are active in both Debug and Release mode builds. The Debug and Trace classes include methods to write format strings to the Output window in Visual Studio, as well as to any other listeners that you configure. You can also write to the Output window only when certain conditions are met, and you can adjust the indentation of your trace messages. For example, if you are writing details of every object within an enumeration to the Output window, you might want to indent these details to distinguish them from other output. The Debug and Trace classes also include a method named Assert. The Assert method enables you to specify a condition (an expression that must evaluate to true or false) together with a format string. If the condition evaluates to false, the Assert method interrupts the execution of the program and displays a dialog box with the message you specify. This method is useful if you need to identify the point in a longrunning program at which an unexpected condition arises. The following example shows how to use the Debug class to write messages to the Output window, and to interrupt execution if unexpected conditions arise. Using the Debug Class
int number; Console.WriteLine("Please type a number between 1 and 10, and then press Enter"); string userInput = Console.ReadLine(); Debug.Assert(int.TryParse(userInput, out number), string.Format("Unable to parse {0} as integer", userInput); Debug.WriteLine(The current value of userInput is: {0}", userInput); Debug.WriteLine(The current value of number is: {0}", number); Console.WriteLine("Press Enter to finish"); Console.ReadLine();

Additional Reading: For more information on tracing, see the How to trace and debug in Visual C# page at http://go.microsoft.com/fwlink/?LinkID=267790.

2-30 Creating g Methods, Handling Exceptions, and M Monitoring Applicatiions

Us sing Application Pr rofiling

Wh hen you deve elop applicatio ons, making your code wor rk without bug gs is only part t of the challe enge. You als so have to ens sure that your r code runs ef fficiently. You need to revie ew how long y your code tak kes to acc complish task ks and whethe er it uses excessive processo or, memory, d disk, or network resources. Vis sual Studio inc cludes a range of tools, col llectively know wn as the Visu ual Studio Pro ofiling Tools, that can he elp you to ana alyze the perfo ormance of yo our applications. At a high level, running g a performan nce analysis in Visual Studio consists of th hree high-leve el steps: 1. Create and run a perform mance session. All performa ance analysis t takes place wi ithin a perform mance session. You u can create and a run a perf formance sess sion by launch hing the Perfo ormance Wiza ard from the Analyze e menu in Vis sual Studio. W When the perfo ormance sessi ion is running g, you run you ur application as you usually would. While your applic cation is runni ing, you typically aim to use spect may be causing perfo functionalit ty that you sus ormance issue es. Analyze the e profiling repo ort. When you u finish runnin ng your applic cation, Visual Studio displays the profiling report. This includes a range of informatio on that can pr rovide insights s into the perf formance of your app plication. For e example, you can: o o o 3. See wh hich functions consume the e most CPU tim me. View a timeline that shows what y your application was doing g when. View w warnings and s suggestions on how to imp prove your cod de.

2.

Revise your r code and rep peat the analy ysis. When your analysis is complete, c you u should make e changes to your cod de to fix any is ssues that you u identified. Yo ou can then run a new perf formance sess sion and generate a new profiling report. The Visual V Studio P Profiling Tools enable you to compare tw wo reports to help you u identify and quantify how w the performa ance of your code c has chan nged.

Pe erformance sessions work by b sampling. W When you crea ate a performance session, you can choo ose whether you want to sam mple CPU use, , .NET memor ry allocation, concurrency c information fo or multi-threa aded ap pplications, or whether you want to use instrumentatio on to collect d detailed timin ng information n about eve ery function c call. In most ca ases you will want w to start b by using CPU sampling, wh hich is the def fault op ption. CPU sam mpling uses st tatistical pollin ng to determine which func ctions are usin ng the most CPU C time. This provides an n insight into the performance of your application, without consum ming many res sources and slo owing down y your applicatio on.

Programming in Visual C# 2-31

Additional Reading: For more information on application profiling, see the Analyzing Application Performance by Using Profiling Tools page at http://go.microsoft.com/fwlink/?LinkID=267791.

2-32 Creating g Methods, Handling Exceptions, and M Monitoring Applicatiions

Us sing Perfo ormance C Counters

Pe erformance co ounters are sys stem tools tha at collect information on ho ow resources are used. View wing pe erformance co ounters can pr rovide additio onal insights in nto what your r application is doing, and c can help you to troublesh hoot performance problem ms. Performance counters fa all into three main groups: Counters th hat are provide ed by the oper rating system and the unde erlying hardwa are platform. T This group includes counters that yo ou can use to measure proc cessor use, ph hysical memor ry use, disk us se, and network use e. The details of the counte ers available w will vary accor rding to the hardware that the computer c contains. Counters th hat are provide ed by the .NET T Framework. The .NET Framework includes counters that you can use to m measure a wid de range of ap pplication cha aracteristics. F For example, y you can look at a the number of exceptions th hrown, view de etails of locks and thread use, and examine the behav vior of the garbage co ollector. Counters th hat you create yourself. You can create yo our own perfo ormance coun nters to exami ine specific aspects of t the behavior o of your applic cation. For exa ample, you can create a performance counter to count the n number of call ls to a particu ular method or to count the e number of times a specifi ic exception is thrown.

Br rowsing and d Using Performance Counters


Pe erformance co ounters are org ganized into categories c . This helps you t to find the cou unters you wa ant when you are capturin ng and review wing performa ance data. For r example, the e PhysicalDisk category typically inc cludes counte ers for the percentage of tim me spent read ding and writing to disk, am mounts of data read fro om and written to disk, and d the queue le engths to read d data from an nd write data to disk. Note: You u can browse the performance counters available on y your compute er from Visual l Stu udio. In Server Explorer, exp pand Servers s, expand the name of your r computer, an nd then expan nd Pe erformance C Counters. Typically, you ca apture and vie ew data from performance e counters in P Performance M Monitor (perfm mon.exe). Pe erformance Mo onitor is inclu uded in the W Windows opera ating system and a enables yo ou to view or capture data from perfo ormance coun nters in real tim me. When you u use Perform mance Monitor r, you can bro owse

Programming in Visual C# 2-33

performance counter categories and add multiple performance counters to a graphical display. You can also create data collector sets to capture data for reporting or analysis.

Creating Custom Performance Counters


You can use the PerformanceCounter and PerformanceCounterCategory classes to interact with performance counters in a variety of ways. For example, you can: Iterate over the performance counter categories available on a specified computer. Iterate over the performance counters within a specified category. Check whether specific performance counter categories or performance counters exist on the local computer. Create custom performance counter categories or performance counters.

You typically create custom performance counter categories and performance counters during an installation routine, rather than during the execution of your application. After a custom performance counter is created on a specific computer, it remains there. You do not need to recreate it every time you run your application. To create a custom performance counter, you must specify a base counter type by using the PerformanceCounterType enumeration. The following example shows how to programmatically create a custom performance counter category. This example creates a new performance counter category named FourthCoffeeOrders. The category contains two performance counters. The first performance counter tracks the total number of coffee orders placed, and the second tracks the number of orders placed per second. Programmatically Creating Performance Counter Categories and Performance Counters
if (!PerformanceCounterCategory.Exists("FourthCoffeeOrders")) { CounterCreationDataCollection counters = new CounterCreationDataCollection(); CounterCreationData totalOrders = new CounterCreationData(); totalOrders.CounterName = "# Orders"; totalOrders.CounterHelp = "Total number of orders placed"; totalOrders.CounterType = PerformanceCounterType.NumberOfItems32; counters.Add(totalOrders); CounterCreationData ordersPerSecond = new CounterCreationData(); ordersPerSecond.CounterName = "# Orders/Sec"; ordersPerSecond.CounterHelp = "Number of orders placed per second"; ordersPerSecond.CounterType = PerformanceCounterType.RateOfCountsPerSecond32; counters.Add(ordersPerSecond); PerformanceCounterCategory.Create("FourthCoffeeOrders", "A custom category for demonstration", PerformanceCounterCategoryType.SingleInstance, counters); }

Note: You can also create performance counter categories and performance counters from Server Explorer in Visual Studio. When you have created custom performance counters, your application must provide the performance counters with data. Performance counters provide various methods that enable you to update the counter value, such as the Increment and Decrement methods. How the counter processes the value will depend on the base type you selected when you created the counter. The following example shows how to programmatically update custom performance counters. Using Custom Performance Counters
// Get a reference to the custom performance counters.

2-34

Creating Methods, Handling Exceptions, and Monitoring Applications

PerformanceCounter counterOrders = new PerformanceCounter("FourthCoffeeOrders", "# Orders", false); PerformanceCounter counterOrdersPerSec = new PerformanceCounter("FourthCoffeeOrders", "# Orders/Sec", false); // Update the performance counter values at appropriate points in your code. public void OrderCoffee() { counterOrders.Increment(); counterOrdersPerSec.Increment(); // Coffee ordering logic goes here. }

When you have created a custom performance counter category, you can browse to your category and select individual performance counters in Performance Monitor. When you run your application, you can then use Performance Monitor to view data from your custom performance counters in real time.

Programming in i Visual C#

2-35 5

Demonstr D ration: Ex xtending t the Class Enrollmen E nt Applicat tion Functionality L Lab

I this demon In nstration, you will learn abo out the tasks t that you will p perform in the e lab for this module. m

2-36 Creating g Methods, Handling Exceptions, and M Monitoring Applicatiions

Lab: E Extendin ng the Class E Enrollment Applicatio on Functionality y

Sc cenario
Yo ou have been asked to refac ctor the code that you wro ote in the lab e exercises for module m 1 into o separate me ethods to avo oid the duplica ation of code in the Class E Enrollment Ap pplication. Als so, you have b been asked to o write code th hat validates t the student in nformation that the user en nters and to enable the upda ated student information i to o be written b back to the da atabase, handling any error rs that may occur.

Ob bjectives
Aft ter completing this lab, you u will be able to: ode to facilitat te reusability. Refactor co Write Visua al C# code tha at validates da ata entered by y a user. Write Visua al C# code tha at saves chang ges back to a database.

timated Time: : 60 minutes Est Virtual Mac chine: 20483A A-SEA-DEV11-02, MSL-TMG G1 User Name: Student P Password: Pa$$w0rd

Programming in Visual C# 2-37

Exercise 1: Refactoring the Enrollment Code


Scenario
In this exercise, you will refactor the existing code to avoid writing duplicate code. The application currently enables a user to edit a students details by pressing Enter, but you now want them to also be able to initiate the edit process by double-clicking on a student in the list. You will begin by creating a new method that contains the code for editing a students details. This will avoid duplicating and maintaining the code in both event handlers. You will then call the new method from both the studentsList_MouseDoubleClick and StudentsList_Keydown events. While doing this, you also decide to refactor the code for adding and deleting students into separate methods, so that it can be called from other parts of the application if the need arises. You will then run the application and verify that users can press Enter or double-click on a student to edit the students details, can press Insert to add a new student, and can press Delete to remove a student. The main tasks for this exercise are as follows: 1. Copy the code for editing a student into the studentsList_MouseDoubleClick event handler 2. Run the application and verify that the user can now double-click a student to edit their details 3. Use the Analyze Solution for Code Clones wizard to detect the duplicated code 4. Refactor the logic that adds and deletes a student into the addNewStudent and deleteStudent methods 5. Verify that students can still be added and removed from the application 6. Debug the application and step into the new method calls

X Task 1: Copy the code for editing a student into the studentsList_MouseDoubleClick event handler
1. 2. 3. 4. 5. Start the MSL-TMG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-02 virtual machine and log on as Student with the password Pa$$w0rd. Start Visual Studio and open the School.sln solution from the E:\Labfiles\Starter\Exercise 1 folder. In the code for the MainWindow.xaml.cs window, in the studentsList_KeyDown event, locate the code for editing student details which is in the case Key.Enter block. Copy the code in this block to the clipboard and then paste it into the StudentsList_MouseDoubleClick method.

X Task 2: Run the application and verify that the user can now double-click a student to edit their details
1. 2. 3. 4. 5. 6. Build the solution and resolve any compilation errors. Change Kevin Lius last name to Cook by pressing Enter in the main application window. Verify that the updated data is copied back to the students list and that the Save Changes button is now enabled. Change George Lis name to Darren Parker by double-clicking on his row in the main application window. Verify that the updated data is copied back to the student list. Close the application.

2-38

Creating Methods, Handling Exceptions, and Monitoring Applications

X Task 3: Use the Analyze Solution for Code Clones wizard to detect the duplicated code
1. 2. 3. 4. On the Analyze menu, click Analyze Solution for Code Clones. In the Code Clone Analysis Results window, expand Exact Match. Using the results of the analysis in the Code Clone Analysis Results window, refactor the duplicated code into a method called editStudent that takes a Student as a parameter. Call this method from the studentsList_MouseDoubleClick and studentsList_KeyDown methods.

X Task 4: Refactor the logic that adds and deletes a student into the addNewStudent and deleteStudent methods
1. 2. 3. 4. Refactor the code in the case Key.Insert code block in the studentsList_KeyDown method into a method called addNewStudent that takes no parameters. Call this method from the case Key.Insert code block in the studentsList_KeyDown method. Refactor the code in the case Key.Delete code block in the studentsList_KeyDown method into a method called removeStudent that takes a Student as a parameter. Call this method from the case Key.Delete code block in the studentsList_KeyDown method.

X Task 5: Verify that students can still be added and removed from the application
1. 2. 3. 4. 5. 6. Build the solution and resolve any compilation errors. Run the application. Add a new student by pressing Insert to display the New Student for Class 3C window, and verify that it contains no data. Enter details for Dominik Dubicki, whose date of birth is 02/03/2006, and verify that the new student is added to the students list. Delete the student Run Liu and verify that the prompt window appears and the student is removed from the student list. Close the application.

X Task 6: Debug the application and step into the new method calls
1. 2. 3. 4. 5. 6. 7. 8. 9. Add a breakpoint at the start of the switch statement in the studentsList_KeyDown method. Debug the application. Edit the row for Kevin Liu by pressing Enter. Step over the code, watching the Call Stack window and Locals window, until you reach the editStudent method call, and then step into that method. Step out of the editStudent method. Cancel editing the students details, and then continue debugging. Add a new student by pressing Insert. Step over the code until you reach the addNewStudent method call, and then step into that method. Step out of the addNewStudent method.

10. Cancel adding a new student, and then continue debugging. 11. Delete the row for George Li by pressing Delete.

Programming in Visual C# 2-39

12. Step over the code until you reach the removeStudent method call, and then step into that method. 13. Step out of the removeStudent method. 14. Cancel deleting the student. 15. Stop debugging the application. 16. In Visual Studio, delete all breakpoints and then close the solution.

Results: After completing this exercise, you should have updated the application to refactor duplicate code into reusable methods.

2-40

Creating Methods, Handling Exceptions, and Monitoring Applications

Exercise 2: Validating Student Information


Scenario
In this exercise, you will write code that validates the information that a user enters for a student. Up until this point, almost anything can be entered as student data, and fields can be left blank. This means, for example, that a student could be added to the student list with no last name or with an invalid date of birth. You will write code to check that when adding or editing a student, the first name and last name fields for the student contain data. You will also write code to check that the date of birth entered is a valid date and that the student is at least five years old. Finally, you will run the application and test your validation code. The main tasks for this exercise are as follows: 1. Run the application and observe that student details that are not valid can be entered 2. Add code to validate the first name and last name fields 3. Add code to validate the date of birth 4. Run the application and verify that student information is now validated correctly

X Task 1: Run the application and observe that student details that are not valid can be entered
1. 2. 3. 4. 5. 6. In Visual Studio, from the E:\Labfiles\Starter\Exercise 2 folder, open the School.sln solution. Build the solution and resolve any compilation errors. Run the application. Press Insert to display the new student window. Leave the First Name and Last Name boxes empty, and type 10/06/3012 in the Date of Birth box. Click OK and verify that a new row has been added to the student list, containing a blank first name, blank last name, and a negative age. Note: If you enter a date in an invalid format, the application will crash. 7. Close the application.

X Task 2: Add code to validate the first name and last name fields
1. 2. 3. 4. In the ok_Click method in StudentForm.xaml.cs code, add a statement to check if the First Name box is empty. If it is empty, display a message box with a caption of Error containing the text The student must have a first name, and then exit the method. In the ok_Click method in StudentForm.xaml.cs code, add a statement to check if the Last Name box is empty. If it is empty, display a message box with a caption of Error containing the text The student must have a last name, and then exit the click method.

Programming in Visual C# 2-41

X Task 3: Add code to validate the date of birth


1. 2. 3. 4. In the ok_Click method in StudentForm.xaml.cs code, add a statement to check if the Date of Birth box is empty. If the entered date is invalid, display a message box with a caption of Error containing the text The date of birth must be a valid date, and then exit the method. In the ok_Click method in StudentForm.xaml.cs code, add a statement to calculate the students age in years, and check if the age is less than five years. If the age is less than five years, display a message box with a caption of Error containing the text The student must at least 5 years old, and then exit the method.

Note: To work out the age in years, use the following formula: Age in years = Age in Days / 365.25

X Task 4: Run the application and verify that student information is now validated correctly
1. 2. 3. 4. 5. 6. 7. 8. 9. Build the solution and resolve any compilation errors. Run the application. Press Insert to display the new student window. Leave the First Name, Last Name, and Date of Birth boxes empty. Click OK, verify that an error message appears containing the text The student must have a first name, then close the error message box. Type Darren into the First Name box, and then click OK. Verify that an error message appears containing the text The student must have a last name, and then close the error message box. Type Parker into the Last Name box, and then click OK. Verify that an error message appears containing the text The date of birth must be a valid date, and then close the error message box.

10. Type 10/06/3012 into the Date of Birth box, and then click OK. 11. Verify that an error message appears containing the text The student must be at least 5 years old, and then close the error message box. 12. Amend the date to 10/06/2006, click OK, and then verify that Darren Parker is added to the student list with an age appropriate to the current date. 13. Close the application. 14. In Visual Studio, close the solution.

Results: After completing this exercise, student data will be validated before it is saved.

2-42

Creating Methods, Handling Exceptions, and Monitoring Applications

Exercise 3: Saving Changes to the Class List


Scenario
In this exercise, you will write code that saves changes in the student list to the database. Every time the user closes and opens the application, they are presented with the original student list as it existed when they first ran the application, regardless of any changes they may have made. You will write code to save changes back to the database when the user clicks the Save Changes button. You will then add exception handling code to catch concurrency, update, and general exceptions, and handle the exceptions gracefully. Finally, you will run your application and verify that changes you make to student data are persisted between application sessions. The main tasks for this exercise are as follows: 1. Verify that data changes are not persisted to the database 2. Add code to save changes back to the database 3. Add exception handling to the code to catch concurrency, update, and general exceptions 4. Run the application and verify that data changes are persisted to the database

X Task 1: Verify that data changes are not persisted to the database
1. 2. 3. 4. 5. 6. 7. 8. 9. In Visual Studio, from the E:\Labfiles\Starter\Exercise 3 folder, open the School.sln solution. Build the solution and resolve any compilation errors. Run the application. Change Kevin Lius last name to Cook by pressing Enter in the main application window. Verify that the updated data is copied to the student list and that the Save Changes button is enabled. Click Save Changes. Delete the student George Li, and then click the Save Changes button. Close the application. Run the application again and verify that it displays the original list of students, without the changes that you just made.

10. Close the application.

X Task 2: Add code to save changes back to the database


1. 2. In the MainWindow.xaml.cs code bring the System.Data and System.Data.Objects namespaces into scope. Add code to perform the following tasks when a user clicks Save Changes: a. b. Call the SaveChanges method of the schoolContext object. Disable the Save Changes button.

X Task 3: Add exception handling to the code to catch concurrency, update, and general exceptions
1. Enclose the lines of code that call the SaveChanges method of the schoolContext object and disable the Save Changes button in a try block.

Programming in Visual C# 2-43

2. 3.

Below the try block, add a catch block to catch any OptimisticConcurrencyException exceptions that may occur. In the catch block, add the following code:
// If the user has changed the same students earlier, then overwrite their changes with the new data this.schoolContext.Refresh( RefreshMode.StoreWins, schoolContext.Students); this.schoolContext.SaveChanges();

4. 5.

Add another catch block to catch any UpdateException exceptions that may occur, storing the exception in a variable named uEx. In the catch block, add the following code:
// If some sort of database exception has occurred, then display the reason for the exception and rollback MessageBox.Show(uEx.InnerException.Message, "Error saving changes"); this.schoolContext.Refresh(RefreshMode.StoreWins, schoolContext.Students);

6. 7.

Add another catch block to catch any other type of exception that might occur, storing the exception in a variable named ex. In the catch block, add the following code:
// If some other exception occurs, report it to the user MessageBox.Show(ex.Message, "Error saving changes"); this.schoolContext.Refresh( RefreshMode.ClientWins, schoolContext.Students);

X Task 4: Run the application and verify that data changes are persisted to the database
1. 2. 3. 4. 5. 6. 7. 8. 9. Build the solution and resolve any compilation errors. Run the application. Change Kevin Lius last name to Cook by pressing Enter in the main application window. In the main application window, click Save Changes. Delete the student George Li by pressing Delete. Click Save Changes and note that the button is disabled when no changes are pending. Close the application. Run the application and verify that the changes you made to the student data have been saved to the database and are reflected in the student list. Close the application

10. In Visual Studio, close the solution.

Results: After completing this exercise, modified student data will be saved to the database

2-44 Creating g Methods, Handling Exceptions, and M Monitoring Applicatiions

Modu ule Revi iew and d Takea aways

M Module Revie ew
In this module, y you learned how h to create and use meth hods, and how w to handle exceptions. You also lea arned how to use logging a and tracing to o record the details of any e exceptions tha at occur. Ve erify the correc ctness of the statement by placing a ma ark in the column to the rig ght. S Statement T return typ The pe of a metho od forms part of a methods s signature. Test Your Know wledge Q Question W When using o output parameters in a me ethod signature, which one e of the follow wing statements is true? S Select the cor rrect answer. You ca annot return d data by using a return state ement in a me ethod that use e output param meters. You ca an only use th he type object t when definin ng an output parameter. You m must assign a v value to an ou utput paramet ter before the e method retu urns. You de efine an output parameter by using the output keywo ord. Ve erify the correc ctness of the statement by placing a ma ark in the column to the rig ght. S Statement A finally block k enables you to run code in i the event o of an error occ curring? Ve erify the correc ctness of the statement by placing a ma ark in the column to the rig ght. Answer Answer

Programming in Visual C# 2-45

Statement Trace statements are active in both Debug and Release mode builds.

Answer

3-1

Module 3
Developing the Code for a Graphical Application
Contents:
Module Overview Lesson 1: Implementing Structs and Enums Lesson 2: Organizing Data into Collections Lesson 3: Handling Events Lab: Writing the Code for the Grades Prototype Application Module Review and Takeaways 3-2 3-3 3-17 3-31 3-41 3-52

3-2

Developin ng the Code for a Graphical Application n

Modu ule Ove erview

To o create effective graphical applications b by using Wind dows Presenta ation Foundat tion (WPF) or other .NET Fra amework plat tforms, you must first learn some basic V Visual C# cons structs. You ne eed to know h how to cre eate simple structures to re epresent the d data items you u are working with. You nee ed to know how to org ganize these structures s into o collections, so that you ca an add items, retrieve items, and iterate over your ite ems. Finally, yo ou need to kn now how to su ubscribe to ev vents so that y you can respo ond to the actions of your users. you will learn how to creat te and use stru ucts and enum ms, organize d data into colle ections, and In this module, y cre eate and subscribe to event ts.

Ob bjectives
Aft ter completing this module e, you will be able to: nd enums. Create and use structs an Use collection classes to organize data a. events. Create and subscribe to e

Programming g in Visual C#

3-3 3

Lesson 1

Implementi ing Stru ucts and d Enum ms

The .NET Fram T mework includ des various bu uilt-in data typ pes, such as In nt32, Decima al, String, and d Boolean. H However, suppose you wan nt to create an n object that represented a coffee. Whic ch type would you use? Y might use You e built-in type es to represen nt the propert ties of a coffee e, such as the country of or rigin (a string) ) o the strengt or th of the coffe ee (an integer r). However, yo ou need a way to represent coffee as a d discrete e entity, so that t you can perf form actions s such as add a coffee to a co ollection or co ompare one c coffee to a another. I this lesson, you will learn In n how to use structs s and en nums to create e your own simple types.

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Create an nd use enums. Create an nd use structs. . Define co onstructors to instantiate st tructs. Create pr roperties to ge et and set field values in a s struct. Create ind dexers to expose struct me embers by usin ng an integer r index.

3-4

Developin ng the Code for a Graphical Application n

Cr reating an nd Using E Enums

An n enumeration n type, or enu um, is a structu ure that enabl les you to create a variable e with a fixed s set of po ossible values. The most com mmon examp ple is to use an n enum to def fine the day o of the week. There are on nly seven poss sible values for days of the w week, and you can be reasonably certain n that these v values will ne ever change. te an enum: The following ex xample shows s how to creat eclaring an En num De
e enum Day { Su unday, Monda ay, Tuesday, Wednesday, Thursday, F Friday, Satu urday };

To o use the enum m, you create an instance o of your enum variable and s specify which enum memb ber you wa ant to use. The following ex xample shows s how to use an a enum: Us sing an Enum m
D Day favoriteD Day = Day.Fr riday;

Us sing enums ha as several advantages over using text or numerical typ pes: Improved manageability m . By constraini ing a variable to a fixed set t of valid value es, you are les ss likely to experience invalid argum ments and spe elling mistakes s. Improved developer d expe erience. In Visu ual Studio, the e IntelliSense feature will prompt you with the available va alues when yo ou use an enum. Improved co ode readability ty. The enum syntax s makes your code ea asier to read a and understan nd.

Each member o of an enum ha as a name and d a value. The name is the s string you def fine in the bra aces, such as Sunday or Mond day. By default, the value is s an integer. If you do not specify a value for each me ember, the me embers are as ssigned increm mental values starting with 0. For example, Day.Sunday is equal to o 0 and Da ay.Monday is s equal to 1. The following ex xample shows s how you can n use names a and values int terchangeably y:

Programming in Visual C# 3-5

Using Enum Names and Values Interchangeably


// Set an enum variable by name. Day favoriteDay = Day.Friday; // Set an enum variable by value. Day favoriteDay = (Day)4;

Reference Links: For more information about enums, see the Enumeration Types (C# Programming Guide) page at http://go.microsoft.com/fwlink/?LinkID=267792.

3-6

Developin ng the Code for a Graphical Application n

Cr reating an nd Using S Structs

In Visual C#, a s struct is a prog gramming con nstruct that yo ou can use to define custom m types. Struc cts are ess sentially lightw weight data structures that t represent rel lated pieces o of information n as a single it tem. For exa ample: med Point might consist of fields to rep present an x-co oordinate and d a y-coordina ate. A struct nam A struct nam med Circle might consist o of fields to rep present an x-coordinate, a y y-coordinate, and a radius. med Color might consist of fields to rep present a red c component, a green compo onent, and A struct nam a blue component.

Mo ost of the built-in types in V Visual C#, suc ch as int, bool, and char, are defined by y structs. You c can use str ructs to create e your own types that beha ave like built-in types.

Cr reating a St truct
Yo ou use the stru uct keyword t to declare a st truct, as show wn by the follo owing example: De eclaring a Str ruct
p public struct t Coffee { public int t Strength; public string Bean; public string Country yOfOrigin; // Other m methods, fie elds, proper rties, and ev vents. }

The struct keyw word is preced ded by an acce ess modifier public in the above exam mplethat spe ecifies wh here you can u use the type. Y You can use t the following access modifi iers in your struct declaratio ons: A Access Modifi ier p public i internal Details s The ty ype is available to code run nning in any assembly. The ty ype is available to any code e within the sa ame assembly y, but not avai ilable to code in i another ass sembly. This is s the default v value if you do o not specify an access modif fier.

Programming in Visual C# 3-7

Access Modifier private

Details The type is only available to code within the struct that contains it. You can only use the private access modifier with nested structs.

Structs can contain a variety of members, including fields, properties, methods, and events.

Using a Struct
To create an instance of a struct, you use the new keyword, as shown by the following example: Instantiating a Struct
Coffee coffee1 = new Coffee(); coffee1.Strength = 3; coffee1.Bean = "Arabica"; coffee1.CountryOfOrigin = "Kenya";

3-8

Developin ng the Code for a Graphical Application n

In nitializing Structs

Yo ou might have e noticed that the syntax fo or instantiating g a struct, for example, new w Coffee(), is similar to the e syntax for ca alling a metho od. This is bec cause when yo ou instantiate e a struct, you are actually c calling a spe ecial type of m method called d a constructo or. A construct tor is a metho od in the struc ct that has the e same name as the stru uct. hen you instantiate a struct t with no argu uments, such as new Coffe ee(), you are c calling the def fault Wh con nstructor whic ch is created b by the Visual C# compiler. If you want to o be able to specify default t field values when you u instantiate a struct, you can c add constructors that a accept parame eters to your s struct. xample shows s how to creat tor in a struct: : The following ex te a construct Ad dding a Cons structor
p public struct t Coffee { // This is s the custom m constructo or. public Cof ffee(int str rength, string bean, string country yOfOrigin) { this.St trength = st trength; this.Be ean = bean; this.Co ountryOfOrig gin = countr ryOfOrigin; } // These st tatements de eclare the s struct fields s and set th he default v values. public int t Strength; public string Bean; public string Country yOfOrigin; // Other m methods, fie elds, proper rties, and ev vents. }

The following ex xample shows s how to use this t constructor to instantia ate a Coffee i item: Ca alling a Const tructor
/ // Call the c custom const tructor by p providing arg guments for the three r required para ameters. C Coffee coffee e1 = new Cof ffee(4, "Ara abica", "Colu umbia");

Yo ou can add mu ultiple constru uctors to your r struct, with e each construct tor accepting a different co ombination of parameters. H However, you cannot add a default cons structor to a struct because e it is created by the compiler.

Programming in Visual C# 3-9

3-10

Develop ping the Code for a Graphical Applicatio on

Cr reating Pr roperties

In Visual C#, a p property is a programming p construct that enables client code to ge et or set the va alue of pri ivate fields within a struct o or a class. To c consumers of your struct or class, the property behaves like a pu ublic field. Wit thin your struc ct or class, the e property is implemented by using acce essors, which are a a spe ecial type of m method. A pro operty can inc clude one or b both of the fo ollowing: A get acces ssor to provide read access to a field. A set accessor to provide e write access s to a field.

xample shows s how to impl lement a prop perty in a struct: The following ex Im mplementing a Property
p public struct t Coffee { private in nt strength; ; public int t Strength { get { return stren ngth; } set { s strength = v value; } } }

Wi ithin the prop perty, the get and set acces ssors use the f following synt tax: The get acc cessor uses the return keyw word to return n the value of f the private fi ield to the cal ller. The set acc cessor uses a s special local va ariable named d value to set t the value of the private fie eld. The value variable contains t the value prov vided by the c client code wh hen it accesse ed the propert ty.

xample shows s how to use a property: The following ex Us sing a Proper rty
C Coffee coffee e1 = new Cof ffee(); / // The follow wing code in nvokes the s set accessor. c coffee1.Stren ngth = 3; / // The follow wing code in nvokes the g get accessor. int coffeeStrength = cof ffee1.Streng gth;

Programming in Visual C# 3-11

The client code uses the property as if as it was a public field. However, using public properties to expose private fields offers the following advantages over using public fields directly: You can use properties to control external access to your fields. A property that includes only a get accessor is read-only, while a property that includes only a set accessor is write-only.
// This is a read-only property. public int Strength { get { return strength; } } // This is a write-only property. public string Bean { set { bean = value; } }

You can change the implementation of properties without affecting client code. For example, you can add validation logic, or call a method instead of reading a field value.
public int Strength { get { return strength; } set { if(value < 1) { strength = 1; } else if(value > 5) { strength = 5; } else { strength = value; } } }

Properties are required for data binding in WPF. For example, you can bind controls to property values, but you cannot bind controls to field values.

When you want to create a property that simply gets and sets the value of a private field without performing any additional logic, you can use an abbreviated syntax. To create a property that reads and writes to a private field, you can use the following syntax:
public int Strength { get; set; }

To create a property that reads from a private field, you can use the following syntax:
public int Strength { get; }

To create a property that writes to a private field, you can use the following syntax:
public int Strength { set; }

In each case, the compiler will implicitly create a private field and map it to your property. These are known as auto-implemented properties. You can change the implementation of your property at any time. Additional Reading: In addition to controlling access to a property by omitting get or set accessors, you can also restrict access by applying access modifiers (such as private or protected) to your accessors. For example, you might create a property with a public get accessor and a protected set accessor. For more information, see the Restricting Accessor Accessibility (C# Programming Guide) page at http://go.microsoft.com/fwlink/?LinkID=267793.

3-12

Developing the Code for a Graphical Application

Programming in i Visual C#

3-13 3

C Creating I Indexers

In some scena I arios, you mig ght want to us se a struct or a class as a co ontainer for an n array of valu ues. For e example, you might create a struct to re epresent the b beverages available at a cof ffee shop. The e struct might t u an array of use o strings to st tore the list of f beverages. T following example sho The ows a struct th hat includes an n array: C Creating a St truct that Inc cludes an Arr ray
public stru uct Menu { public s string[] bev verages; public M Menu(string bev1, string bev2) { bever rages = new string[] { "Americano", , "Caf au Lait", L "Caf Macchiato", "Cappuccino o", "Espress so" }; } }

When you exp W pose the array y as a public f field, you wou uld use the fol llowing syntax x to retrieve b beverages f from the list: A Accessing Ar rray Items Directly
Menu myMenu u = new Menu u(); string firs stDrink = my yMenu.beverages[0];

A more intuiti ive approach would be if you could acce ess the first ite em from the m menu by using g the syntax m myMenu[0] . You can do th his by creating g an indexer. An indexer is similar to a p property, in that it uses get a set access and sors to contro ol access to a field. f More im mportantly, an n indexer enab bles you to access c collection members directly y from the na ame of the con ntaining struc ct or class by p providing an integer i index v value. To decl lare an indexe er, you use the e this keywor rd, which indic cates that the property will be accessed b using the n by name of the struct instance e.

3-14

Developing the Code for a Graphical Application

The following example shows how to define an indexer for a struct: Creating an Indexer
public struct Menu { private string[] beverages; // This is the indexer. public string this[int index] { get { return this.beverages[index]; } set { this.beverages[index] = value; } } // Enable client code to determine the size of the collection. public int Length { get { return beverages.Length; } } }

When you use an indexer to expose the array, you use the following syntax to retrieve the beverages from the list: Accessing Array Items by Using an Indexer
Menu myMenu = new Menu(); string firstDrink = myMenu[0]; int numberOfChoices = myMenu.Length;

Just like a property, you can customize the get and set accessors in an indexer without affecting client code. You can create a read-only indexer by including only a get accessor, and you can create a writeonly indexer by including only a set accessor. Reference Links: For more information about indexers, see the Using Indexers (C# Programming Guide) page at http://go.microsoft.com/fwlink/?LinkID=267794.

Programming in i Visual C#

3-15 5

D Demonstr ration: Cr reating an nd Using a Struct

In this demon I nstration, you will create a s struct named Coffee and a add several pr roperties to th he struct. You w then creat will te an instance e of the Coffe ee struct, set some s property y values, and display these property v values in a console window w.

D Demonstra ation Steps


1 1. 2 2. 3 3. Start the MSL-TMG1 vi irtual machine e if it is not already running g. Start the 20483A-SEA-DEV11-03 vir rtual machine. . Log on to o Windows 8 as a Student with the passwo rd. ord Pa$$w0r Note: If f necessary, click Switch Us ser to display the list of use ers. 4 4. 5 5. 6 6. 7 7. 8 8. 9 9. Switch to the Windows s 8 Start wind dow. Click Visu ual Studio 20 012. In Visual Studio, on the e File menu, p point to New, and then clic ck Project. In the Ne ew Project dia alog box, in th he Templates s list, click Vis sual C#, and t then in the Pr roject Type list, click Console C App plication. In the Na ame box, type e UsingStruct ts In the Loc cation box, se et the location n to E:\Demo ocode, and then click OK.

1 In the UsingStructs na 10. amespace, add the followin ng code:


struct C Coffee { publi ic string Na ame { get; set; } publi ic string Be ean { get; set; } publi ic string Co ountryOfOrigin { get; se et; } publi ic int Stren ngth { get; set; } }

3-16

Developing the Code for a Graphical Application

11. In the Program class, in the Main method, add the following code:
Coffee coffee1 = new Coffee(); coffee1.Name = "Fourth Coffee Quencher"; coffee1.CountryOfOrigin = "Indonesia"; coffee1.Strength = 3; Console.WriteLine("Name: {0}", coffee1.Name); Console.WriteLine("Country of Origin: {0}", coffee1.CountryOfOrigin); Console.WriteLine("Strength: {0}", coffee1.Strength);

12. Notice that you are able to use the Coffee struct in the same way that you would use a standard .NET Framework type. 13. On the Build menu, click Build Solution. 14. On the Debug menu, click Start Without Debugging. 15. Notice that the Coffee struct works just like a standard .NET Framework type at runtime. 16. Press Enter to close the console window. 17. Close Visual Studio.

Programming in i Visual C#

3-17 7

Lesson 2

Orga anizing Data in nto Collection ns

When you cre W eate multiple items of the same s type, reg gardless of wh hether they ar re integers, str rings, or a c custom type s such as Coffee, you need a way of mana aging the item ms as a set. Yo ou need to be able to c count the num mber of items s in the set, ad dd items to or r remove item ms from the set, and iterate through the s one item a set at a time. To d do this, you ca an use a collec ction. Collections ar C re an essential l tool for man naging multiple items. They y are also cent tral to develop ping g graphical app plications. Con ntrols such as drop-down list boxes and menus are typ pically data-b bound to c collections. I this lesson, you will learn In n how to use a variety of co ollection classes in Visual C# #.

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Choose appropriate co ollections for d different scenarios. Manage items i in a coll lection. Use Language Integrat ted Query (LIN NQ) syntax to query a colle ection.

3-18

Develop ping the Code for a Graphical Applicatio on

Ch hoosing C Collections s

All l collection cla asses share va arious commo on characterist tics. To manag ge a collection n of items, yo ou must be ab ble to: to the collection. Add items t Remove items from the c collection. ecific items fro om the collec ction. Retrieve spe Count the n number of items in the collection. Iterate through the items s in the collec ction, one item m at a time.

ery collection class in Visua al C# provides s methods and d properties t that support these core ope erations. Eve Be eyond these operations, how wever, you wi ill want to ma anage collectio ons in differen nt ways depen nding on the e specific requ uirements of your y applicati ion. Collection n classes in Visual C# fall into the followi ing broad cat tegories: ollections of it tems. You can n think of a lis st class as a on ne-dimensional array List classes store linear co that dynam mically expands as you add items. For exa ample, you might use a list class to main ntain a list of available e beverages at t your coffee shop. s Dictionary c classes store a collection of f key/value pa airs. Each item m in the collect tion consists o of two objectsth he key and the e value. The va alue is the obj ject you want t to store and retrieve, and the key is the object t that you use t to index and look up the va alue. In most dictionary d clas sses, the key m must be unique, whe ereas duplicat te values are perfectly p acce eptable. For ex xample, you might m use a di ictionary class to mai intain a list of f coffee recipe es. The key wo ould contain t the unique na ame of the cof ffee, and the value w would contain the ingredien nts and the ins structions for making the coffee. c Queue class ses represent a first in, first out collection n of objects. It tems are retrieved from the e collection in the same e order they w were added. Fo or example, you might use a queue class s to process o orders in a drinks in turn. coffee shop p to ensure that customers receive their d Stack classe es represent a last in, first o out collection of objects. Th he item that yo ou added to t the collection la ast is the first item you retr rieve. For exam mple, you mig ght use a stack k class to dete ermine the 10 most rec cent visitors to o your coffee shop.

Wh hen you choo ose a built-in c collection clas ss for a specifi ic scenario, as sk yourself the e following qu uestions:

Programming in Visual C# 3-19

Do you need a list, a dictionary, a stack, or a queue? Will you need to sort the collection? How large do you expect the collection to get? If you are using a dictionary class, will you need to retrieve items by index as well as by key? Does your collection consist solely of strings?

If you can answer all of these questions, you will be able to select the Visual C# collection class that best meets your needs.

3-20

Develop ping the Code for a Graphical Applicatio on

St tandard Collection Classes

The System.Collections nam mespace provides a range of o general-pur rpose collectio ons that includes lists, dic ctionaries, que eues, and stac cks. The follow wing table sho ows the most important collection classe es in the Sy ystem.Collect tions namespa ace: C Class A ArrayList Descr ription The A ArrayList is a general-purp pose list that s stores a linear r collection of f objects. The A ArrayList includes method ds and proper rties that enab ble you to add d items, remo ove items, cou unt the numb ber of items in the collection n, and sort the colle ection. The BitArray is a list class that represents a collection c of b bits as Boolean values. most commonl ly used for bit twise operatio ons and Boole ean The BitArray is m hmetic, and includes metho ods to perform m common Bo oolean operat tions such arith as AND, NOT, and d XOR. The Hashtable cla ass is a genera al-purpose dictionary class s that stores a collection ey/value pairs s. The Hashtable includes m methods and properties tha at enable of ke you to retrieve ite ems by key, ad dd items, remove items, and check for particular within the colle ection. keys and values w The Queue class is a first in, las st out collectio on of objects. The Queue in ncludes hods to add o objects to the back of the q queue (Enqueue) and retrie eve objects meth from m the front of the queue (Dequeue). The SortedList cla ass stores a co ollection of ke ey/value pairs that are sorte ed by key. ddition to the functionality provided by the Hashtabl le class, the So ortedList In ad enab bles you to ret trieve items either by key or o by index. The Stack class is a first in, first t out collection of objects. T The Stack includes hods to view the t top item i in the collectio on without re emoving it (Pe eek), add meth an it tem to the top p of the stack (Push), and r remove and re eturn the item m at the top of th he stack (Pop) ).

B BitArray

H Hashtable

Q Queue

S SortedList

S Stack

Programming in Visual C# 3-21

Reference Links: For more information about the classes listed in the previous table, see the System.Collections Namespace page at http://go.microsoft.com/fwlink/?LinkID=267795.

3-22

Develop ping the Code for a Graphical Applicatio on

Sp pecialized Collectio on Classes

The System.Collections.Spe ecialized namespace provid des collection classes that a are suitable fo or more spe ecialized requ uirements, suc ch as specializ zed dictionary y collections and strongly ty yped string co ollections. The following ta able shows the most impor rtant collection classes in th he System.Co ollections.Spe ecialized namespace: C Class L ListDictionar ry Descriptio on The L ListDictionary y is a dictiona ary class that is optimized fo or small collec ctions. As a ge eneral rule, if y on includes 10 0 items or your collectio fewer r, use a ListDi ictionary. If y your collection n is larger, use ea Hash htable. The HybridDiction H nary is a dictionary class th hat you can us se when you cannot c estimate the size of the collection n. The Hybrid dDictionary uses a ListDictiona ary implemen ntation when the collection n size is small, and switches s to a Hashta able implemen ntation as the e collection grows larger. size g The OrderedDictio O onary is an in ndexed diction nary class that t enables you to retrieve item ms by key or by b index. Note that unlike t the edList class, it tems in an Ord deredDiction nary are not s sorted by Sorte key. The NameValueCo N ollection is an indexed dic ctionary class i in which both the key and t the value are strings. s The N NameValueCo ollection will th hrow an error r if you attemp pt to set a key y or a value to o anything other r than a string g. You can retr rieve items by y key or by ind dex. The StringCollecti S ion is a list cla ass in which e every item in t the collec ction is a strin ng. Use this cla ass when you want to store e a simple, linear r collection of f strings. The StringDiction S nary is a dictio onary class in which both th he key and the va alue are string gs. Unlike the NameValueC Collection cla ass, you canno ot retrieve items from a Str ringDictionar ry by index.

H HybridDictio onary

O OrderedDicti ionary

N NameValueC Collection

S StringCollect tion

S StringDiction nary

Programming in Visual C# 3-23

Class BitVector32

Description The BitVector32 is a struct that can represent a 32-bit value as both a bit array and an integer value. Unlike the BitArray class, which can expand indefinitely, the BitVector32 struct is a fixed 32-bit size. As a result, the BitVector32 is more efficient than the BitArray for small values. You can divide a BitVector32 instance into sections to efficiently store multiple values.

Reference Links: For more information about the classes and structs listed in the previous table, see the System.Collections.Specialized Namespace page at http://go.microsoft.com/fwlink/?LinkID=267796.

3-24

Develop ping the Code for a Graphical Applicatio on

Us sing List C Collections

The most comm monly used list t collection is the ArrayList t class. The Ar rrayList store es items as a linear collection of obj jects. You can n add objects of any type to o an ArrayLis st collection, b but the Array yList rep presents each item in the c collection as a System.Obje ect instance. W When you add d an item to a an Ar rrayList collec ction, the Arra ayList implicit tly casts, or co onverts, your item to the O Object type. W When you ret trieve items fr rom the collec ction, you must explicitly ca ast the object back to its or riginal type. The following ex xample shows s how to add and retrieve i items from an n ArrayList co ollection: Ad dding and Re etrieving Item ms from an A ArrayList
/ // Create a n new ArrayLis st collectio on. A ArrayList bev verages = ne ew ArrayList t(); / // Create som me items to add to the collection. C Coffee coffee e1 = new Cof ffee(4, "Ara abica", "Colu umbia"); C Coffee coffee e2 = new Cof ffee(3, "Ara abica", "Viet tnam"); C Coffee coffee e3 = new Cof ffee(4, "Rob busta", "Indo onesia"); / // Add the it tems to the collection. / // Items are implicitly cast to the e Object type e when you a add them. b beverages.Add d(coffee1); b beverages.Add d(coffee2); b beverages.Add d(coffee3); / // Retrieve i items from t the collection. / // Items must t be explici itly cast ba ack to their original ty ype. C Coffee firstC Coffee = (Co offee)bevera ages[0]; C Coffee second dCoffee = (C Coffee)bever rages[1];

Wh hen you work k with collectio ons, one of yo our most common program mming tasks w will be to iterate over the collection. Essen ntially, this me eans that you retrieve each item from th he collection in n turn, usually y to render a list of items, to o evaluate eac ch item again nst some criter ria, or to extra act specific me ember values from each ite em. To iterate over a collect tion, you use a foreach loo op. The foreac ch loop expos ses each item from the collection in tur rn, using the variable v name e you specify in the loop de eclaration. xample shows s how to itera ate over an Ar rrayList collect tion: The following ex

Programming in Visual C# 3-25

Iterating Over a List Collection


foreach(Coffee coffee in beverages) { Console.WriteLine("Bean type: {0}", coffee.Bean); Console.WriteLine("Country of origin: {0}", coffee.CountryOfOrigin); Console.WriteLine("Strength (1-5): {0}", coffee.Strength); }

Reference Links: For more information on the ArrayList class, see the ArrayList Class page at http://go.microsoft.com/fwlink/?LinkID=267797.

3-26

Develop ping the Code for a Graphical Applicatio on

Us sing Dictionary Col llections

Dic ctionary classe es store collec ctions of key/ /value pairs. Th he most comm monly used dictionary class s is the Ha ashtable. Whe en you add an n item to a Ha ashtable colle ection, you m must specify a key and a value. Both the e key and the value can be e instances of any type, but the Hashtab ble implicitly c casts both the key and the e value to the e Object type. . When you re etrieve values from the collection, you m must explicitly cast the ob bject back to it ts original typ pe. The following ex xample shows s how to add and retrieve i items from a Hashtable H co ollection. In th his case bo oth the key an nd the value are strings: Ad dding and Re etrieving Item ms from a Ha ashtable
/ // Create a n new Hashtabl le collectio on. H Hashtable ing gredients = new Hashtab ble(); / // Add some k key/value pa airs to the collection. ingredients.A Add("Caf au u Lait", "Co offee, Milk") ); ingredients.A Add("Caf Mo ocha", "Coff fee, Milk, Ch hocolate"); ingredients.A Add("Cappucc cino", "Coff fee, Milk, Fo oam"); ingredients.A Add("Irish C Coffee", "Co offee, Whiske ey, Cream, S Sugar"); ingredients.A Add("Macchia ato", "Coffe ee, Milk, Foa am"); / // Check whet ther a key e exists. if(ingredient ts.ContainsK Key("Caf Mo ocha")) { // Retriev ve the value e associated d with a key. Console.WriteLine("Th he ingredien nts of a Caf Mocha are: : {0}", ingr redients["Caf f M Mocha"]); }

Dic ctionary classe es, such as the e Hashtable, actually contain two enum merable collect tionsthe ke eys and the values. You can iterate over e either of these e collections. In I most scena arios, however r, you are likel ly to iterate thr rough the key y collection, fo or example to o retrieve the value v associat ted with each key in turn. The following ex xample shows s how to itera ate over the ke eys in a Hashtable collectio on and retriev ve the value associated d with each ke ey:

Programming in Visual C# 3-27

Iterating Over a Dictionary Collection


foreach(string key in ingredients.Keys) { // For each key in turn, retrieve the value associated with the key. Console.WriteLine("The ingredients of a {0} are {1}", key, ingredients[key]); }

Reference Links: For more information on the Hashtable class, see the Hashtable Class page at http://go.microsoft.com/fwlink/?LinkID=267798.

3-28

Develop ping the Code for a Graphical Applicatio on

Querying a Collectio on

LIN NQ is a query technology that is built in to .NET langu uages such as Visual C#. LIN NQ enables yo ou to use a sta andardized, de eclarative que ery syntax to q query data fro om a wide ran nge of data so ources, such as s .NET collections, SQL L Server datab bases, ADO.NE ET datasets, an nd XML docum ments. A basic c LINQ query uses the fol llowing syntax x: fro om <variable names> in <data source> wh here <selectio on criteria> orderby <result t ordering crit teria> e names> select <variable se a Hashtabl le to maintain n a price list fo or beverages a at Fourth Coff fee. You For example, suppose you us ight use a LIN NQ expression to retrieve all the drinks th hat meet certa ain price criteria, such as dr rinks that mi cost less than $2 2.00. xample shows s how to use a LINQ expres ssion to query y a Hashtable e: The following ex Us sing LINQ to Query a Coll lection
/ // Create a n new Hashtabl le and add s some drinks with w prices. . H Hashtable pri ices = new H Hashtable(); p prices.Add("C Caf au Lait t", 1.99M); p prices.Add("C Caffe Americ cano", 1.89M M); p prices.Add("C Caf Mocha", , 2.99M); p prices.Add("C Cappuccino", , 2.49M); p prices.Add("E Espresso", 1 1.49M); p prices.Add("E Espresso Rom mano", 1.59M M); p prices.Add("E English Tea" ", 1.69M); p prices.Add("J Juice", 2.89 9M); / // Select all l the drinks s that cost less than $2 2.00, and or rder them by y cost. v var bargains = from strin ng drink in prices.Keys s where (Dec cimal)prices s[drink] < 2 2.00M orderby p prices[drink k] ascending g select dri ink; / // Display th he results. f foreach(strin ng bargain i in bargains) { Console.WriteLine(bar rgain);

Programming in Visual C# 3-29

} Console.ReadLine();

Note: Appending the suffix m or M to a number indicates that the number should be treated as a decimal type. In addition to this basic query syntax, you can call a variety of methods on your query results. For example: Call the FirstOrDefault method to get the first item from the results collection, or a default value if the collection contains no results. This method is useful if you have ordered the results of your query. Call the Last method to get the last item from the results collection. This method is useful if you have ordered the results of your query. Call the Max method to find the largest item in the results collection. Call the Min method to find the smallest item in the results collection.

Note: Most built-in types provide methods that enable you to compare one instance to another to determine which is considered larger or smaller. The Max and Min methods rely on these methods to find the largest or smallest items. If your collection contains numerical types, these methods will return the highest and lowest values, respectively. If your collection contains strings, members are compared alphabeticallyfor example, "Z" is considered greater than "A". If your collection contains custom types, the Max and Min methods will use the comparison logic created by the type developer. For example, if you have ordered your results by ascending cost, the first item in the results collection will be the cheapest and the last item in the results collection will be the most expensive. As such, you can use the FirstOrDefault and Last methods to find the cheapest and most expensive drinks, respectively. The following example shows how to retrieve the smallest and largest items from a collection based on the sort criteria in the LINQ expression: Using the FirstOrDefault and Last Methods
// Query the Hashtable to order drinks by cost. var drinks = from string drink in prices.Keys orderby prices[drink] ascending select drink; Console.WriteLine("The cheapest drink is {0}: ", drinks.FirstOrDefault()); // Output: "The cheapest drink is Espresso" Console.WriteLine("The most expensive drink is {0}: ", drinks.Last()); // Output: "The most expensive drink is Caf Mocha" Console.WriteLine("The maximum is {0}: ", drinks.Max()); // Output: "The maximum is Juice" // "Juice" is the largest value in the collection when ordered alphabetically. Console.WriteLine("The minimum is {0}: ", drinks.Min()); // Output: "The minimum is Caf au Lait" // "Caf au Lait" is the smallest value in the collection when ordered alphabetically.

Note: The return type of a LINQ expression is IEnumerable<T>, where T is the type of the items in the collection. IEnumerable<T> is an example of a generic type. The methods you use on a results set, such as FirstOrDefault, Last, Max, and Min, are extension methods. Generic types and extension methods are covered later in this course.

3-30

Developing the Code for a Graphical Application

Reference Links: For more information about using LINQ to query collections, see the LINQ Query Expressions (C# Programming Guide) page at http://go.microsoft.com/fwlink/?LinkID=267799.

Programming in i Visual C#

3-31 1

Lesson 3

Hand dling Ev vents

Events are me E echanisms tha at enable obje ects to notify o other objects when someth hing happens. . For example, , c controls on a web page or in a WPF user interface generate events s when a user interacts with h the control, s such as by clic cking a button n. You can cre eate code that subscribes to o these events s and takes so ome action in r response to an event. Without events, your code would need t W to constantly read control values v to look k for any chan nges in state t that require action. This wo ould be a very y inefficient way of develop ping an applic cation. In this lesson, you w learn how will w to create, or raise, events, and how to s subscribe to e events. I this lesson, you will learn In n how to hand dle events.

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Create ev vents and dele egates. Raise events. Subscribe e to events an nd unsubscribe e from events s.

3-32

Develop ping the Code for a Graphical Applicatio on

Cr reating Ev vents and Delegates

Wh hen you creat te an event in a struct or a class, you nee ed a way of en nabling other code to subscribe to your event. In V Visual C#, you accomplish th his by creating g a delegate. A delegate is a special type e that de efines a metho od signature; in i other word ds, the return type t and the parameters of f a method. A As the name sug ggests, a dele egate behaves s like a represe entative for methods m with matching sign natures. Wh hen you defin ne an event, you associate a delegate wit th your event. To subscribe e to the event t from client code, you need to: Create a me ethod with a signature s that t matches the e event delega ate. This meth hod is known a as the event handler. o the event by y giving the name n of your event handler method to t the event publ lisher, in Subscribe to other words, the object t that will raise the event.

Wh hen the event t is raised, the e delegate invokes all the ev vent handler methods that t have subscribed to the eve ent. Suppose you cre eate a struct n named Coffee e. One of the responsibilitie es of this struc ct is to keep t track of the sto ock level for e each Coffee in nstance. When n the stock lev vel drops belo ow a certain p point, you mig ght want to raise an event to o warn an ord dering system that you are running out o of beans. you need to do se the delega ate The first thing y o is to define a delegate. To define a delegate, you us key yword. A dele egate includes s two parameters: The first parameter is the e object that r raised the eve entin this ca ase, a Coffee i instance. gumentsin o other words, a any other info ormation that t you want The second parameter is the event arg to provide t to consumers. This must be e an instance of the EventA Args class, or an instance o of a class that derives s from EventA Args.

Ne ext, you need to define the event. To def fine an event, you use the event e keywor rd. You preced de the delegate you want to assoc name of your ev vent with the name of the d ciate with you ur event. The following ex xample shows s how to defin ne delegates and a events:

Programming in Visual C# 3-33

Defining a Delegate and an Event


public struct Coffee { public EventArgs e; public delegate void OutOfBeansHandler(Coffee coffee, EventArgs args); public event OutOfBeansHandler OutOfBeans; }

In this example, you define an event named OutOfBeans. You associate a delegate named OutOfBeansHandler with your event. The OutOfBeansHandler delegate takes two parameters, an instance of Coffee that will represent the object that raised the event and an instance of EventArgs that could be used to provide more information about the event.

3-34

Develop ping the Code for a Graphical Applicatio on

Ra aising Eve ents

Aft ter you have defined d an ev vent and a delegate, you ca an write code that raises the e event when certain conditions are met. m When yo ou raise the ev vent, the deleg gate associate ed with your e event will invo oke any eve ent handler m methods that have h subscrib bed to your ev vent. To o raise an even nt, you need t to do two thin ngs: 1. 2. Check whet ther the event t is null. The event e will be n null if no code e is currently s subscribing to o it. Invoke the event and pro ovide argume ents to the del legate.

fee struct inclu udes a method named MakeCoffee. Eve ery time you call c the For example, suppose a Coff akeCoffee method, the me ethod reduces the stock lev vel of the Cof ffee instance. If the stock le evel drops Ma be elow a certain point, the Ma akeCoffee method will rais se an OutOfB Beans event. The following ex xample shows s how to raise e an event: aising an Even nt Ra
p public struct t Coffee { // Declare e the event and the delegate. public Eve entArgs e = null; public del legate void OutOfBeansH Handler(Coffe ee coffee, E EventArgs ar rgs); public eve ent OutOfBea ansHandler O OutOfBeans; int curren ntStockLevel l; int minimu umStockLevel l; public voi id MakeCoffe ee() { // Decrement the s stock level. current tStockLevel--; // If t the stock le evel drops b below the min nimum, raise e the event. if (currentStockLe evel < minim mumStockLevel l) { // C Check whethe er the event t is null. if (OutOfBeans != null) { / // Raise the e event. O OutOfBeans(t this, e); } } }

Programming in Visual C# 3-35

To raise the event, you use a similar syntax to calling a method. You provide arguments to match the parameters required by the delegate. The first argument is the object that raised the event. Note how the this keyword is used to indicate the current Coffee instance. The second parameter is the EventArgs instance, which can be null if you do not need to provide any other information to subscribers.

3-36

Develop ping the Code for a Graphical Applicatio on

Su ubscribing g to Event ts

If y you want to h handle an event in client co ode, you need to do two things: Create a me ethod with a signature s that t matches the e delegate for the event. Use the add dition assignm ment operator r (+=) to attac ch your event handler meth hod to the eve ent.

ave created an n instance of t the Coffee str ruct named co offee1. In you ur For example, suppose you ha ventory class, you want to subscribe to the OutOfBe eans that may y be raised by coffee1. Inv e previous top pic shows how w the Coffee s struct, the OutOfBeans eve ent, and the Note: The Ou utOfBeansHa andler delega ate are defined d. The following ex xample shows s how to subs scribe to an ev vent: ubscribing to an Event Su
p public class Inventory { public void d HandleOutO OfBeans(Coff fee sender, E EventArgs ar rgs) { string coffeeBean = sender.Be ean; // Reorder the cof ffee bean. } public voi id Subscribe eToEvent() { coffee1 1.OutOfBeans s += HandleO OutOfBeans; } }

In this example, the signature e of the Hand dleOutOfBean ns method matches the de elegate for the e Ou utOfBeans ev vent. When yo ou call the Sub bscribeToEve ent method, t the HandleOu utOfBeans m method is added to the list of subscribe ers for the Out tOfBeans eve ent on the cof ffee1 object. o unsubscribe from an even nt, you use the e subtraction assignment o operator (-=) t to remove you ur event To handler method d from the eve ent. xample shows s how to unsu ubscribe from an event: The following ex

Programming in Visual C# 3-37

Unsubscribing from an Event


public void UnsubscribeFromEvent() { coffee1.OutOfBeans -= HandleOutOfBeans; }

3-38

Develop ping the Code for a Graphical Applicatio on

Demonstration: Working with h Events in n XAML

Vis sual Studio pr rovides tools t that make it e easy to work w with events in WPF applicat tions. In this de emonstration, you will learn n how to subsc cribe to event ts raised by W WPF controls.

De emonstration Steps
1. 2. 3. Start the MSL-TMG1 virtual machine if it is not already running. 0483A-SEA-DE EV11-03 virtual machine. Start the 20 Log on to W Windows 8 as Student with h the password Pa$$w0rd. Note: If necessary, click k Switch User r to display th he list of users s. 4. 5. 6. 7. 8. 9. he Windows 8 Start window w. Switch to th Click Visual Studio 2012 2. udio, on the F File menu, point to Open, and a then click k Project/Solution. In Visual Stu In the Open n Project dial log box, brow wse to the E:\D Democode\Starter folder, click EventsAnd dXAML.sln, an nd then click Open O . In Solution Explorer, expand EventsAn ndXAML, and d then double e-click MainW Window.xaml l. Notice that the window i includes a but tton named b btnGetTime a and a label na amed lblShow wTime.

0. In the Desig gn window, click the butto on to select it. 10 perties window w, ensure that btnGetTime e is selected, a and then click k Events. 11. In the Prop Note: The e Events butto on is marked with a lightning icon. ies window no ow displays a list of the eve ents to which you can subscribe. 12. Notice that the Properti perties window w, double-clic ck inside the C Click text box x. 13. In the Prop

Programming in Visual C# 3-39

14. Notice that Visual Studio creates an event handler method for you and switches to the code behind page. 15. In the btnGetTime_Click method, add the following code:
lblShowTime.Content = DateTime.Now.ToLongTimeString();

16. In Solution Explorer, expand MainWindow.xaml, expand MainWindow.xaml.cs, and then doubleclick MainWindow. 17. Switch back to the MainWindow.xaml window. 18. In the Button element, note that the designer has added the following attribute:
Click="btnGetTime_Click"

This attribute subscribes the btnGetTime_Click method to the Click event. 19. In Solution Explorer, expand obj, expand Debug, and then double-click MainWindow.g.i.cs. 20. Near the bottom of the file, notice that Visual Studio has added the following line of code:
this.btnGetTime.Click += new System.Windows.RoutedEventHandler(this.btnGetTime_Click);

This demonstrates that Visual Studio parses the XAML to create the code that subscribes your event handler method to the Click event of the button. 21. On the File menu, click Close. 22. On the Debug menu, click Start Without Debugging. 23. Click What's the time? button several times. 24. Notice that the label displays the current time. 25. Close the application, close the solution, and then close Visual Studio.

3-40

Develop ping the Code for a Graphical Applicatio on

Demonstration: Writing Code e for the G Grades Pro ototype A Application n Lab

In this demonstration, you wi ill learn about t the tasks tha at you will per rform in the la ab for this mo odule.

Programming in i Visual C#

3-41 1

Lab: Writing g the C Code for the Grades P Prototy ype lication n Appl

S Scenario
The School of T f Fine Arts has s decided that t they want to o extend their basic class en nrollment app plication to e enable teache ers to record t the grades tha at students in their class ha ave achieved f for each subje ect, and to a allow students to view their own grades. . This function nality necessit tates impleme enting applica ation log on f functionality t to authenticat te the user an nd to determin ne whether th he user is a tea acher or a student. You decide to Y o start by deve eloping parts of a prototyp pe application to test proof f of concept and to obtain c client feedbac ck before emb barking on the e final applica ation. The pro ototype applic cation will use basic WPF v views rather than separate forms for the e user interface. These views have already y been design ned and you m must add the code to navig gate among them. You also decid Y de to begin by b storing the user and grad de information in basic stru ucts, and to us se a dummy d data source in n the application to test your log on func ctionality.

O Objectives
A After complet ting this lab, you y will be able to: Navigate among views s. Create an nd use collecti ions of structs s. Handle ev vents.

E Estimated Tim me: 60 minutes Virtual Machine: 20483 3A-SEA-DEV11-03, MSL-TM MG1 User Nam me: Student Password d: Pa$$w0rd

3-42

Developing the Code for a Graphical Application

Exercise 1: Adding navigation logic to the Grades Prototype Application


Scenario
In this exercise, you will add navigation logic to the Grades Prototype application. First, you will examine the window and views in the application so that you are familiar with the existing structure of the application. You will define a public event handler named LogonSuccess that will be raised when a user successfully logs on to the application. You will add dummy code to the Logon_Click event handler to store the username and role of the logged on user and raise the LogonSuccess event. Then you will add markup to the LogonPage XAML code to connect the Logon button to the Logon_Click event handler. Next, you will add code to the GotoLogon method to display the logon view and to hide the other views. You will implement the Logon_Success method to handle a successful log on by displaying the logged on views, and then you will add markup to the MainWindow XAML code to connect the LogonSuccess event to the Logon_Success method. You will add code to the MainWindow to determine whether the user is a teacher or a student, display their name in the application, and display either the StudentsPage view for teachers or the StudentProfile view for students. You will then add code to the StudentsPage view that catches a student name being clicked and raises the StudentSelected event for that student and displays their student profile. Finally, you will run the application and verify that the appropriate views are displayed for students and teachers upon a successful log on. The main tasks for this exercise are as follows: 1. Examine the window and views in the application 2. Define the LogonSuccess event and add dummy code for the Logon_Click event 3. Add code to display the Log On view 4. Add code to determine the type of user 5. Handle the Student_Click event 6. Build and test the application

X Task 1: Examine the window and views in the application


1. 2. 3. 4. 5. Start the MSL-TMG1 virtual machine if it is not already running. Start the 20483A- SEA-DEV11-03 virtual machine and log on as Student with the password Pa$$w0rd. Start Visual Studio and open the GradesPrototype.sln solution from the E:\Labfiles\Starter\Exercise 1 folder. Build the solution. Review MainWindow.xaml, which is the main window for the application and will host the following views: LogonPage.xaml StudentProfile.xaml StudentsPage.xaml

Programming in Visual C# 3-43

6.

In the Views folder, review the LogonPage.xaml. Notice that this view contains text boxes for the username and password, a check box to identify the user as a teacher, and a button to log on to the application. In the Views folder, review the StudentProfile.xaml. Notice that this view contains a Report Card that currently displays a list of dummy grades. The view also contains a Back button and a blank space that will display the students name. This view is displayed when a student logs on or when a teacher views a students profile. In the View folder, review the StudentsPage.xaml. Notice that this view contains the list of students in a particular class. This view is displayed when a teacher logs on. A teacher can click a student and the Students Profile view will be displayed, containing the selected students data.

7.

8.

X Task 2: Define the LogonSuccess event and add dummy code for the Logon_Click event
1. 2. 3. In the LogonPage.xaml.cs class, in the Event Members region, define a public event handler named LogonSuccess. In the Logon Validation region, add an event handler for the Logon_Click event, which takes an object parameter named sender and a RoutedEventArgs parameter named e. In the Logon_Click event handler, add code to do the following: a. b. c. d. e. Save the username and role that the user specified on the form in the relevant properties of the SessionContext object. If the user is a student, set the CurrentStudent property of the SessionContext object to the string Eric Gruber. Raise the LogonSuccess event. In the LogonPage.xaml XAML editor, locate the definition of the Log on button. Modify the definition to call the Logon_Click method when the button is clicked.

X Task 3: Add code to display the Log On view


1. 2. In the MainWindow.xaml.cs code, locate the GotoLogon method, and then add code to display the logonPage view and to hide the studentsPage and studentProfile views. In the Event Handlers region, add code to the Logon_Success method to handle a successful log on. This method should take an object parameter named sender and an EventArgs parameter named e. The method should update the display and show the data for the logged on user. In the MainWindow.xaml XAML editor, locate the definition of the LogonPage page. Modify the definition to call the Logon_Success method for the LogonSuccess event.

3. 4.

X Task 4: Add code to determine the type of user


1. In the MainWindow.xaml.cs file, in the Refresh method, add code to determine the type of user, display Welcome <username> in the txtName box, and then call either the GotoStudentProfile method (for students) or GotoStudentsPage method (for teachers) to display the appropriate view. In the GotoStudentProfile method, add code to hide the studentsPage view, and then to display and refresh the studentProfile view. In the GotoStudentsPage method, add code to hide the studentProfile view, and then add code to display and refresh the studentsPage view. In the StudentProfile.xaml.cs file, in the Refresh method, add code to:

2. 3. 4.

3-44

Developing the Code for a Graphical Application

a.

Parse the student name into the first name and last name by using a regular expression.

Note: You can use the following code to parse the name: Match matchNames = Regex.Match(SessionContext.CurrentStudent, @"([^ ]+) ([^ ]+)"); b. 5. If a name is successfully parsed, display the first name and last name of the student in the appropriate boxes.

If the user is a student, hide the btnBack button, or if the user is a teacher, display the btnBack button.

X Task 5: Handle the Student_Click event


1. 2. In the StudentsPage.xaml.cs file, in the StudentsPage class, locate the Student_Click method. Add code to this method to identify which student was clicked by using the Tag property of the button, and then raise the StudentSelected event, passing the student name as the second parameter. In the MainWindow.xaml.cs file, in the studentsPage_StudentSelected method, add code to set the CurrentStudent property of the SessionContext object to the student who was clicked by using the Child property of the e argument. Call the GotoStudentProfile method. In the MainWindow.xaml XAML editor, locate the definition of the StudentsPage page. Modify the definition to call the studentsPage_StudentSelected method for the StudentSelected event.

3.

4. 5. 6.

X Task 6: Build and test the application


1. 2. 3. 4. Build the solution and resolve any compilation errors. Run the application. Log on as the teacher, vallee with a password of password. Verify that the application displays the StudentPage view. The Students page should look like this:

Programming in Visual C# 3-45

FIGURE 3.1: THE STUDENTS PAGE 5. Click Kevin Liu and verify that the application displays the StudentProfile view. The Student Profile page should look like this:

FIGURE 3.2: THE STUDENT PROFILE PAGE 6. 7. 8. 9. Log off the application. Log on as the student, grubere, with a password of password. Verify that the application displays the student profile page for Eric Gruber. Close the application and then close the solution.

Results: After completing this exercise, you should have updated the Grades Prototype application to respond to user events and move among the application views appropriately.

3-46

Developing the Code for a Graphical Application

Exercise 2: Creating Data Types to Store User and Grade Information


Scenario
In this exercise, you will define basic structs that will hold the teacher, student, and grade information for the application. You will then add a unit test project to the solution to test the creation and use of the structs. You will run these tests and verify that the structs function as expected. The main tasks for this exercise are as follows: 1. Define basic structs for holding Grade, Student, and Teacher information 2. Add unit tests to create and use the collections of structs

X Task 1: Define basic structs for holding Grade, Student, and Teacher information
1. 2. 3. 4. 5. Open the GradesPrototype solution from the E:\Labfiles\Starter\Exercise 2 folder. In the Data folder, open Grade.cs. In the GradesPrototype.Data namespace, create a struct named Grade that contains the following fields: StudentID as an integer AssessmentDate as a string Assessment as a string Comments as a string In the GradesPrototype.Data namespace, create a struct named Student that contains the following fields: StudentID as an integer UserName as a string Password as a string TeacherID as an integer FirstName as a string LastName as a string In the GradesPrototype.Data namespace, create a struct named Teacher that contains the following fields: TeacherID as an integer UserName as a string Password as a string FirstName as a string LastName as a string Class as a string

X Task 2: Add unit tests to create and use the collections of structs
1. Add a Unit Test Project called GradesTest to the solution and reference the GradesPrototype project from it.

Programming in Visual C# 3-47

2. 3. 4.

In Solution Explorer, rename the UnitTest1.cs file as GradesUnitTests.cs. Add a using directive to the GradesUnitTests file to bring the GradesPrototype.Data namespace into scope. Define the following tests and support methods: StudentTest test method: To create a new student by using the following information, and then verify that it is created correctly.

Field FirstName LastName UserName Password

Value Eric Gruber grubere password

TeacherTest test method: To create a new teacher by using the following information, and then verify that it is created correctly. Field FirstName LastName UserName Password Class Value Esther Valle vallee password 3A

createGrade method: Takes an assessment, a subject, and a comments arguments, creates a new Grade object from them and the current date, and returns the Grade object. GradeTest test method: To create a new grade by passing the following information to the createGrade method, and then verify that it is created correctly. Argument assessment subject comments Value B+ Math Good

GradeCollectionTest test method: To create a collection of new grades by passing the following sets of grade information to the createGrade method, and then verify that one of the collection items is created correctly. assessment subject comments

3-48

Developing the Code for a Graphical Application

assessment B+ ACD5. 6. 7.

subject Math English Geography History

comments Good Very Good Could do better Very poor

Build the solution and resolve any compilation errors. Run all tests and verify that they all pass. Close Test Explorer and then close the solution.

Results: After completing this exercise, the application will contain structs for the teacher, student, and grade types.

Programming in Visual C# 3-49

Exercise 3: Displaying User and Grade Information


Scenario
In this exercise, you will first examine the dummy data source that the application uses to populate the collections in this exercise. You will define a public event handler named LogonFailed that will be raised when a user fails to log on successfully. You will add code to the Logon_Click event handler to validate the username and password entered by the user against the Users collection in the MainWindow window. If the user is a teacher or a student, you will store their details in the global context and then raise the LogonSuccess event, but if the user is not validated, you will raise the LogonFailed event. You will handle log on failure in the Logon_Failed method to display a message to the user and then you will add markup to the MainWindow XAML code to connect the LogonFailed event to the Logon_Failed method. You will add code to the StudentsPage view to display students for the current teacher, and to display the details for a student when the user clicks their name. You will then use data binding to display the details and grades for the current student in the StudentProfile view, and to display only the Back button if the user is a teacher. Finally, you will run the application and verify that only valid users can log on and that valid users can see only data appropriate to their role. The main tasks for this exercise are as follows: 1. Examine the dummy data source used to populate the collections 2. Add the LogonFailed event 3. Add the Logon_Failed event handler 4. Display the students for the current teacher 5. Set the DataContext for the page 6. Build and test the application

X Task 1: Examine the dummy data source used to populate the collections
1. 2. 3. 4. 5. Open the GradesPrototype solution from the E:\Labfiles\Starter\Exercise 3 folder. In the Data folder, in the DataSource.cs file, expand the Sample Data region. Note how the Teachers ArrayList is populated with Teacher data, each containing TeacherID, UserName, Password, FirstName, LastName, and Class fields. Note how the Students ArrayList is populated with Student data, each containing a StudentID, UserName, Password, TeacherID, FirstName, and LastName fields. Note how the Grades ArrayList is populated with Grade data, each containing a StudentID, AssessmentDate, SubjectName, Assessment, and Comments fields.

X Task 2: Add the LogonFailed event


1. 2. In the LogonPage.xaml.cs file, in the Event Members region, define a public event handler named LogonFailed. In the Logon_Click event, add code to do the following: a. Determine whether the user is a teacher by using a LINQ query to retrieve teachers with the same user name and password as the current user. If the LINQ query returns a result, then the user is a teacher.

3-50

Developing the Code for a Graphical Application

b.

If the user is a teacher, set the UserID, UserRole, UserName, and CurrentTeacher properties of the SessionContext object to the appropriate fields from the data source, and then raise the LogonSuccess event. If the user is not a teacher, determine whether the user is a student by using a LINQ query to retrieve students with the same user name and password as the current user. If the user is a student, set the UserID, UserRole, UserName, and CurrentStudent properties of the SessionContext object to the appropriate fields from the data source, and then raise the LogonSuccess event. If the credentials do not match any teachers or students, raise the LogonFailed event.

c. d.

e.

X Task 3: Add the Logon_Failed event handler


1. In the MainWindow.xaml.cs class, in the Event Handlers region, add an event handler for the Logon_Failed event that takes an object parameter named sender and an EventArgs parameter named e. In the Logon_Failed event handler, add code to display an error message to the user. In the MainWindow.xaml XAML editor, locate the definition of the LogonPage page. Modify the definition to call the Logon_Failed method for the LogonFailed event. In the MainWindow.xaml.cs code, locate the Refresh method. In the case statement for a student, add code to display the student name in txtName text box at the top of the page. In the case statement for a teacher, add code to display the teacher name in the banner at the top of the page.

2. 3. 4. 5. 6. 7.

X Task 4: Display the students for the current teacher


1. In StudentsPage.xaml XAML editor, locate the ItemsControl named list and note how data binding is used to display the name of each student.

Note: DataBinding is also used to retrieve the StudentID of a student. This binding is used when a user clicks on a Student on the Student Page list to identify which students data to display in the Student Profile page. 2. In the StudentsPage.xaml.cs code, locate the Refresh method, and then add code to do the following: a. b. c. 3. Find all the students for the current teacher and store them in a new ArrayList object. Bind the collection to the ItemsSource property of the list control. Display the class name.

Locate the Student_Click event and then add code to do the following: a. b. c. d. Identify which student was clicked by using the Tag property of the button. Find the details of that student by examining the DataContext of the button. Raise the StudentSelected event, passing the student as the second parameter. In the StudentsPage_StudentSelected event handler, add code to set the CurrentStudent property of the SessionContext object to the student passed to the event by using the Child property of the e argument.

Programming in Visual C# 3-51

X Task 5: Set the DataContext for the page


1. In the StudentProfile.xaml.cs file, in the Refresh method, add code to display the details of the current student in the studentName StackPanel object and to display the Back button only if the user is a teacher. In the StudentProfile.xaml XAML editor, locate the definition of the firstName text block. Modify the definition to bind the Text property to the FirstName field. Locate the definition of the lastName text block. Modify the definition to bind the Text property to the LastName field. In the StudentProfile.xaml.cs file, at the end of the Refresh method, add code to iterate the grades for the current student in DataSource.Grades list and then display them in the studentGrades control by using data binding.

2. 3. 4. 5. 6.

X Task 6: Build and test the application


1. 2. 3. 4. 5. 6. 7. Build the solution and resolve any compilation errors. Run the application. Log on as parkerd with a password of password and verify that the Logon Failed message box appears. Log on as vallee with a password of password and verify that the Students page appears. Click Kevin Liu, verify that the Student Profile page appears, and then log off. Log on as grubere with a password of password and verify that the Student Profile page appears. Close the application and then close the solution.

Results: After completing this exercise, only valid users will be able to log on to the application and they will see only data appropriate to their role.

3-52

Develop ping the Code for a Graphical Applicatio on

Modu ule Revi iew and d Takea aways

M Module Revie ew
In this module, y you have lear rned how to im mplement stru ucts and enum ms, organize d data into colle ections, and wo ork with event ts and delegates. Test Your Know wledge Q Question Y You want to c create a string g property na amed Country yOfOrigin. Yo ou want to be e able to re ead the property value fro om any code, but you shou uld only be able to write t to the p property from m within the c containing str ruct. How sho ould you decl lare the prope erty? S Select the cor rrect answer. public c string CountryOfOrigin { g get; set; } public c string CountryOfOrigin { g get; } public c string CountryOfOrigin { s set; } public c string CountryOfOrigin { g get; private se et; } private e string CountryOfOrigin { get; set; } Test Your Know wledge Q Question Y You want to c create a collec ction to store e coffee recipe es. You must be able to re etrieve e each coffee re ecipe by prov viding the nam me of the cof ffee. Both the e name of the e coffee a and the coffee e recipe will b be stored as s strings. You also need to b be able to retr rieve c coffee recipes s by providing g an integer i index. Which collection cla ass should yo ou use?

Programming in Visual C# 3-53

Question Select the correct answer. ArrayList Hashtable SortedList NameValueCollection StringDictionary Test Your Knowledge Question You are creating a method to handle an event named OutOfBeans. The delegate for the event is as follows: public delegate void OutOfBeansHandler(Coffee coffee, EventArgs args); Which of the following methods should you use to subscribe to the event? Select the correct answer. public void HandleOutOfBeans(delegate OutOfBeansHandler) { } public void HandleOutOfBeans(Coffee c, EventArgs e) { } public Coffee HandleOutOfBeans(EventArgs e) public Coffee HandleOutOfBeans(Coffee coffee, EventArgs args) public void HandleOutOfBeans(Coffee c, EventArgs e)

4-1

Module 4
Creating Classes and Implementing Type-Safe Collections
Contents:
Module Overview Lesson 1: Creating Classes Lesson 2: Defining and Implementing Interfaces Lesson 3: Implementing Type-Safe Collections Lab: Adding Data Validation and Type-Safety to the Application Module Review and Takeaways 4-2 4-3 4-18 4-31 4-49 4-61

4-2

Creating Classes and Implem menting Type-Safe Collections C

Modu ule Ove erview

Cla asses enable y you to create your own cus stom, self-con ntained, and re eusable types. Interfaces en nable you to define a set o of inputs and outputs that c classes must implement in order to ensu ure compatibility with consumers of th he classes. In t this module, you y will learn how to use in nterfaces and classes to def fine and cre eate your own n custom, reus sable types. Y You will also le earn how to cr reate and use e enumerable, type-safe collections of an ny type.

Ob bjectives
Aft ter completing this module e, you will be able to: asses. Create and instantiate cla Create and instantiate interfaces. Use generic cs to create ty ype-safe collec ctions.

Programming g in Visual C#

4-3 3

Lesson 1

Creat ting Cla asses

In Visual C#, y I you can define e your own cu ustom types by b creating cla asses. As a pro ogramming co onstruct, the c class is central to object-or riented progra amming in Vis sual C#. It ena ables you to e encapsulate th he behaviors a character and ristics of any lo ogical entity in a reusable a and extensible e way. I this lesson, you will learn In n how to creat te, use, and te est classes in y your own app plications.

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Create cla asses. Create ob bjects by insta antiating class ses. Use const tructors to set t values or to run logic whe en classes are instantiated. Explain th he difference between reference types and value type es. Create sta atic classes an nd members. Describe the high-leve el process for t testing class functionality. f

4-4

Creating Classes and Implem menting Type-Safe Collections C

Cr reating Classes and Members

In Visual C#, a c class is a programming construct that yo ou can use to d define your own custom ty ypes. When you create a class, you are eff fectively creat ting a blueprint for the typ pe. The class defines the beh haviors and characteristics, o or class memb bers, which ar re shared by a all instances of f the class. Yo ou represent th hese be ehaviors and c characteristics by defining m methods, field ds, properties, and events w within your cla ass. For example, suppose you cre eate a class na amed DrinksMachine. You u would use fields and prop perties to de efine the chara acteristics of a drinks machine, such as th he make, mod del, age, and service s interva al of the ma achine. You w would create m methods to represent the th hings that a drinks machine e can do, such h as make an espresso or m make a cappu uccino. Finally, , you would d define events to t represent a actions that m might req quire your att tention, such a as replacing c coffee beans w when the mac chine has run o out of coffee beans.

De eclaring a Class C
Yo ou use the clas ss keyword to o declare a cla ass, as shown in the following example: De eclaring a Cla ass
p public class DrinksMachi ine { // Methods s, fields, p properties, and events g go here. }

The class keywo ord is precede ed by an acces ss modifier, su uch as public in the above example, which specifies fro om where you u can use the t type. You can n use the following access modifiers m in yo our class decla arations: A Access modifier p public i internal Description The type is available to c code running in any assemb bly that refere ences the assembly in n which the cla ass is containe ed. The type is available to a any code within the same assembly, but not available to o code in anot ther assembly y. This is the default value if f you do not specify an access mo odifier. The type is only available e to code with hin the class th hat contains it. You can

p private

Programming in Visual C# 4-5

Access modifier

Description only use the private access modifier with nested classes.

Adding Members to a Class


Within your class, you can add methods, fields, properties, and events to define the behaviors and characteristics of your type, as shown in the following example: Defining Class Members
public class DrinksMachine { // The following statements are properties with implicit private fields. public int Age { get; set; } public string Make { get; set; } public string Model { get; set; } // The following statements are methods. public void MakeCappuccino() { // Method logic goes here. } public void MakeEspresso() { // Method logic goes here. } } // The following statement defines an event. The delegate definition is not shown. public event OutOfBeansHandler OutOfBeans;

4-6

Creating Classes and Implem menting Type-Safe Collections C

In nstantiatin ng Classes

A class c is just a blueprint b for a type. To use e the behavior rs and charact teristics that y you define wit thin a class, you need to cre eate instances of the class. A An instance of f a class is call led an object. o create a new w instance of a class, you us se the new keyword, as sho own in the foll lowing examp ple: To Ins stantiating a Class
D DrinksMachine e dm = new D DrinksMachin ne();

Wh hen you instantiate a class in this way, yo ou are actuall ly doing two t things: eating a new object o in mem mory based on the DrinksM Machine type. You are cre You are cre eating an objec ct reference named dm tha at refers to the e new Drinks sMachine object.

hen you creat te your object t reference, instead of expli icitly specifyin ng the Drinks sMachine type, you can Wh allo ow the compiler to deduce e the type of t the object at compile c time. . This is known n as type infer rence. To use e type inferen nce, you create your object reference by using the var r keyword, as shown in the e following exa ample: Ins stantiating a Class by Using Type Infe erence
v var dm = new DrinksMachi ine();

In this case, the compiler doe es not know in n advance the e type of the d dm variable. W When the dm m variable is initialized as a re eference to a DrinksMachine object, th he compiler de educes that th he type of dm m is Dr inference in this way cause rinksMachine e. Using type i es no change i in how your a application run ns; it is sim mply a shortcu ut for you to a avoid typing t the class name e twice. In som me circumstan nces, type infe erence can ma ake your code e easier to rea ad, while in other circumsta ances it may m make your cod de more confu using. As a ge eneral rule, consider using t type inference e when the type of variable e is absolutely y clear. Aft ter you have instantiated i y your object, yo ou can use any of the mem mbersmetho ods, fields, pro operties, and eventstha at you defined d within the c class, as shown n in the follow wing example: :

Programming in Visual C# 4-7

Using Object Members


var dm = new DrinksMachine(); dm.Make = "Fourth Coffee"; dm.Model = "Beancrusher 3000"; dm.Age = 2; dm.MakeEspresso();

This approach to calling members on an instance variable is known as dot notation. You type the variable name, followed by a period, followed by the member name. The IntelliSense feature in Visual Studio will prompt you with member names when you type a period after a variable.

4-8

Creating Classes and Implem menting Type-Safe Collections C

Us sing Cons structors

In the previous topics, you might m have not ticed that the syntax for ins stantiating a c classfor example, new Dr rinksMachine e()looks sim milar to the syn ntax for callin ng a method. This T is becaus se when you in nstantiate a cla ass, you are ac ctually calling a special met thod called a constructor. A constructor is a method in n the class tha at has the sam me name as th he class. Co onstructors are e often used t to specify initi ial or default v values for dat ta members w within the new w object, as sho own by the fo ollowing exam mple: Ad dding a Cons structor
p public class DrinksMachi ine { public int t Age { get; ; set; } public Dri inksMachine( () { Age = 0 0; } }

A constructor c th hat takes no p parameters is known as the default const tructor. This co onstructor is c called wh henever some eone instantiat tes your class without prov viding any arg guments. If you do not inclu ude a constructor in y your class, the Visual C# com mpiler will aut tomatically ad dd an empty public p default t constructor to your y compiled d class. f your class to o be able to sp pecify initial v values for data a members In many cases, it is useful for consumers of wh hen the class is instantiated d. For example e, when someo one creates a new instance e of DrinksMa achine, it mi ight be useful if they can sp pecify the make and model of the machine at the sam me time. Your class can inc clude multiple e constructors s with differen nt signatures t that enable co onsumers to provide p differe ent combinations of information when they in nstantiate your class. xample shows s how to add multiple cons structors to a class: The following ex

Programming in Visual C# 4-9

Adding Multiple Constructors


public class DrinksMachine { public int Age { get; set; } public string Make { get; set; } public string Model { get; set; } public DrinksMachine(int age) { this.Age = age; } public DrinksMachine(string make, string model) { this.Make = make; this.Model = model; } public DrinksMachine(int age, string make, string model) { this.Age = age; this.Make = make; this.Model = model; } }

Consumers can use any of the constructors to create instances of your class, depending on the information that is available to them at the time. For example: Calling Constructors
var dm1 = new DrinksMachine(2); var dm2 = new DrinksMachine("Fourth Coffee", "BeanCrusher 3000"); var dm3 = new DrinksMachine(3, "Fourth Coffee", "BeanToaster Turbo");

4-10 Creating g Classes and Imple ementing Type-Safe Collections

Re eference T Types and d Value Ty ypes

No ow that you know how to create c and instantiate classe es, you will lea arn about the e differences between b cla asses and struc cts. A struct s is a valu ue type. This definition d app plies to built-in n struct types, , such as int a and bool, as w well as to str ructs that you define yourse elf. A value ty ype contains it ts data directly y. In other wo ords, when you interact . By contrast, a class wit th a value typ pe, you are int teracting direc ctly with the d data it contain ns in memory. de efines a referen nce type. Whe en you create an object by instantiating a class, you are creating a reference typ pe. The object t itself is store ed in memory, , but you inte eract with the object throug gh an object re eference. All l the object re eference does is point to th he object in memory. Note: Mo ost of the built t-in types in V Visual C#, such h as int, bool, byte, and ch har, are value typ pes. For more information a about built-in n types, see th he Built-In Typ pes Table (C# Reference) page at http://g go.microsoft.c com/fwlink/?LinkID=267800 0. alue types and d reference typ pes behave di ifferently. If yo ou copy a value type from one variable to another, Va you are copying g the data tha at your variabl le contains an nd creating a new n instance of that data in memory. If y you copy an o object reference from one v variable to another, all you are doing is c copying the object o ref ference. You a are not creatin ng a second object o in mem mory. Both var riables will poi int to the sam me object.

Bo oxing and U Unboxing


In some scenario os you may need to convert value types s to reference types, and vic ce versa. For e example, some collection classes will only o accept ref ference types. . This is less lik kely to be an issue with the e advent of ge eneric collectio ons. However, , you still need d to be aware e of the conce ept, because a fundamental concept of Visual C# is that you can treat any type as an object. The process of c converting a v value type to a reference ty ype is called b boxing. To box x a variable, yo ou assign it to an object refe erence:

Programming in Visual C# 4-11

Boxing
int i = 100; object o = i;

The boxing process is implicit. When you assign an object reference to a value type, the Visual C# compiler automatically creates an object to wrap the value and stores it in memory. If you copy the object reference, the copy will point to the same object wrapper in memory. The process of converting a reference type to a value type is called unboxing. Unlike the boxing process, to unbox a value type you must explicitly cast the variable back to its original type: Unboxing
int j; j = (int)o;

4-12 Creating g Classes and Imple ementing Type-Safe Collections

Demonstration: Com mparing R Reference Types and d Value Ty ypes

r value and a reference typ In this demonstration, you wi ill create a val lue type to sto ore an integer pe to store an integer value e. You will create a copy of each type, an nd then obser rve what happ pens when you u change the e value of the e copy in each h case.

De emonstration Steps
1. 2. 3. Start the MSL-TMG1 virtual machine if it is not already running. 0483A-SEA-D DEV11-04 virt tual machine. Start the 20 Log on to W Windows 8 as Student with h the password Pa$$w0rd. Note: If necessary, click k Switch User r to display th he list of users s. 4. 5. 6. 7. 8. 9. he Windows 8 Start window w. Switch to th Click Visual Studio 2012 2. udio, on the F File menu, point to New, and then click Project. In Visual Stu In the New w Project dialo og box, in the e Templates li ist, click Visua al C#, and the en in the Project Type list, click Co onsole Applic cation. In the Nam me text box, ty ype ValuesAn ndReferences s In the Location text box x, set the locat tion to E:\Dem mocode, and then click OK K.

0. Within the V ValuesAndRe eferences namespace, add d the following g code: 10


struct MyStruct { public int Content ts; }

c you just added, add th he following c code: 11. Immediately below the code

class MyClass

Programming in Visual C# 4-13

{ public int Contents = 0; }

12. Within the Program class, within the Main method, add the following code:
MyStruct struct1 = new MyStruct(); MyStruct struct2 = struct1; struct2.Contents = 100; MyClass class1 = new MyClass(); MyClass class2 = class1; class2.Contents = 100; Console.WriteLine("Value types: {0}, {1}", struct1.Contents, struct2.Contents); Console.WriteLine("Reference types: {0}, {1}", class1.Contents, class2.Contents);

13. On the Debug menu, click Start without Debugging. The console window shows the following output:
Value types: 0, 100 Reference types: 100, 100

14. Press Enter to close the console window. 15. Close Visual Studio 2012.

4-14 Creating g Classes and Imple ementing Type-Safe Collections

Cr reating St tatic Classe es and Me embers

In some cases, y you may want t to create a class purely to encapsulate some useful f functionality, rather r than to represent an instance of anything. For e example, supp pose you want ted to create a set of methods that convert imperia al weights and d measures to metric weigh hts and measu ures, and vice versa. It would not make sen nse if you had d to instantiate a class in or rder to use the ese methods, because you do not need to store or ret trieve any inst tance-specific c data. In fact, the concept o of an instance e is meaningle ess in this case e. In scenarios like e this, you can n create a stati ic class. A stat tic class is a class that canno ot be instantia ated. To cre eate a static class, you use the t static key yword. Any me embers within n the class mu ust also use th he static key yword, as sho own in the foll lowing examp ple: Sta atic Classes
p public static c class Conv versions { public sta atic double PoundsToKilos(double po ounds) { // Conv vert argumen nt from poun nds to kilograms double kilos = pou unds * 0.453 36; return kilos; } public sta atic double KilosToPoun nds(double ki ilos) { // Conv vert argumen nt from kilo ograms to pou unds double pounds = ki ilos * 2.205 5; return pounds; } }

To o call a method d on a static c class, you call the method o on the class name itself inst tead of on an instance name, as shown n by the follow wing example: alling Method ds on a Static c Class Ca
d double weight tInKilos = 8 80; d double weight tInPounds = Conversions s.KilosToPoun nds(weightIn nKilos);

Programming in Visual C# 4-15

Static Members
Non-static classes can include static members. This is useful when some behaviors and characteristics relate to the instance (instance members), while some behaviors and characteristics relate to the type itself (static members). Methods, fields, properties, and events can all be declared static. Static properties are often used to return data that is common to all instances, or to keep track of how many instances of a class have been created. Static methods are often used to provide utilities that relate to the type in some way, such as comparison functions. To declare a static member you use the static keyword before the return type of the member, as shown by the following example: Static Members in Non-static Classes
public class DrinksMachine { public int Age { get; set; } public string Make { get; set; } public string Model { get; set; } public static int CountDrinksMachines() { // Add method logic here. } }

Regardless of how many instances of your class exist, there is only ever one instance of a static member. You do not need to instantiate the class in order to use static members. You access static members through the class name rather than the instance name, as shown by the following example: Access Static Members
int drinksMachineCount = DrinksMachine.CountDrinksMachines();

4-16 Creating g Classes and Imple ementing Type-Safe Collections

Te esting Classes

Cla asses often represent self-c contained unit ts of functiona ality. In many y cases, you wi ill want to test the fun nctionality of your classes in isolation be efore you integrate them w with other classes in your ap pplications. To o test function nality in isolation, you create a unit test. A unit test pre esents the cod de under test with known inputs, p performs an ac ction on the c code under te est (for examp ple by calling a method), an nd then verifies that the outputs of th he operation a are as expecte ed. In this way y, the unit test t represents a contract tha at your code must m fulfill. Ho owever, when n you change the implemen ntation of a class or metho od, the unit tes st ensures that your code a always returns particular ou utputs in respo onse to particular inputs. For example, co onsider the cas se where you create a simp ple class to rep present a cust tomer. To help you tar rget your mar rketing efforts s, the Custom mer class includ des a GetAge e method that t returns the c current age of the customer r in years: Cla ass Under Te est
p public class Customer { public Dat teTime DateO OfBirth { ge et; set; } public int t GetAge() { TimeSpa an differenc ce = DateTim me.Now.Subtra act(DateOfBi irth); int age eInYears = ( (int)(differ rence.Days / 365.25); // Note e: convertin ng a double to an int ro ounds down t to the neare est whole num mber. return ageInYears; ; } }

In this case, you u might want t to create a un nit test that en nsures the Get tAge method d behaves as e expected. As such, your te est method ne eeds to instant tiate the Cust tomer class, specify a date of birth, and then verify tha at the GetAge e method retu urns the corre ect age in years. Depending g on the unit t test framework you use, your test metho od might look k something like the followi ing:

Programming in Visual C# 4-17

Example Test Method


[TestMethod] public void TestGetAge() { // Arrange. DateTime dob = DateTime.Today; dob.AddDays(7); dob.AddYears(-24); Customer testCust = new Customer(); testCust.DateOfBirth = dob; // The customer's 24th birthday is seven days away, so the age in years should be 23. int expectedAge = 23; // Act. int actualAge = testDog.GetAge(); // Assert. // Fail the test if the actual age and the expected age are different. Assert.IsTrue((actualAge == expectedAge), "Age not calculated correctly"); }

Notice that the unit test method is divided into three conceptual phases: Arrange. In this phase, you create the conditions for the test. You instantiate the class you want to test, and you configure any input values that the test requires. Act. In this phase, you perform the action that you want to test. Assert. In this phase, you verify the results of the action. If the results were not as expected, the test fails.

The Assert.IsTrue method is part of the Microsoft Unit Test Framework that is included in Visual Studio 2012. This particular method throws an exception if the specified condition does not evaluate to true. However, the concepts described here are common to all unit testing frameworks.

4-18 Creating g Classes and Imple ementing Type-Safe Collections

Lesson 2

Defini ing and d Imple ementin ng Inter rfaces

An n interface is a little bit like a class withou ut an impleme entation. It sp pecifies a set o of characterist tics and thout specifyi be ehaviors by de efining signatu ures for metho ods, propertie es, events, and d indexers, wit ing how any of these me embers are im mplemented. W When a class implements an n interface, th he class provid des an implementation n for each mem mber of the in nterface. By im mplementing the interface, , the class is th hereby gu uaranteeing th hat it will prov vide the functionality specif fied by the int terface. In this lesson, yo ou will learn h how to define and impleme ent interfaces. .

Le esson Obje ectives


Aft ter completing this lesson, you will be ab ble to: nterfaces in Vi isual C#. Explain the purpose of in Create inter rfaces. Create class ses that imple ement a single e interface. Create class ses that imple ement multiple interfaces. Implement the ICompar rable interface e. Implement the ICompar rer interface.

Programming in i Visual C#

4-19 9

I Introducin ng Interfa aces

In Visual C#, a I an interface sp pecifies a set of o characteristics and behaviors; it does this by definin ng methods, p properties, ev vents, and inde exers. The inte erface itself does not specif fy how these members are i implemented . Instead, class ses can implem ment the inte erface and pro ovide their ow wn implementa ations of the i interface mem mbers. You can think of an interface as a contract. By implementing g a particular interface, a c class guarante ees to consum mers that it will provide spe ecific functiona ality through specific members, even t though the ac ctual impleme entation is not t part of the c contract. For example, suppose that you want to develop F d a loyalty card sche eme for Fourth Coffee. You might start b creating an by n interface named ILoyalty yCardHolder that defines: A read-o only integer property name ed TotalPoint ts. A method d named Add dPoints that accepts a a decimal argumen nt. A method d named Rese etPoints.

T following example sho The ows an interfac ce that define es one read-only property a and two meth hods: D Defining an Interface I
public inte erface ILoya altyCardHolder { int Tota alPoints { g get; } int AddP Points(decim mal transactionValue); void Res setPoints(); }

Note: P Programming convention d dictates that all interface na ames should b begin with an "I". Notice that th N he methods in n the interface e do not include method bo odies. Similarl ly, the proper rties in the i interface indic cate which accessors to include but do not n provide an ny implement tation details. The interface e s simply states t that any implementing clas ss must includ de and provid de an impleme entation for th he three m members. The e creator of th he implementing class can choose how t the methods a are implemen nted. For e example, any implementation of the AddPoints meth hod will accep pt a decimal argument a (the e cash value o the custom of mer transaction n) and return an integer (th he number of points added d). The class developer

4-20

Creating Classes and Implementing Type-Safe Collections

could implement this method in a variety of ways. For example, an implementation of the AddPoints method could: Calculate the number of points to add by multiplying the transaction value by a fixed amount. Get the number of points to add by calling a service. Calculate the number of points to add by using additional factors, such as the location of the loyalty cardholder.

The following example shows a class that implements the ILoyaltyCardHolder interface: Implementing an Interface
public class Customer : ILoyaltyCardHolder { private int totalPoints; public int TotalPoints { get { return totalPoints; } } public int AddPoints(decimal transactionValue) { int points = Decimal.ToInt32(transactionValue); totalPoints += points; } public void ResetPoints() { totalPoints = 0; } // Other members of the Customer class. }

The details of the implementation do not matter to calling classes. By implementing the ILoyaltyCardHolder interface, the implementing class is indicating to consumers that it will take care of the AddPoints operation. One of the key advantages of interfaces is that they enable you to modularize your code. You can change the way in which your class implements the interface at any point, without having to update any consumer classes that rely on an interface implementation.

Programming in i Visual C#

4-21 1

D Defining I Interfaces s

T syntax for The r defining an interface is sim milar to the sy yntax for defining a class. Y use the in You nterface keyw word to declare an interface, as shown b by the followin ng example: D Declaring an Interface
public inte erface IBeve erage { // Method ds, properties, events, and indexer rs go here. }

Similar to a class declaratio S on, an interfac ce declaration can include a an access mod difier. You can n use the f following acce ess modifiers in your interfa ace declaratio ons: Access modifier public internal Description The interfa ace is availabl le to code run nning in any a assembly. The interfa ace is availabl le to any code e within the sa ame assembly y, but not available t to code in ano other assembl ly. This is the d default value if you do not t specify an access modif fier.

A Adding Inte erface Mem mbers


An interface defines A d the sig gnature of me embers but do oes not includ de any implem mentation deta ails. I Interfaces can n include meth hods, properties, events, an nd indexers: To define e a method, yo ou specify the e name of the e method, the return type, a and any param meters:
int Get tServingTemperature(bool l includesMilk);

To define e a property, y you specify the name of the e property, th he type of the property, and d the property accessors:
bool Is sFairTrade { get; set; }

To define e an event, you use the eve ent keyword, followed f by th he event hand dler delegate, followed by the name e of the event:

4-22

Creating Classes and Implementing Type-Safe Collections

event EventHandler OnSoldOut;

To define an indexer, you specify the return type and the accessors:
string this[int index] { get; set; }

Interface members do not include access modifiers. The purpose of the interface is to define the members that an implementing class should expose to consumers, so that all interface members are public. Interfaces cannot include members that relate to the internal functionality of a class, such as fields, constants, operators, and constructors.

Programming in i Visual C#

4-23 3

I Implemen nting Interfaces

To create a cla T ass that imple ements an inte erface, you ad dd a colon followed by the name of the interface to y your class dec claration. T following example sho The ows how to cre eate a class th hat implement ts the IBevera age interface: : D Declaring aC Class that Implements an Interface
public clas ss Coffee : IBeverage { }

Within your class, you must provide an implementatio W on for every m member of the e interface. Yo our class can i include additi ional member rs that are not t defined by t the interface. In fact, most c classes will inc clude a additional me embers, becau use generally t the class exten nds the interfa ace. However r, you cannot o omit any i interface mem mbers from th he implementi ing class. The way you implement the interface memb bers does not m matter, as lon ng as your imp plementations s have the sam me signatures (that is, the same names, t types, return t types, and parameters) as t the member definitions d in t the interface. T following example sho The ows a trivial interface, toget ther with a cla ass that implements the interface: I Implementin ng an Interfac ce
public inte erface IBeve erage { int GetS ServingTempe erature(bool includesMil lk); bool IsF FairTrade { get; set; } } public clas ss Coffee : IBeverage { private int serving gTempWithoutMilk { get; set; } private int serving gTempWithMilk { get; set t; } public i int GetServingTemperature(bool incl ludesMilk) { if(in ncludesMilk) ) { r return servingTempWithMilk; } else {

4-24

Creating Classes and Implementing Type-Safe Collections

return servingTempWithoutMilk; } } public bool IsFairTrade { get; set; } // Other non-interface members go here. }

Interface Polymorphism
As it relates to interfaces, polymorphism states that you can represent an instance of a class as an instance of any interface that the class implements. Interface polymorphism can help to increase the flexibility and modularity of your code. Suppose you have several classes that implement the IBeverage interface, such as Coffee, Tea, Juice, and so on. You can write code that works with any of these classes as instances of IBeverage, without knowing any details of the implementing class. For example, you can build a collection of IBeverage instances without needing to know the details of every class that implements IBeverage. For example, If the Coffee class implements the IBeverage interface, you can represent a new Coffee object as an instance of Coffee or an instance of IBeverage: Representing an Object as an Interface Type
Coffee coffee1 = new Coffee(); IBeverage coffee2 = new Coffee();

You can use an implicit cast to convert to an interface type, because you know that the class must include all the interface members. Casting to an Interface Type
IBeverage beverage = coffee1;

You must use an explicit cast to convert from an interface type to a derived class type, as the class may include members that are not defined in the interface. Casting an Interface Type to a Derived Class Type
Coffee coffee3 = beverage as Coffee; // OR Coffee coffee4 = (Coffee)beverage;

Programming in i Visual C#

4-25 5

I Implemen nting Mult tiple Inter rfaces

In many cases I s, you will wan nt to create classes that imp plement more e than one int terface. For ex xample, you m might want to o: Implemen nt the IDisposable interfac ce to enable the .NET runtime to dispose e of your class s correctly. Implemen nt the IComp parable interfa ace to enable collection cla asses to sort in nstances of yo our class. Implemen nt your own custom c interfa ace to define t the functionality of your cla ass.

To implement T t multiple inte erfaces, you ad dd a comma-separated list t of the interfa aces that you want to i implement to your class de eclaration. You ur class must implement ev very member of every inter rface you add t your class d to declaration. T following example sho The ows how to cre eate a class th hat implement ts multiple int terfaces: D Declaring aC Class that Implements Mu ultiple Interfa aces
public clas ss Coffee: IBeverage, I IInventoryIte em { }

I Implicit and d Explicit Im mplementa ation


When you cre W eate a class that implement ts an interface e, you can cho oose whether to implement t the i interface impl licitly or explic citly. To imple ement an inte erface implicitl ly, you implem ment each interface m member with a signature that matches t the member definition d in th he interface. T To implement t an interface e explicitly, you fully qualify each e member r name so that it is clear tha at the membe er belongs to a particular i interface. T following example sho The ows an explicit t implementat tion of the IBeverage inter rface:

4-26

Creating Classes and Implementing Type-Safe Collections

Implementing an Interface Explicitly


public class Coffee : IBeverage { private int servingTempWithoutMilk { get; set; } private int servingTempWithMilk { get; set; } public int IBeverage.GetServingTemperature(bool includesMilk) { if(includesMilk) { return servingTempWithMilk; } else { return servingTempWithoutMilk; } } public bool IBeverage.IsFairTrade { get; set; } // Other non-interface members. }

In most cases, whether you implement an interface implicitly or explicitly is an aesthetic choice. It does not make a difference in how your class compiles. Some developers prefer explicit interface implementation because doing so can make the code easier to understand. The only scenario in which you must use explicit interface implementation is if you are implementing two interfaces that share a member name. For example, if you implement interfaces named IBeverage and IInventoryItem, and both interfaces declare a Boolean property named IsAvailable, you would need to implement at least one of the IsAvailable members explicitly. In this scenario, the compiler would be unable to resolve the IsAvailable reference without an explicit implementation.

Programming in i Visual C#

4-27 7

I Implemen nting the ICompara able Interf face

The .NET Fram T mework includ des various co ollection classe es that enable e you to sort t the contents o of the c collection. The ese classes, su uch as the Arr rayList class, include a method named S Sort. When yo ou call this m method on an n ArrayList in nstance, the co ollection orde ers its contents. How does the H e ArrayList instance know h how items in the collection n should be or rdered? In the e case of ars fairly straig s simple types, such as intege ers, this appea ghtforward. In ntuitively, thre ee follows two o and two f follows one. H However, supp pose you crea ate a collection n of Coffee o objects. How would w the Arr rayList i instance determine whethe er one coffee is greater or lesser than another coffee? The answer is that the C Coffee class n needs to prov vide the Array yList instance with logic tha at enables it to compare on ne coffee with h a another. To do this, the Co offee class mu ust implement t the ICompar rable interfac ce. T following example sho The ows the IComp parable interf face: T ICompar The rable Interfac ce
public inte erface IComp parable { int Comp pareTo(Objec ct obj); }

As you can se A ee, the IComp parable interfa ace declares a single metho od named Co ompareTo. I Implementatio ons of this me ethod must: Compare the current object o instance with anothe er object of th he same type (the argumen nt). Return an n integer value that indicates whether th he current object instance s should be plac ced before, in n the same position, or a after the passe ed-in object in nstance.

T integer va The alues returned d by the Com mpareTo meth hod are interp preted as follo ows: Less than zero indicate es that the cur rrent object in nstance precedes the suppl lied instance in the sort order. Zero indic cates that the e current object instance oc ccurs at the sa ame position as a the supplie ed instance in the sort o order. More than zero indicat tes that the cu urrent object instance follo ows the supplied instance in n the sort order.

4-28

Creating Classes and Implementing Type-Safe Collections

The following example illustrates what happens if you use the CompareTo method to compare two integers: CompareTo Example
int number1 = 5; int number2 = 100; int result = number1.CompareTo(number2); // The value of result is -1, indicating that number1 should precede number2 in the sort order.

Note: All the built-in value types in the .NET Framework implement the IComparable interface. For more information about the IComparable interface, seethe IComparable Interface page at http://go.microsoft.com/fwlink/?LinkID=267801. When you call the Sort method on an ArrayList instance, the Sort method calls the CompareTo method of the collection members to determine the correct order for the collection. When you implement the IComparable interface in your own classes, you determine the criteria by which objects should be compared. For example, you might decide that coffees should be sorted alphabetically by variety. The following example shows how to implement the IComparable interface: Implementing the IComparable Interface
public class Coffee: IComparable { public double AverageRating { get; set; } public string Variety { get; set; } int IComparable.CompareTo(object obj) { Coffee coffee2 = obj as Coffee; return String.Compare(this.Variety, coffee2.Variety); } }

In this example, because the values we want to compare are strings, we can use the String.Compare method. This method returns -1 if the current string precedes the supplied string in an alphabetical sort order, 0 if the strings are identical, and 1 if the current string follows the supplied string in an alphabetical sort order.

Programming in i Visual C#

4-29 9

I Implemen nting the ICompare er Interfac ce

When you cal W ll the Sort me ethod on an A ArrayList insta ance, the Arra ayList sorts th he collection b based on the rrayList I IComparable e interface imp plementation in the underlying type. For example, if y you sort an Ar c collection of integers, the s sort criteria is defined by th he IComparab ble interface implementatio on in the I Int32 type. Th he creator of t the ArrayList t instance has no control ov ver the criteria a that are use ed to sort the c collection. In some cases I s, developers may m want to s sort instances of your class using alterna ative sort criteria. For e example, supp pose you wan nt to sort a collection of Coffee instances by the value e of the Avera ageRating p property rathe er than the Va ariety proper rty. To sort an ArrayList ins stance by usin ng custom sor rt criteria, you u n need to do tw wo things: 1 1. 2 2. Create a c class that imp plements the I IComparer in nterface to pro ovide your cus stom sort functionality. Call the S Sort method o on the ArrayL List instance, a and pass in an n instance of y your ICompa arer implemen ntation as a parameter.

T following example sho The ows the IComp parer interfac ce: T ICompar The rer Interface
public inte erface IComp parer { int Comp pare(Object x, Object y) }

As you can se A ee, the IComp parer interface e declares a single method named Comp pare. Implem mentations of t method must: this m Compare two objects o of the same ty ype. Return an n integer value that indicates whether th he current object instance s should be plac ced before, in n the same position, or a after the passe ed-in object in nstance.

T following example sho The ows how to im mplement the IComparer in nterface:

4-30

Creating Classes and Implementing Type-Safe Collections

Implementing the IComparer Interface


public class CoffeeRatingComparer : IComparer { public int Compare(Object x, Object y) { Coffee coffee1 = x as Coffee; Coffee coffee2 = y as Coffee; double rating1 = coffee1.AverageRating; double rating2 = coffee2.AverageRating; return rating1.CompareTo(rating2); } }

In the above example, because the values we want to compare are doubles, we can make use of the Double.CompareTo method. This returns -1 if the current double is less than the supplied double, 0 if the current double is equal to the supplied double, and 1 if the current double is greater than the supplied double. It is always better to make use of a built-in comparison function, if one exists, rather than creating your own. The following example shows how to use a custom IComparer implementation: Using an IComparer Implementation
// Create some instances of the Coffee class. Coffee coffee1 = new Coffee(); coffee1.Rating = 4.5; Coffee coffee2 = new Coffee(); coffee2.Rating = 8.1; Coffee coffee3 = new Coffee(); coffee3.Rating = 7.1; // Add the Coffee instances to an ArrayList. ArrayList coffeeList = new ArrayList(); coffeeList.Add(coffee1); coffeeList.Add(coffee2); coffeeList.Add(coffee3); // Sort the ArrayList by average rating. coffeeList.Sort(new CoffeeRatingComparer());

To sort the ArrayList using a custom comparer, you call the Sort method and pass in a new instance of your IComparer implementation as an argument.

Programming in i Visual C#

4-31 1

Lesson 3

Implementi ing Typ pe-Safe Collect tions

Almost every application th A hat you create e will use colle ection classes in one form o or another. In most cases, c collections co ontain a set of objects of the e same type. W When you int teract with a c collection, you u often rely o the collect on tion to provide objects of a specific type. Historically, this created v various challen nges. You had d t create exce to eption handlin ng logic in cas se a collection n contained items of the wr rong type. You also had to b value types in order to box o add them to collection cla asses, and unb box them on retrieval. r Visua al C# r removes many of these cha allenges by us sing generics In this lesson, you will learn I n how to creat te and use ge eneric classes t to create strongly typed co ollections of a type. any

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Describe generics. Identify the advantage es of generic c classes over no on-generic cla asses. Apply con nstraints to ty ype parameter rs. Use gene eric list collections. Use gene eric dictionary collections. Create cu ustom generic c collections. Create en numerable generic collectio ons.

4-32 Creating g Classes and Imple ementing Type-Safe Collections

In ntroducing g Generics s

Ge enerics enable e you to create e and use stro ongly typed co ollections that are type safe e, do not requ uire you to cas st items, and d do not require you to box and unbox va alue types. Ge eneric classes work w by including a type parameter, T, in n the class or interface decla aration. You d do not need to o specify the type of T until you ins stantiate the c class. To create a generic class, you need d to: Add the typ pe parameter T in angle bra ackets after th he class name e. Use the typ pe parameter T in place of t type names in n your class m members.

xample shows s how to creat te a generic c class: The following ex Creating a Gen neric Class
p public class CustomList< <T> { public T t this[int ind dex] { get; set; } public voi id Add(T ite em) { // Meth hod logic go oes here. } public voi id Remove(T item) { // Meth hod logic go oes here. } }

Wh hen you creat te an instance e of your gene eric class, you specify the ty ype you want to supply as a type parameter. For e example, if yo ou want to use e your custom m list to store objects of typ pe Coffee, you u would sup pply Coffee a as the type pa arameter. The following ex xample shows s how to insta antiate a gene eric class:

Programming in Visual C# 4-33

Instantiating a Generic Class


CustomList<Coffee> clc = new CustomList<Coffee>; Coffee coffee1 = new Coffee(); Coffee coffee2 = new Coffee(); clc.Add(coffee1); clc.Add(coffee2); Coffee firstCoffee = clc[0];

When you instantiate a class, every instance of T within the class is effectively replaced with the type parameter you supply. For example, if you instantiate the CustomList class with a type parameter of Coffee: The Add method will only accept an argument of type Coffee. The Remove method will only accept an argument of type Coffee. The indexer will always provide a return value of type Coffee.

4-34 Creating g Classes and Imple ementing Type-Safe Collections

Ad dvantages s of Generics

The use of gene eric classes, pa articularly for collections, of ffers three ma ain advantage es over non-generic ap pproaches: typ pe safety, no casting, c and no boxing and unboxing.

Ty ype Safety
Co onsider an exa ample where y you use an Ar rrayList to sto ore a collectio on of Coffee o objects. You can add ob bjects of any ty ype to an Arr rayList. Suppo ose a developer adds an ob bject of type T Tea to the collection. The code will build w without comp plaint. Howeve er, a runtime e exception will l occur if the Sort S method is called, be ecause the collection is unable to compare objects of different type es. Furthermor re, when you retrieve an ob bject from the collection, yo ou must cast t the object to the t correct type. If you atte empt to cast t the object to the wrong type, an invalid cast runtime exception will occur. The following ex xample shows s the type safe ety limitations s of the Array yList approach: Ty ype Safety Lim mitations for r Non-Generi ic Collections s
v var coffee1 = new Coffee e(); v var coffee2 = new Coffee e(); v var tea1 = ne ew Tea(); v var arrayList t1 = new Arr rayList(); a arrayList1.Ad dd(coffee1); ; a arrayList1.Ad dd(coffee2); ; a arrayList1.Ad dd(tea1); / // The Sort m method throw ws a runtime e exception because b the collection is not homog genous. a arrayList1.So ort(); / // The cast t throws a run ntime except tion because you cannot cast a Tea instance to a Coffee instance. C Coffee coffee e3 = (Coffee e)arrayList1 1[2];

As an alternative e to the Array yList, suppose e you use a ge eneric List<T T> to store a c collection of C Coffee ob bjects. When you y instantiate e the list, you provide a typ pe argument o of Coffee. In t this case, your list is gu uaranteed to b be homogeno ous, because your y code will not build if y you attempt to o add an obje ect of any oth her type. The Sort method will work bec cause your collection is hom mogenous. Fin nally, the inde exer returns ob bjects of type C Coffee, rathe er than System m.Object, so there t is no risk of invalid ca ast exceptions s. The following ex xample shows s an alternativ ve to the Arra ayList approach using the g generic List<T T> class:

Programming in Visual C# 4-35

Type Safety in Generic Collections


var coffee1 = new Coffee(); var coffee2 = new Coffee(); var tea1 = new Tea(); var genericList1 = new List<Coffee>(); genericList1.Add(coffee1); genericList1.Add(coffee2); // This line causes a build error, as the argument is not of type Coffee. genericList1.Add(tea1); // The Sort method will work because the collection is guaranteed to be homogenous. arrayList1.Sort(); // The indexer returns objects of type Coffee, so there is no need to cast the return value. Coffee coffee3 = genericList[1];

No Casting
Casting is a computationally expensive process. When you add items to an ArrayList, your items are implicitly cast to the System.Object type. When you retrieve items from an ArrayList, you must explicitly cast them back to their original type. Using generics to add and retrieve items without casting improves the performance of your application.

No Boxing and Unboxing


If you want to store value types in an ArrayList, the items must be boxed when they are added to the collection and unboxed when they are retrieved. Boxing and unboxing incurs a large computational cost and can significantly slow your applications, especially when you iterate over large collections. By contrast, you can add value types to generic lists without boxing and unboxing the value. The following example shows the difference between generic and non-generic collections with regard to boxing and unboxing: Boxing and Unboxing: Generic vs. Non-Generic Collections
int number1 = 1; var arrayList1 = new ArrayList(); // This statement boxes the Int32 value as a System.Object. arrayList1.Add(number1); // This statement unboxes the Int32 value. int number2 = (int)arrayList1[0]; var genericList1 = new List<Int32>(); //This statement adds an Int32 value without boxing. genericList1.Add(number1); //This statement retrieves the Int32 value without unboxing. int number3 = genericList1[0];

4-36 Creating g Classes and Imple ementing Type-Safe Collections

Co onstrainin ng Generic cs

In some cases, y you may need d to restrict the types that developers d can n supply as ar rguments whe en they ins stantiate your r generic class. The nature o of these const traints will dep pend on the logic you implement in your generic cla ass. For examp ple, if a collect tion class uses s a property named n Averag geRating to sort s the ite ems in a collec ction, you wou uld need to co onstrain the ty ype paramete er to classes th hat include th he Av verageRating g property. Suppose the Av verageRating g property is d defined by the e IBeverage in nterface. To implement this restriction, yo ou would cons strain the type e parameter t to classes that t implement the IBe everage inter rface by using g the where k keyword. The following ex xample shows s how to cons strain a type parameter p to classes c that im mplement a pa articular int terface: Co onstraining T Type Paramet ters by Interf face
p public class CustomList< <T> where T : IBeverage { }

Yo ou can apply the following s six types of co onstraint to ty ype parameters: C Constraint w where T : <na ame of interface> w where T : <na ame of base cl lass> w where T:U w where T : new w() w where T : struct w where T : class s Description Th he type argum ment must be, or implement, the specifie ed interface. Th he type argum ment must be, or derive from m, the specifie ed class. Th he type argum ment must be, or derive from m, the supplie ed type arg gument U. Th he type argum ment must hav ve a public de efault construc ctor. Th he type argum ment must be a value type. Th he type argum ment must be a reference ty ype.

Yo ou can also ap pply multiple c constraints to the same clas ss, as shown by b the followin ng example:

Programming in Visual C# 4-37

Apply Multiple Type Constraints


public class CustomList<T> where T : IBeverage, IComparable<T>, new() { }

4-38 Creating g Classes and Imple ementing Type-Safe Collections

Us sing Gene eric List Co ollections

On ne of the most common an nd important uses u of generics is in collec ction classes. Generic G collections fall int to two broad categories: ge eneric list collections and g generic diction nary collection ns. A generic list stores a collection of obj jects of type T. T

Th he List<T> Class
The List<T> cla ass provides a strongly-type ed alternative e to the Array yList class. Like e the ArrayList class, the Lis st<T> class in ncludes metho ods to: Add an item m. Remove an item. Insert an ite em at a specif fied index. Sort the items in the collection by usin ng the default t comparer or r a specified comparer. e collection. Reorder all or part of the

xample shows s how to use the t List<T> c class. The following ex sing the List< <T> Class Us
s string s1 = "Latte"; s string s2 = "Espresso"; s string s3 = "Americano"; ; s string s4 = "Cappuccino" "; s string s5 = "Mocha"; / // Add the it tems to a st trongly-type ed collection n. v var coffeeBev verages = ne ew List<String>(); c coffeeBeverag ges.Add(s1); ; c coffeeBeverag ges.Add(s2); ; c coffeeBeverag ges.Add(s3); ; c coffeeBeverag ges.Add(s4); ; c coffeeBeverag ges.Add(s5); ; / // Sort the i items using the default t comparer. / // For object ts of type S String, the default comp parer sorts the items a alphabeticall ly. c coffeeBeverag ges.Sort(); / // Write the collection to a console window. f foreach(Strin ng coffeeBev verage in co offeeBeverage es) { Console.WriteLine(cof ffeeBeverage e);

Programming in Visual C# 4-39

} Console.ReadLine ("Press Enter to continue");

Other Generic List Classes


The System.Collections.Generic namespace also includes various generic collections that provide more specialized functionality: The LinkedList<T> class provides a generic collection in which each item is linked to the previous item in the collection and the next item in the collection. Each item in the collection is represented by a LinkedListNode<T> object, which contains a value of type T, a reference to the parent LinkedList<T> instance, a reference to the previous item in the collection, and a reference to the next item in the collection. The Queue<T> class represents a strongly typed first in, last out collection of objects. The Stack<T> class represents a strongly typed last in, last out collection of objects.

4-40 Creating g Classes and Imple ementing Type-Safe Collections

Us sing Gene eric Dictio onary Colle ections

Dic ctionary classe es store collec ctions of key value v pairs. Th he value is the e object you w want to store, and the key y is the object t you use to in ndex and retr rieve the value e. For example e, you might u use a dictiona ary class to sto ore coffee recipes, where th he key is the name n of the co offee and the e value is the r recipe for that t coffee. In the e case of gene eric dictionari ies, both the k key and the va alue are stron ngly typed.

Th he Dictiona ary<TKey, T TValue> Cla ass


The Dictionary<TKey, TValu ue> class provides a gener ral purpose, st trongly typed dictionary cla ass. You can add duplicate va alues to the c collection, but t the keys mus st be unique. The class will throw an Ar rgumentExce eption if you attempt a to ad dd a key that a already exists in the diction nary. The following ex xample shows s how to use the t Dictionar ry<TKey, TVa alue> class: Us sing the Dicti ionary<TKey y, TValue> Class
/ // Create a n new dictiona ary of strin ngs with stri ing keys. v var coffeeCod des = new Di ictionary<St tring, String g>(); / // Add some e entries to t the dictiona ary. c coffeeCodes.A Add("CAL", " "Caf Au Lait"); c coffeeCodes.A Add("CSM", " "Cinnamon Sp pice Mocha"); c coffeeCodes.A Add("ER", "E Espresso Rom mano"); c coffeeCodes.A Add("RM", "R Raspberry Mo ocha"); c coffeeCodes.A Add("IC", "I Iced Coffee"); / // This state ement would result in a an ArgumentEx xception bec cause the ke ey already ex xists. / // coffeeCode es.Add("IC", , "Instant C Coffee"); / // To retriev ve the value e associated d with a key, you can us se the index xer. / // This will throw a Key yNotFoundExc ception if th he key does not exist. C Console.Write eLine("The v value associated with th he key \"CAL L\" is {0}", c coffeeCodes["CAL"]); / // Alternativ vely, you ca an use the T TryGetValue method. m / // This returns true if the key exists and fals se if the ke ey does not exist. s string csmVal lue = ""; if(coffeeCode es.TryGetVal lue("CSM", o out csmValue) )) { Console.WriteLine("Th he value ass sociated with h the key \" "CSM\" is {0 0}", csmValue e); } e else { Console.WriteLine("Th he key \"CSM M\" was not f found"); } / // You can al lso use the indexer to change the value v associ iated with a key.

Programming in Visual C# 4-41

coffeeCodes["IC"] = "Instant Coffee";

Other Generic Dictionary Classes


The SortedList<TKey, TValue> and SortedDictionary<TKey, TValue> classes both provide generic dictionaries in which the entries are sorted by key. The difference between these classes is in the underlying implementation: The SortedList generic class uses less memory than the SortedDictionary generic class. The SortedDictionary class is faster and more efficient at inserting and removing unsorted data.

4-42 Creating g Classes and Imple ementing Type-Safe Collections

Us sing Colle ection Inte erfaces

The System.Collections.Gen neric namespa ace provides a range of generic collectio ons to suit var rious sce enarios. Howe ever, there wil ll be circumsta ances when you will want t to create your r own generic c collection cla asses in order to provide more specialize ed functionalit ty. For example, you might t want to store e data in a tre ee structure or create a circ cular linked list. Wh here should y you start when n you want to create a cust tom collection n class? All col llections have e certain thi ings in common. For example, you will ty ypically want to be able to enumerate th he items in th he collection by y using a forea ach loop, and d you will need d methods to o add items, re emove items, and clear the list. The pic cture on the slide s shows that the .NET Fr ramework pro ovides a hierar rchical set of i interfaces that define the characteristics a and behaviors of collections s. These interf faces build on n one another r to define pro ogressively mo ore specific fu unctionality.

Th he IEnumer rable and IE Enumerable e<T> Interf faces


If y you want to b be able to use a foreach loo op to enumer rate over the items in your custom gene eric collection, you m must impleme ent the IEnum merable<T> interface. i The IEnumerable e<T> method d defines a sin ngle method n named GetEn numerator(). T This method must return an object of ty ype IEnumera ator<T>. The foreach sta atement relies s on this enum merator object t to iterate thr rough the collection. ble<T> interfa ace inherits fro om the IEnum merable inter rface, which al lso defines a s single The IEnumerab me ethod named GetEnumera ator(). When an interface in nherits from a another interf face, it expose es all the me embers of the e parent interf face. In other words, if you implement IE Enumerable< <T>, you also need to implement IEnu umerable.

Th he ICollectio on<T> Inte erface


The ICollection n<T> interface e defines the basic function nality that is common c to all generic colle ections. The int terface inherit ts from IEnum merable<T>, which means that if you wa ant to implem ment ICollecti ion<T>, you must also im mplement the e members de efined by IEnu umerable<T> > and IEnume erable.

Programming in Visual C# 4-43

The ICollection<T> interface defines the following methods: Name Add Clear Contains CopyTo Remove Description Adds an item of type T to the collection. Removes all items from the collection. Indicates whether the collection contains a specific value. Copies the items in the collection to an array. Removes a specific object from the collection.

The ICollection<T> interface defines the following properties: Name Count IsReadOnly Description Gets the number of items in the collection. Indicates whether the collection is read-only.

The IList<T> Interface


The IList<T> interface defines the core functionality for generic list classes. You should implement this interface if you are defining a linear collection of single values. In addition to the members it inherits from ICollection<T>, the IList<T> interface defines methods and properties that enable you to use indexers to work with the items in the collection. For example, if you create a list named myList, you can use myList[0] to access the first item in the collection. The IList<T> interface defines the following methods: Name Insert RemoveAt Description Inserts an item into the collection at the specified index. Removes the item at the specified index from the collection.

The IList<T> interface defines the following properties: Name IndexOf Description Determines the position of a specified item in the collection.

The IDictionary<TKey, TValue> Interface


The IDictionary<TKey, TValue> interface defines the core functionality for generic dictionary classes. You should implement this interface if you are defining a collection of key-value pairs. In addition to the members it inherits from ICollection<T>, the IDictionary<T> interface defines methods and properties that are specific to working with key-value pairs.

4-44

Creating Classes and Implementing Type-Safe Collections

The IDictionary<TKey, TValue> interface defines the following methods: Name Add ContainsKey GetEnumerator Remove TryGetValue Description Adds an item with the specified key and value to the collection. Indicates whether the collection includes a key-value pair with the specified key. Returns an enumerator of KeyValuePair<TKey, TValue> objects. Removes the item with the specified key from the collection. Attempts to set the value of an output parameter to the value associated with a specified key. If the key exists, the method returns true. If the key does not exist, the method returns false and the output parameter is unchanged.

The IDictionary<TKey, TValue> interface defines the following properties: Name Item Description Gets or sets the value of an item in the collection, based on a specified key. This property enables you to use indexer notation, for example myDictionary[myKey] = myValue. Returns the keys in the collection as an ICollection<T> instance. Returns the values in the collection as an ICollection<T> instance.

Keys Values

Reference Links: For comprehensive information and examples of all of the generic interfaces covered in this topic, see the System.Collections.Generic Namespace page at http://go.microsoft.com/fwlink/?LinkID=267802.

Programming in i Visual C#

4-45 5

C Creating E Enumerab ble Collect tions

To enumerate T e over a collec ction, you typically use a fo oreach loop. T The foreach loop exposes e each item in t collection in turn, in an the n order that is appropriate to t the collecti ion. The forea ach statement t masks some e o the comple of exities of enum meration. For the foreach statement s to w work, a gener ric collection class c must i implement the IEnumerab ble<T> interfa ace. This inter rface exposes a method, Ge etEnumerato or, which must t r return an IEnu umerator<T> > type.

T IEnume The erator<T> Interface


T IEnumera The ator<T> inte erface defines the functiona ality that all en numerators m must implemen nt. T IEnumera The ator<T> inte erface defines the following g methods: Name MoveNext Reset De escription Ad dvanced the e enumerator to o the next item m in the collection. Se ets the enume erator to its starting positio on, which is be efore the first item in the co ollection.

T IEnumera The ator<T> inte erface defines the following g properties: Name Current Descr ription Gets the item that the enumerator is pointing g to.

An enumerato A or is essentiall ly a pointer to o the items in the collection n. The starting g point for the e pointer is b before the firs st item. When n you call the MoveNext method, m the po ointer advanc ces to the next t element in t collection. The MoveN the Next method r returns true if f the enumera ator was able to advance one position, o false if it has reached th or he end of the collection. At any point during the enum meration, the Current p property returns the item t to which the enumerator e is currently pointing. W When you cre eate an enume erator, you must m define: Which ite em the enume erator should treat as the fi irst item in the e collection. In what o order the enum merator shoul ld move throu ugh the items s in the collect tion.

4-46

Creating Classes and Implementing Type-Safe Collections

The IEnumerable<T> Interface


The IEnumerable<T> interface defines a single method named GetEnumerator. This returns an IEnumerator<T> instance. The GetEnumerator method returns the default enumerator for your collection class. This is the enumerator that a foreach loop will use, unless you specify an alternative. However, you can create additional methods to expose alternative enumerators. The following example shows a custom collection class that implements a default enumerator, together with an alternative enumerator that enumerates the collection in reverse order: Default and Alternative Enumerators
class CustomCollection<T> : IEnumerable<T> { public IEnumerator<T> Backwards() { // This method returns an alternative enumerator. // The implementation details are not shown. } #region IEnumerable<T> Members public IEnumerator<T> GetEnumerator() { // This method returns the default enumerator. // The implementation details are not shown. } #endregion #region IEnumerable Members IEnumerator IEnumerable.GetEnumerator() { // This method is required because IEnumerable<T> inherits from IEnumerable throw new NotImplementedException(); } #endregion }

The following example shows how you can use a default enumerator or an alternative enumerator to iterate through a collection: Enumerating a Collection
CustomCollection<Int32> numbers = new CustomCollection<Int32>(); // Add some items to the collection. // Use the default enumerator to iterate through the collection: foreach (int number in numbers) { // } // Use the alternative enumerator to iterate through the collection: foreach(int number in numbers.Backwards()) { // }

Implementing the Enumerator


You can provide an enumerator by creating a custom class that implements the IEnumerator<T> interface. However, if your custom collection class uses an underlying enumerable type to store data, you can use an iterator to implement the IEnumerable<T> interface without actually providing an IEnumerator<T> implementation. The best way to understand iterators is to start with a simple example. The following example shows how you can use an iterator to implement an enumerator:

Programming in Visual C# 4-47

Implementing an Enumerator by Using an Iterator


using System; using System.Collections; using System.Collections.Generic; class BasicCollection<T> : IEnumerable<T> { private List<T> data = new List<T>(); public void FillList(params T [] items) { foreach (var datum in items) data.Add(datum); } IEnumerator<T> IEnumerable<T>.GetEnumerator() { foreach (var datum in data) { yield return datum; } } IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException(); } }

The example shows a custom generic collection class that uses a List<T> instance to store data. The List<T> instance is populated by the FillList method. When the GetEnumerator method is called, a foreach loop enumerates the underlying collection. Within the foreach loop, a yield return statement is used to return each item in the collection. It is this yield return statement that defines the iterator essentially, the yield return statement pauses execution to return the current item to the caller before the next element in the sequence is retrieved. In this way, although the GetEnumerator method does not appear to return an IEnumerator type, the compiler is able to build an enumerator from the iteration logic that you provided.

4-48 Creating g Classes and Imple ementing Type-Safe Collections

Demonstration: Add ding Data Validation and Typ pe-Safety to the pplication n Lab Ap

In this demonstration, you wi ill learn about t the tasks tha at you will per rform in the la ab for this mo odule.

Programming in i Visual C#

4-49 9

Lab: Adding g Data Validat V tion and d Type-Safety y to the lication n Appl

S Scenario
Now that the user interface N e navigation f features are w working, you d decide to repla ace the simple e structs with c classes to mak ke your applic cation more e efficient and st traightforward d. You have also Y o been asked to t include validation logic in the applica ation to ensure e that when a user adds g grades to a st tudent, that th he data is valid d before it is written w to the e database. Yo ou decide to c create a unit t test project th hat will perfor rm tests against the require ed validation f for different g grade scenario os. Teachers who T o have seen th he application have express sed concern th hat the studen nts in their cla asses are d displayed in a random orde er. You decide e to use the IC Comparable in nterface to en nable them to o be displayed d i alphabetica in al order. Finally, you ha F ave been aske ed to add func ctionality to the application n to enable te eachers to add d students to a remove students from a class, and to add student grades to th and he database.

O Objectives
A After complet ting this lab, you y will be able to: Create cla asses. Write dat ta validation code c and unit tests. Implemen nt the IComp parable interfa ace. Use gene eric collections s.

E Estimated Tim me: 60 minutes Virtual Machine: 20483 3A-SEA-DEV11-04, MSL-TM MG1 User Nam me: Student Password d: Pa$$w0rd

4-50

Creating Classes and Implementing Type-Safe Collections

Exercise 1: Implementing the Teacher, Student, and Grade Structs as Classes


Scenario
In this exercise, you will convert the existing Teacher, Student, and Grade structs into classes. This will enable you to implement the additional functionality required for each class, such as adding constructors, properties, and methods. In the Teacher and Student classes, you will make the password property writeonly, add the VerifyPassword method, and then define their respective constructors. You will also modify the Logon_Click method to use the VerifyPassword method to verify passwords when a user logs on. Finally, you will run the application and verify that it still functions correctly, allowing a student or a teacher to log on. The main tasks for this exercise are as follows: 1. Convert the Grades struct into a class 2. Convert the Students and Teachers structs into classes 3. Use the VerifyPassword method to verify the password when a user logs in 4. Build and run the application, and verify that a teacher or student can still log on

X Task 1: Convert the Grades struct into a class


1. 2. 3. 4. 5. Start the MSL-TNG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-04 virtual machine and log on as Student with the password Pa$$w0rd. Start Visual Studio and open the GradesPrototype.sln solution from the E:\Labfiles\Starter\Exercise 1 folder. In the Data folder, in Grade.cs, convert the Grade struct into a class. Define a class constructor that takes the following parameters and uses them to populate the public properties of the class: o o o o o 6. studentID assessmentDate subject assessment comments

Define a default class constructor that takes no parameters and assigns the following default values to the public properties: o o o o o Student ID: 0 AssessmentDate: the current date SubjectName: Math Assessment: A Comments: an empty string

X Task 2: Convert the Students and Teachers structs into classes


1. Convert the Students struct into a class.

Programming in Visual C# 4-51

2. 3.

Create a write-only password property that generates a new GUID for the default value. Create a VerifyPassword method that uses the String.Compare method to check that the password passed to it as a parameter matches the stored

Note: An application should not be able to read passwords; only set them and verify that a password is correct 4. Define a class constructor that takes the following parameters and uses them to populate the public properties of the class: o o o o o o 5. studentID userName password firstName lastName teacherID

Define a default class constructor that takes no parameters and assigns the following default values to the public properties: o o o o o o Student ID: 0 UserName: an empty string Password: an empty string FirstName: an empty string LastName: an empty string TeacherID: an empty string

6. 7.

Convert the Teachers struct into a class. Create a write-only password property that generates a new GUID for a default value and a VerifyPassword method that uses the String.Compare method to check that the password passed to it as a parameter matches the stored password. Define a class constructor that takes the following parameters and uses them to populate the public properties of the class: o o o o o o teacherID userName password firstName lastName className

8.

9.

Define a default class constructor that takes no parameters and assigns the following default values to the public properties: o o TeacherID: 0 UserName: an empty string

4-52

Creating Classes and Implementing Type-Safe Collections

o o o o

Password: an empty string FirstName: an empty string LastName: an empty string Class: an empty string

X Task 3: Use the VerifyPassword method to verify the password when a user logs in
1. 2. 3. 4. In the Views folder, in the LogonPage.xaml.cs code, modify the code in the Logon_Click method to call the VerifyPassword method to verify the teachers password. Modify the code to check whether teacher is null before examining the UserName property. In the Student class, modify the code in the Logon_Click method to use the VerifyPassword method to verify the students password. Modify the code to check whether student is null before examining the UserName property.

X Task 4: Build and run the application, and verify that a teacher or student can still log on
1. 2. 3. 4. 5. 6. 7. 8. Build the solution and resolve any compilation errors. Log in as vallee with a password of password. Verify that you can log on as a teacher. Log off from the application. Log in as grubere with a password of password. Verify that you can log on as a student. Close the application. In Visual Studio, close the solution.

Results: After completing this exercise, the Teacher, Student, and Grade structs will be implemented as classes and the VerifyPassword method will be called when a user logs on.

Programming in Visual C# 4-53

Exercise 2: Adding Data Validation to the Grade Class


Scenario
In this exercise, you will define a public list of strings called Subjects to hold the names of each subject that can be assessed and then populate it with valid subject names. You will then add validation logic to the Grade class to ensure that the subject name appears in the list you created and that the assessment date and assessment grade contain allowed values. Finally, you will create a unit test project to verify that your validation code functions as expected. The main tasks for this exercise are as follows: 1. Create a list of valid subject names 2. Add validation logic to the Grade class to check the data entered by the user 3. Add a unit test to verify that the validations defined for the Grade class functions as expected.

X Task 1: Create a list of valid subject names


1. 2. 3. In Visual Studio, from the E:\Labfiles\Starter\Exercise 2 folder, open the GradesPrototype.sln solution. In the Data folder, in the DataSource class, define a generic List collection to hold the names of valid subjects. In the CreateData method in that class, populate the list with the following subject names: o o o o o Math English History Geography Science

X Task 2: Add validation logic to the Grade class to check the data entered by the user
1. 2. 3. In the Data folder, in the Grade.cs code, add validation code to the AssessmentDate property to ensure that the following requirements have been met: Verify that the user has provided a valid date. Check that the date is no later than the current date. If it is, throw an ArgumentOutOfRangeException exception. If the date is valid, then save it in the appropriate format. If the date is not in a valid format, throw an ArgumentException exception. Add validation code to the Subject property to ensure that the following requirements are met: Check that the specified subject is in the list that you have defined. If the subject is valid, store the subject name. If the subject is not valid, then throw an ArgumentException exception. Add validation to the Assessment property to ensure that the following requirements are met: Verify that the grade is in the range A+ to E-.

Note: You will need to use the following regular expression:

4-54

Creating Classes and Implementing Type-Safe Collections

Match matchGrade = Regex.Match(value, @"[A-E][+-]?$"); If the grade is not valid, then throw an ArgumentOutOfRangeException exception.

X Task 3: Add a unit test to verify that the validations defined for the Grade class functions as expected.
1. 2. 3. 4. 5. Add a Unit Test Project called GradesTest to the solution and reference the GradesPrototype project from it. In the UnitTest1 class, define the following tests and support methods: Init: to call the CreateData method to initialize the DataSource TestValidGrade: to check that valid data passes the validation logic successfully TestBadDate: to check that dates in the future are not valid TestDateNotRecognized: to check that non-dates are not valid TestBadAssessment: to check that assessment values outside the permitted range are not valid TestBadSubject: to check that subject names not in the list are not valid Build the solution and resolve any compilation errors. Run all tests and verify that they all pass. Close Test Explorer and then close the solution.

Results: After completing this exercise, the Grade class will contain validation logic.

Programming in Visual C# 4-55

Exercise 3: Displaying Students in Name Order


Scenario
In this exercise, you will write code to display the students in alphabetical order of last name and then first name. The application currently displays students in no specific order when logged on as a teacher, but you now want them to be displayed in alphabetical order of last name and first name. To achieve this, you decide that the Student class should implement the IComparable<> interface to enable comparison of student data. You can then add code to the CompareTo method in the Student class, enabling students to be sorted based on their last name and first name. Currently, Students are stored in a non-type-safe ArrayList collection. You decide to modify this so they are stored in a type-safe List collection. Finally, you will sort the Students data and then run the application to verify that the students are retrieved and displayed in alphabetical order of their last name and first name. The main tasks for this exercise are as follows: 1. Run the application and verify that the students are not displayed in any specific order when logged on as a teacher 2. Implement the IComparable<Student> interface to enable comparison of students 3. Change the Students ArrayList collection into a List<Student> collection 4. Sort the data in the Students collection 5. Verify that Students are retrieved and displayed in order of their first name and last name

X Task 1: Run the application and verify that the students are not displayed in any specific order when logged on as a teacher
1. 2. 3. 4. In Visual Studio, from the E:\Labfiles\Starter\Exercise 3 folder, open the GradesPrototype.sln solution. Build the solution and resolve any compilation errors. Log in as vallee with a password of password. Verify that the students are not displayed in any specific order. Close the application.

X Task 2: Implement the IComparable<Student> interface to enable comparison of students


1. 2. In the Grade.cs code window, locate the Student class definition, and modify it to implement the IComparable<Student> interface. In the CompareTo method, concatenate the FirstName and LastName properties of each of the students being compared, and then use the String.Compare method to establish the order that they should be displayed in the list.

X Task 3: Change the Students ArrayList collection into a List<Student> collection


1. 2. In the Data folder, in the DataSource.cs code, in the DataSource class, modify the Students ArrayList collection to be a generic List collection. In the CreateData method, modify the creation of the Students collection to create a new generic List collection.

4-56

Creating Classes and Implementing Type-Safe Collections

X Task 4: Sort the data in the Students collection


1. In MainWindow.xaml.cs, in the MainWindow constructor, after calling the DataSource.CreateData method, add a method call to sort the data in the Students collection.

X Task 5: Verify that Students are retrieved and displayed in order of their first name and last name
1. 2. 3. 4. 5. 6. Build the solution and resolve any compilation errors. Run the application without debugging. Log in as vallee with a password of password. Verify that the students are displayed in order of ascending last name. Close the application. In Visual Studio, close the solution.

Results: After completing this exercise, the application will display the students in alphabetical order of last name and then first name.

Programming in Visual C# 4-57

Exercise 4: Enabling Teachers to Modify Class and Grade Data


Scenario
In this exercise, you will write code that enables a teacher to add a student and then enroll them in a class. This will be implemented as two separate steps, because a teacher may want to add a student before knowing which class they will be enrolled in. You will also enable a teacher to remove a student from a class. When adding or removing a student, you will display a prompt to confirm that the teacher wants to perform the action. To enroll a student in a class or remove them from a class, you modify the TeacherID property of that student. The application now includes the AssignStudentDialog window, which displays a list of students who are not assigned to a class. You need to add code to this window to assign a student to the teachers class and to update the list of students as appropriate. You also need to add code to remove a student from a class and to enable teachers to add grades to their students. After a student has been added to the database, that student will be able to log on to view their own grades. The main tasks for this exercise are as follows: 1. Change the Teachers and Grades collections to be generic List collections 2. Add the EnrollInClass and RemoveFromClass methods for the Teacher class 3. Add code to enroll a student in a teachers class 4. Add code to enable a teacher to remove the student from the assigned class 5. Add code to enable a teacher to add a grade to a student 6. Run the application and verify that students can be added to and removed from classes, and that grades can be added to students

X Task 1: Change the Teachers and Grades collections to be generic List collections
1. 2. 3. 4. 5. In Visual Studio, from the E:\Labfiles\Starter\Exercise 4 folder, open the GradesPrototype.sln solution. In the Data folder, in the DataSource.cs code, change the Teachers collection to be a generic List collection. Change the Grades collection to be a generic List collection. In the CreateData method, modify the creation of the Teachers collection to create a new generic List collection. In the CreateData method, modify the creation of the Grades collection to create a new generic List collection.

X Task 2: Add the EnrollInClass and RemoveFromClass methods for the Teacher class
1. 2. In the Data folder, in the Grade.cs code, in the Teacher class, implement the EnrollInClass method as follows: Verify that the student is not already enrolled in another class. If the student is not in another class, set the TeacherID property of the student to the current TeacherID. If the Student is in another class, throw an ArgumentException exception to show that the student is already assigned to a class. In the Teacher class, add code to the RemoveFromClass method as follows:

4-58

Creating Classes and Implementing Type-Safe Collections

3.

Verify that the Student is actually assigned to the class for the given teacher. If the student is part of the class, reset the TeacherID property of the student to zero. If the student is not part of the class, throw an ArgumentException exception to show that the student is not assigned to this class. In the Teacher class, implement the AddGrade method as follows: Verify that the Grade object passed to the method does not belong to another student. If it does not belong to another student, add the grade to the students record by setting the StudentID property of the Grade object. If it does belong to another student, throw an ArgumentException exception to show that the grade belongs to a different student.

X Task 3: Add code to enroll a student in a teachers class


1. 2. 3. In the Controls folder, in the AssignStudentDialog.xaml.cs code, in the Student_Click method, write code as follows: Add a try block. Inside the try block, determine which student the user clicked by using the Tag property of the studentClicked button. Find this student in the Students collection and prompt the user to confirm that they wish to add the student to their class. If the user confirms this, add the student to the class by calling the EnrollInClass method, and then refresh the display. Add a catch block to display a message to the user if an exception occurs. In the Refresh method, write code as follows: Find all unassigned students with a TeacherID of zero. If there are no unassigned students, show the txtMessage box and hide the list control. If there are unassigned students, hide the txtMessage box and show the list control bound to the list of unassigned students. In the StudentsPage.xaml.cs code, in the EnrollStudent_Click method, add code to use the AssignStudentDialog to display the unassigned students. Then refresh the display to show any newly enrolled students.

X Task 4: Add code to enable a teacher to remove the student from the assigned class
1. In the StudentProfile.xaml.cs code, in the Remove_Click method, write code as follows: Detect if the user is a teacher. If they are not, exit the method. Add a try block. Inside the try block, display a message box to prompt the user to confirm that the current student should be removed from their class. If the user confirms, call the RemoveFromClass method of the current teacher to remove this student from their class, and then return to the previous page. Add a catch block to display a message to the user if an exception occurs.

Programming in Visual C# 4-59

X Task 5: Add code to enable a teacher to add a grade to a student


1. In the StudentProfile.xaml.cs code, in the AddGrade_Click method, write code to add a grade to a student as follows: Detect if the user is a teacher. If they are not, exit the method. Add a try block. Inside the try block, use the GradeDialog to get the details of the assessment grade and use them to create a new Grade object. Save the grade to the list of grades. Add the grade to the current student. Refresh the display so that the new grade appears. Add a catch block to display a message to the user if an exception occurs.

X Task 6: Run the application and verify that students can be added to and removed from classes, and that grades can be added to students
1. 2. 3. 4. 5. 6. 7. 8. Build the solution and resolve any compilation errors. Log in as vallee with a password of password. Add a student with the following details: First name: Darren Last name: Parker Password: password Verify that Darren Parker is added to the student list. Remove the student Kevin Liu from the student list. For the student Darren Parker, add a new grade by using the following information: Date: current date Subject: English Assessment: B Comments: Good Verify that the grade information is added to the Report Card. Log on as the student Darren Parker and verify that the grade information from the previous steps is displayed in the Report Card.

Note: A username is generated by taking a users last name and the first initial of their first name. The username for Darren Parker is parkerd. 9. Close the application.

10. In Visual Studio, close the solution.

Results: After completing this exercise, the application will enable teachers to add and remove students from their classes, and to add grades to students.

4-60

Creating Classes and Implementing Type-Safe Collections

Programming in i Visual C#

4-61 1

Module Rev view an nd Take eaways

M Module Rev view


I this module In e, you have le earned how to o work with classes, interfac ces, and generic collections s in Visual C#. . T Test Your Kno owledge Question Which of the following types t is a refe erence type? Select the correct answer r. Boolean Byte e Decimal Int32 Obje ect T Test Your Kno owledge Question Which of the following types t of mem mber CANNOT T be included d in an interfa ace? Select the correct answer r. Even nts Field ds

4-62

Creating Classes and Implementing Type-Safe Collections

Question Indexers Methods Properties Test Your Knowledge Question You want to create a custom generic class. The class will consist of a linear collection of values, and will enable developers to queue items from either end of the collection. Which of the following should your class declaration resemble? Select the correct answer. public class DoubleEndedQueue<T> : IEnumerable<T> public class DoubleEndedQueue<T> : ICollection<T> public class DoubleEndedQueue<T> : IList<T> public class DoubleEndedQueue<T> : IList<T>, IEnumerable<T> public class DoubleEndedQueue<T> : IDictionary<TKey,TValue>

5-1

Module 5
Creating a Class Hierarchy by Using Inheritance
Contents:
Module Overview Lesson 1: Creating Class Hierarchies Lesson 2: Extending .NET Framework Classes Lab: Refactoring Common Functionality into the User Class Module Review and Takeaways 5-2 5-3 5-17 5-29 5-37

5-2

Creating a Class Hierarchy by y Using Inheritance

Modu ule Ove erview

The concept of inheritance is s central to ob bject-oriented programmin ng in any language. It is also o one of the e most power rful tools in yo our developer r toolbox. Esse entially, inheri itance enables s you to creat te new cla asses by inheriting characte eristics and be ehaviors from existing classes. When you u inherit from an existing cla ass and add so ome functiona ality of your o own, your clas ss becomes a more specializ zed instance of o the existing class. Not only does this save you time by reduc cing the amount of code y you need to w write, it also enables you to create c hierarc chies of related d classes that you can then n use interchangeably, depe ending on your requirements. In this module, y you will learn how to use in nheritance to create class hierarchies h and d to extend .N NET Fra amework type es.

Ob bjectives
Aft ter completing this module e, you will be able to: e classes and d derived classe es by using inh heritance. Create base Create class ses that inheri it from .NET Framework F cla asses.

Programming g in Visual C#

5-3 3

Lesson 1

Creat ting Cla ass Hierarchie es

Rather than creating new classes R c from nothing, in ma any cases you can use an ex xisting class as s a base for y your new clas ss. This is know wn as inheritance. Your clas ss inherits all the t members from the base class, and y simply inc you clude the func ctionality that t you want to add to the ba ase classs cap pabilities. This way, your c class becomes s a more spec cialized version of the base class. This concept of inheritance is one e of the main p pillars of obje ect-oriented programming. I this lesson, you will learn In n how to use inheritance i to o create class hierarchies. h

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Describe inheritance. Create ba ase classes. Create ba ase class mem mbers. Create cla asses that inhe erit from base e classes. Call base class method ds and constru uctors from within a derived d class.

5-4

Creating a Class Hierarchy by y Using Inheritance

W What Is Inh heritance? ?

In Visual C#, a class c can inher rit from anoth her class. Whe en you create a class that in nherits from an nother cla ass, your class is known as t the derived cla ass and the cla ass that you in nherit from is known as the e base class. The derived clas ss inherits all the t members of the base class, including g constructors s, methods, pr roperties, fields, and events. Inh heritance enables you to bu uild hierarchie es of progress sively more sp pecialized clas sses. Rather th han creating ac class from not thing, you can n inherit from a more general base class to provide a starting point t for your fun nctionality. For example, yo ou define a cla ass named Beverage, as shown below: Th he Beverage C Class
p public class Beverage { protected int serving gTemperature e; public string Name { get; set; } public boo ol IsFairTra ade { get; s set; } public int t GetServing gTemperature e() { return servingTemp perature; } }

No ow you want t to create a cla ass to represent coffees. Co offee is a type of beverage. It shares all th he characteristics a and behaviors of a beverage. Rather than n creating a class from scratch to represe ent coffees, you can create a class that inherits from th ived class inhe he Beverage class. c The deri erits all the m members of the e Beverage cla ass, such as th he servingTem mperature fie eld, the Name e property, th he IsFairTrade e property, and the GetServ vingTempera ature method d. Within the derived d class, you just need d to add mem mbers that are e specific to coffees. The following ex xample shows s how to creat te a class for coffees c that in nherits from the Beverage class:

Programming in Visual C# 5-5

The Coffee Class


public class Coffee : Beverage { public string Bean { get; set; } public string Roast { get; set; } public string CountryOfOrigin { get; set; } }

Note: In object-oriented programming, the terms derives and inherits are used interchangeably. Saying that the Coffee class derives from the Beverage class means the same as saying the Coffee class inherits from the Beverage class. As you can see in the previous examples, the syntax for inheriting from a class is similar to the syntax for implementing an interface. This is because inheriting from a class and implementing an interface are both examples of inheritance. However, you do not need to duplicate the base class members in the derived class. By adding the base class to your class declaration, you make all the members of the base class available to consumers of your derived class. The following example shows how to use base class members in a derived class: Calling Base Class Members
Coffee coffee1 = new Coffee(); // Use base class members. coffee1.Name = "Fourth Espresso"; coffee1.IsFairTrade = true; int servingTemp = coffee1.GetServingTemperature(); // Use derived class members. coffee1.Bean = "Arabica"; coffee1.Roast = "Dark"; coffee1.CountryOfOrigin = "Columbia";

As shown in the above example, you can call members of a base class in the same way that you call members of the class itself.

5-6

Creating a Class Hierarchy by y Using Inheritance

Cr reating Ba ase Classes

Wh hen you creat te a class, you should consider whether y you or other d developers will need to use e it as a base for derived d classes. You have full cont trol over whether, and how w, your class can be inherite ed.

Ab bstract Clas sses and Members


As part of an ob bject-oriented d design, you may want to c create classes that serve so olely as base classes for oth her types. The e base class m may contain missing or inco omplete functi ionality, and y you may not w want to enable code to instantiate yo our class directly. In these sc cenarios, you can add the a abstract keyw word to your class declaration. The following ex xample shows s how to decla are an abstrac ct class: De eclaring an A Abstract Class s
a abstract clas ss Beverage { }

The abstract ke eyword indicates that the class cannot be e instantiated directly; it ex xists solely to d define or implement mem mbers for derived classes. If f you attempt to instantiate e an abstract class c you will get an err ror when you build your co ode. An n abstract clas ss can contain both abstract and non-abstract membe ers. Abstract m members are a also de eclared with th he abstract ke eyword and a are conceptually similar to i interface mem mbers, in that abstract me embers define e the signatur re of the mem mber but do no ot provide any implementa ation details. Any A class tha at inherits from the abstrac ct class must p provide an implementation n for the abstr ract members. . Nonab bstract membe ers, however, can be used d directly by derived classes. The following ex xample illustr rates the difference betwee en abstract and non-abstrac ct members: bstract and N Non-Abstract t Members Ab
a abstract clas ss Beverage { // Non-abs stract membe ers. // Derived d classes ca an use these e members wit thout modify ying them. public string Name { get; set; } public boo ol IsFairTra ade { get; s set; } // Abstrac ct members.

Programming in Visual C# 5-7

// Derived classes must override and implement these members. public abstract int GetServingTemperature(); }

Note: You can only include abstract members within abstract classes. A non-abstract class cannot include abstract members.

Sealed Classes
You may want to create classes that cannot be inherited from. You can prevent developers from inheriting from your classes by marking the class with the sealed keyword. The following example shows how to use the sealed modifier: Creating a Sealed Class
public sealed class Tea : Beverage { // }

You can apply the sealed modifier to classes that inherit from other classes and classes that implement interfaces. You cannot use the sealed modifier and the abstract modifier on the same class, as a sealed class is the opposite of an abstract classa sealed class cannot be inherited, whereas an abstract class must be inherited. Any static class is also a sealed class. You can never inherit from a static class. Similarly, any static members within non-static classes are not inherited by derived classes.

5-8

Creating a Class Hierarchy by y Using Inheritance

Cr reating Ba ase Class Members M

Yo ou may want t to implement a method in y your base class, but allow d derived classe es to replace your y me ethod implem mentation with h more specifi ic functionalit ty. To create a member that developers c can ov verride in a de erived class, yo ou use the vir rtual keyword d. The following ex xample shows s how to creat te a virtual method in a cla ass: dding Virtual l Members Ad
p public class Beverage { protected int serving gTemperature e; public string Name { get; set; } public boo ol IsFairTra ade { get; s set; } public virtual int Ge etServingTem mperature() { // This s is the def fault implem mentation of the GetServ vingTemperat ture method. // Beca ause the met thod is declared virtual l, you can o override the e implementat tion in d derived class ses. return servingTemp perature; } }

Wh hen you creat te a class, you can use acce ess modifiers t to control whe ether the mem mbers of your r class are acc cessible to de erived types. Y You can use th he following a access modifie ers for class m members: A Access Modifi ier p public p protected i internal p protected inte ernal p private Deta ails The member is av vailable to code running in n any assembly y. The member is av vailable only within w the con ntaining class or in classes d derived m the containing class. from The member is av vailable only t to code within n the current assembly. The member is av vailable to any code within n the current a assembly, and d to types ived from the containing cl lass in any ass sembly. deri The member is av vailable only within w the con ntaining class.

Programming in Visual C# 5-9

Members of a class are private by default. Private members are not inherited by derived classes. If you want members that would otherwise be private to be accessible to derived classes, you must prefix the member with the protected keyword.

5-10 Creating g a Class Hierarchy by Using Inheritanc ce

In nheriting from f a Bas se Class

To o inherit from another class, you add a co olon followed d by the name e of the base c class to your c class de eclaration. The following ex xample shows s how to inhe erit from a bas se class: De eclaring a Cla ass that Inher rits From a B Base Class
p public class Coffee : Be everage { }

The derived clas ss inherits eve ery member fr rom the base class. Within y your derived class, you can n add new me embers to ext tend the funct tionality of the base type. A class c can only y inherit from one base clas ss. However, y your class can implement one or more in nterfaces in addition to deriving from a b base type.

Ov verriding B Base Class Members M


In some cases yo ou may want to change the way a base class member r works in you ur derived clas ss. b class includes a metho od named Get tServingTemperature: For example, the Beverage base dding Virtual l Members Ad
p public class Beverage { protected int serving gTemperature e; public virtual int Ge etServingTem mperature() { return servingTemp perature; } // Other c class member rs not shown n. }

Be ecause GetSer rvingTemper rature is a virt tual method, you y can overr ride it in a der rived class. To o override a vir rtual method i in a derived c class, you create a method w with the same e signature an nd prefix it wit th the ov verride keywor rd. The following ex xample shows s how to over rride a virtual method in a derived d class:

Programming in Visual C# 5-11

Overriding a Virtual Method by Using the override Keyword


public class Coffee : Beverage { protected bool includesMilk; private int servingTempWithMilk; private int servingTempWithoutMilk; public override int GetServingTemperature() { if(includesMilk) return servingTempWithMilk else return servingTempWithoutMilk; } }

You can use the same approach to override properties, indexers, and events. In each case, you can only override a base class member if the member is marked as virtual in the base class. You cannot override constructors. You can also override a base class member by using the new keyword: Overriding a Virtual Method by Using the new Keyword
public class Coffee : Beverage { public new int GetServingTemperature() { // } }

When you use the override keyword, your method extends the base class method. By contrast, when you use the new keyword, your method hides the base class method. This causes subtle but important differences in how the compiler treats your base class and derived class types. Reference Links: For a detailed explanation of the differences in behavior between the override keyword and the new keyword, see Knowing When to Use Override and New Keywords (C# Programming Guide) at http://go.microsoft.com/fwlink/?LinkID=267803.

Sealing Overridden Members


When you override a base class member, you can prevent classes that derive from your class from overriding your implementation of the base class member by using the sealed keyword. The following example shows how to seal an overridden base class member: Sealing an Overridden Member
public class Coffee : Beverage { sealed public override int GetServingTemperature() { // Derived classes cannot override this method. } }

By sealing an overridden member, you force any classes that derive from your class to use your implementation of the base class member, rather than creating their own. You can only apply the sealed modifier to a member if the member is an override member. Remember that members are inherently sealed unless they are marked as virtual. In this case, because the base class

5-12

Creating a Class Hierarchy by Using Inheritance

method is marked as virtual, any descendants are able to override the method unless you seal it at some point in the class hierarchy.

Programming in i Visual C#

5-13 3

C Calling Ba ase Class C Constructo ors and Members M

onstructors fr You can use the base keyw Y word to access s base class methods m and co rom within a d derived class. T is useful in This i the followin ng scenarios: You overr ride a base cla ass method, b but you still want to execute the function nality in the base class method in addition to your own add ditional functionality. You creat te a new meth hod, but you want w to call a base class me ethod as part of your meth hod logic. You creat te a constructor and you w want to call a base b class constructor as pa art of your init tialization logic. You want t to call a base e class method from a prop perty accessor r.

C Calling Bas se Class Con nstructors f from a Deri ived Class


You cannot ov Y verride constr ructors in deri ived classes. In nstead, when you create co onstructors in a derived c class, your con nstructors will automaticall ly call the defa ault base class constructor before they e execute any o the logic th of hat you have added. a Howev ver, in some c circumstances s, you might w want your con nstructors to c an alterna call ative base clas ss constructor r. In these case es, you can us se the base ke eyword in you ur constructor r d declarations to specify whic ch base class constructor yo ou want to ca all. T following example sho The ows how to call base class constructors: C Calling Base Class Constr ructors
public clas ss Beverage { public B Beverage() { // Im mplementatio on details not shown. } public B Beverage(str ring name, bool isFairTr rade, int se ervingTemp) { // Im mplementatio on details are not shown n. } // Other r class memb bers are not shown. } public clas ss Coffee : Beverage { public C Coffee()

5-14

Creating a Class Hierarchy by Using Inheritance

{ // This constructor implicitly calls the default Beverage constructor. // The declaration is implicitly equivalent to public Coffee() : base() // You can include additional code here. } public Coffee(string name, bool isFairTrade, int servingTemp, string bean, string roast) : base(name, isFairTrade, servingTemp) { // This calls the Beverage(string, bool, int) constructor. // You can include additional code here: Bean = bean; Roast = roast; } public string Bean { get; set; } public string Roast { get; set; } public string CountryOfOrigin { get; set; } }

As the previous example shows, you must call the base class constructor from your constructor declaration. You cannot call the base class constructor from within your constructor method body. You can use the named parameters from your constructor declaration as arguments to the base class constructor.

Calling Base Class Methods from a Derived Class


You can call base class methods from within method bodies or property accessors in a derived class. To do this, you use the base keyword as you would use an instance variable. The following example shows how to call base class methods: Calling Base Class Methods
public class Beverage { protected int servingTemperature; public virtual int GetServingTemperature() { return servingTemperature; } // Constructors and additional class members are not shown. } public class Coffee : Beverage { bool iced = false; protected int servingTempIced = 40; public override int GetServingTemperature() { if(iced) { return servingTempIced; } else { return base.GetServingTemperature(); } } }

Remember that the rules of inheritance do not apply to static classes and members. As such, you cannot use the base keyword within a static method.

Programming in i Visual C#

5-15 5

D Demonstr ration: Ca alling Base e Class Co onstructors

In this demon I nstration, you will step through the execu ution of an ap pplication. The e solution includes a class n named Coffee that inherits s from a class named Beverage. The Coffee class incl ludes two con nstructors ctor, and one that explicitly o that implicitly calls the one e default base class construc y calls an alternative base c class construc ctor. The appli ication creates instances of f the Coffee class c by using both of these e c constructors. In both cases, , you can obse erve how deri ived class con nstructors call base class constructors. Y will also s You see how deriv ved class const tructors pass argument values to base class construct tors.

D Demonstra ation Steps


1 1. 2 2. 3 3. Start the MSL-TMG1 vi irtual machine e if it is not already running g. Start the 20483-SEA-D DEV11-05 virtu ual machine. Log on to o Windows 8 as a Student with the passwo ord Pa$$w0r rd. Note: If f necessary, click Switch Us ser to display the list of use ers. 4 4. 5 5. 6 6. 7 7. 8 8. 9 9. Switch to the Windows s 8 Start men nu. Click Visu ual Studio 201 12. In Visual Studio, on the e File menu, p point to Open n, and then click Project/Solution. In the Op pen Project dialog box, bro owse to E:\De emocode, clic ck BaseConstructors.sln, and a then click Open. In Solutio on Explorer, do ouble-click Be everage.cs an nd review the contents of t the class. Note that t the Beverag ge class contains a default constructor c an nd an alternat tive construct tor.

1 In Solutio 10. on Explorer, do ouble-click Co offee.cs and review the contents of the class. 1 Note that 11. t the Coffee c class inherits f from the Beve erage class. 1 Note that 12. t the Coffee c class contains a default con nstructor and an alternative e constructor. 1 Note that 13. t the alternative constructo or explicitly ca alls the alterna ative constructor in the bas se class. 1 In Solutio 14. on Explorer, do ouble-click Pr rogram.cs an nd review the contents of th he class.

5-16

Creating a Class Hierarchy by Using Inheritance

15. Note that the Program class creates two instances of the Coffee type: one by using the default constructor, and one by using the alternative constructor. 16. On the Build menu, click Rebuild Solution. 17. Press F11 twice so that the first line of executable code in the Program class is highlighted. 18. Press F11. Note that the debugger steps into the default constructor for the Coffee class. 19. Press F11. Note that the debugger steps into the default constructor for the Beverage class. 20. Point out that derived class constructors implicitly call the default base class constructor unless you specify an alternative base class constructor. 21. Press F11 six times, until the debugger returns to the default constructor for the Coffee class. 22. Point out that the base class constructor logic is executed before the derived class constructor logic. 23. Press F11 six times, until the debugger returns to the Program class. 24. Press F11. The second executable line of code in the Program class should be highlighted. 25. Press F11. Note that the debugger steps into the alternative constructor for the Coffee class. 26. Press F11. Note that the debugger steps into the alternative constructor for the Beverage class. 27. Hover over the Beverage constructor parameters, and point out that the Coffee constructor has passed argument values to this constructor. 28. Press F11 six times, until the debugger returns to the alternative constructor for the Coffee class. 29. Press F11 six times, until the debugger returns to the Program class. 30. Press F5 to run the remainder of the application. 31. When the console window appears, point out that it makes no difference to consumers of the class whether variables were set by the derived class constructor or the base class constructor. 32. Press Enter to close the console window. 33. Close Visual Studio.

Programming in i Visual C#

5-17 7

Lesson 2

Exten nding .NET Fra amewo ork Clas sses

The .NET Fram T mework conta ains several thousand classe es that provide a wide rang ge of functionality. When y create your own classe you es, you should d look to build d on these clas sses by inherit ting from .NE ET Framework t types whereve er possible. Not only does t this reduce th he amount of code you nee ed to write, it also helps to e ensure that yo our classes wo ork in a standa ardized way. The .NET Fram T mework also enables e you to o create exten nsion methods s to add functionality to sea aled .NET F Framework ty ypes. This enab bles you to ex xtend the func ctionality of b built-in types, such as the String class, w when the inhe eritance appro oach is not pe ermitted. In this lesson, you will learn I n how to extend .NET Fram mework types by b using inheritance and ex xtension m methods.

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Create cla asses that inhe erit from .NET T Framework t types. Create cu ustom exception classes. Throw an nd catch custo om exceptions s. Create cla asses that inhe erit from gene eric types. Create ex xtension meth hods for .NET Framework ty ypes.

5-18 Creating g a Class Hierarchy by Using Inheritanc ce

In nheriting from f .NET T Framewo ork Classe es

There are almos st 15,000 public types in the .NET Framework. Althoug gh not all of t these are extendable cla asses, many of f them are. W When you want t to develop a class, in man ny cases there e is a built-in .NET Fra amework class s that can pro ovide a founda ation for your r code. There are two k key advantage es to creating a class that in nherits from a .NET Framew work class, rath her than de eveloping a cla ass from scrat tch: Reduced development time. By inhe eriting from an existing clas ss, you reduce e the amount of logic that you ha ave to create y yourself. Standardiz zed functiona ality. Just like implementing an interface e, inheriting fr rom a standar rd base class means s that your cla ass will work in n a standardiz zed way. You can also repre esent instance es of your class as inst tances of the base b class, wh hich makes it easier e for developers to use e your class al longside other types s that derive fr rom the same e base class.

The rules of inheritance apply y to built-in .N NET Framewo ork classes in t the same way they apply to o custom cla asses: eate a class that derives from a .NET Fram mework class, providing tha at the class is not sealed You can cre or static. erride any bas se class memb bers that are marked m as vir rtual. You can ove If you inher rit from an abstract class, yo ou must provide implemen ntations for all abstract mem mbers.

hen you creat te a class, sele ect a base clas ss that minimizes the amou unt of coding and customiz zation Wh req quired. If you find yourself replicating fu unctionality th hat is available e in built-in classes, you sho ould pro obably choose a more spec cific base class. On the othe er hand, if you u find that you need to ove erride sev veral member rs, you should d probably cho oose a more g general base class. c For example, co onsider that yo ou want to cre eate a class th hat stores a lin near list of values. The class s must enable you to re emove duplicate items from m the list. Rather than creating a new list t class from nothing, you can accomplish this by creating a class tha at inherits from m the generic List<T> class and adding a single me ethod to remo ove duplicate items. In add dition, you can n take advanta age of the Sort method in the Lis st<T> class. If f you call the Sort method, , any duplicate items will be adjacent in the collection n, which can ma ake it easier to o identify and d remove them m. The following ex xample shows s how to extend the List<T T> class:

Programming in Visual C# 5-19

Extending a .NET Framework Class


public class UniqueList<T> : List<T> { public void RemoveDuplicates() { base.Sort(); for (int i = this.Count 1; i > 0; i--) { if(this[i].Equals(this[i-1])) { this.RemoveAt(i); } } } }

When you use this approach, consumers of your class have access to all the functionality provided by the base List<T> class. They also have access to the additional RemoveDuplicates method that you provided in your derived class.

5-20 Creating g a Class Hierarchy by Using Inheritanc ce

Cr reating Cu ustom Exc ceptions

The .NET Frame ework contains built-in exce eption classes s to represent most commo on error condi itions. For exa ample: ke a method w with a null arg gument value, , and the met thod cannot h handle null arg gument If you invok values, the method will throw t an Argu umentNullEx xception. mpt to divide a numerical v value by zero, the runtime w will throw a D DivideByZeroException. If you attem If you attem mpt to retrieve e an indexed item from a c collection, and d the index it o outside the bo ounds of the collectio on, the indexe er will throw a an IndexOutO OfRangeExce eption.

Note: Mo ost built-in exc ception classe es are defined in the System m namespace e. For more inf formation abo out the System m namespace e, see the Syst tem Namespace page at htt tp://go.micros soft.com/fwlin nk/?LinkID=26 67804. Wh hen you need d to throw exc ceptions in your code, you should reuse existing .NET Framework e exception typ pes wherever possible. How wever, there m may be circum mstances when n you want to create your o own custom exc ception types s.

W When Should d You Creat te a Custom m Exception n Type?


Yo ou should consider creating g a custom exc ception type when: w ception types do not adequ uately represe ent the error c condition you are identifyin ng. Existing exc The excepti ion requires v very specific re emedial action n that differs f from how you u would handle built-in exception ty ypes.

emember that the primary purpose p of ex xception types s is to enable you to handle e specific erro or Re conditions in sp pecific ways by y catching a specific except tion type. The e exception type is not designed to communicate th he precise det tails of the pro oblem. All exc ception classe es include a message prope erty for this pu urpose. Theref fore, you shou uld not create a custom exc ception class j just to commu unicate the na ature of an err ror condition. Create a cust tom exception n class only if you need to handle that error condition n in a dis stinct way.

Programming in Visual C# 5-21

Creating Custom Exception Types


All exception classes ultimately derive from the System.Exception class. This class provides a range of properties that you can use to provide more detail about the error condition. For example: The Message property enables you to provide more information about what happened as a text string. The InnerException property enables you to identify another Exception instance that caused the current instance. The Source property enables you to specify the item or application that caused the error condition. The Data property enables you to provide more information about the error condition as key-value pairs.

When you create a custom exception type, you should make use of these existing properties wherever possible, rather than creating your own alternative properties. At a high level, the process for creating a custom exception class is as follows: 1. 2. 3. Create a class that inherits from the System.Exception class. Map your class constructors to base class constructors. Add any members if required.

The following example shows how to create a custom exception class: Creating a Custom Exception Type
using System; public class LoyaltyCardNotFoundException : Exception { public LoyaltyCardNotFoundException() { // This implicitly calls the base class constructor. } public LoyaltyCardNotFoundException( string message) : base(message) { } public LoyaltyCardNotFoundException(string message, Exception inner) : base(message, inner) { } }

Note: When you create a custom exception class, it is a best practice to include the word Exception at the end of your class name.

5-22 Creating g a Class Hierarchy by Using Inheritanc ce

Th hrowing a and Catching Custo om Exceptions

Aft ter you have created c your c custom excep ption type, you u can throw a and catch cust tom exception ns in the sam me way that y you would thr row and catch h any other ex xceptions. To t throw a custo om exception, you use the e throw keyw word and create a new insta ance of your e exception type e. The following co ode shows ho ow you can throw a custom m exception: hrowing a Custom Except tion Th
p public Loyalt tyCard { public sta atic int Get tBalance(str ring loyaltyC CardNumber) { var cus stomer = Loy yaltyCard.Ge etCustomer(lo oyaltyCardNu umber); if(cust tomer == nul ll) { thro ow new Loyal ltyCardNotFo oundException n("The card number prov vided was not t f found"); } else { retu urn customer r.TotalPoint ts; } } // Other c class member rs are not s shown. }

To o catch the exc ception, you u use a try/catch h block. Reme ember that yo ou should always attempt to o catch the mo ost specific ex xceptions first, , and the mos st general exception (typica ally System.Ex xception) last t. The following ex xample shows s how you can n catch a cust tom exception n: Ca atching a Cus stom Exceptio on
p public bool PayWithPoint ts(int costI InPoints, string cardNum mber) t try { int totalPoints = Loy yaltyCard.Ge etBalance(cardNumber); // Throws a LoyaltyCa ardNotFoundE Exception if the card nu umber is inv valid. if(totalPo oints >= cos stInPoints) {

Programming in Visual C# 5-23

LoyaltyCard.DeductPoints(costInPoints); return true; } else return false; } catch(LoyaltyCardNotFoundException) { // Take appropriate action to remedy the invalid card number. return false; } catch(Exception) { // Catches other unanticipated exceptions. return false; }

5-24 Creating g a Class Hierarchy by Using Inheritanc ce

In nheriting from f Gene eric Types s

Wh hen you inher rit from a gen neric class, you u must decide e how you want to manage e the type parameters of the e base class. You Y can handl le type param meters in two w ways: Leave the ty ype paramete er of the base type unspecif fied. Specify a ty ype argument for the base type.

onsider an exa ample where y you want to c create a custom m list class tha at inherits from List<T>. If you leave Co the e type parame eter of the ba ase type unspe ecified, you m must include th he same type parameter in your class de eclaration. The following ex xample shows s how to inhe erit from a gen neric base typ pe without spe ecifying a type e arg gument: Inh heriting from m a Generic B Base Type Wi ithout Specif fying a Type Argument
p public class CustomList< <T> : List<T T> { }

In the above exa ample, when you instantiat te the Custom mList class and provide a ty ype argument t for T, the sam me type argument is applie ed to the base e class. Alt ternatively, yo ou can specify y a type argum ment for the b base type in yo our class declaration. When n you use thi is approach, any a references s to the type p parameter in t the base type e are replaced with the type e you spe ecify in your c class declaration. The following ex xample shows s how to spec cify a type argument for a b base type: heriting from m a Generic B Base Type by y Specifying a Type Argum ment Inh
p public class CustomList : List<int> > { }

In the above exa ample, when you instantiat te the Custom mList class, yo ou do not nee ed to specify a type parameter. Any base class me ethods or pro operties that re eferenced the e type parame eter are now s strongly typ ped to the Int t32 type. For example, the List.Add met thod will only y accept argum ments of type Int32. If t the base class that you are inheriting fro om contains m multiple type p parameters, yo ou can specify y type arg guments for any a number of o them. The im mportant thin ng to rememb ber is that you must either p provide a

Programming in Visual C# 5-25

type argument or add a matching type parameter to your class declaration for each type parameter in the base type. The following example shows the different ways in which you can inherit from a base type with multiple type parameters: Inheriting from a Base Type with Multiple Type Parameters
// Pass all the base type parameters on to the derived class. public class CustomDictionary1<TKey, TValue> : Dictionary<TKey, TValue> { } // Provide an argument for one of the base type parameters and pass the other one to the derived class. public class CustomDictionary2<TValue> : Dictionary<int, TValue> { } // Provide arguments for both of the base type parameters. public class CustomDictionary3 : Dictionary <int, string> { }

Regardless of how manyif anytype parameters the base type includes, you can add additional type parameters to your derived class declarations. The following example shows how to add additional type parameters to derived class declarations: Adding Type Parameters to Derived Class Declarations
// Pass the base type parameter on to the derived class, and add an additional type parameter. public class CustomCollection1<T, U> : List <T> // Provide an argument for the base type parameter, but add a new type parameter. public class CustomCollection2<T> : List<int> //Inherit from a non-generic class, but add a type parameter. public class CustomCollection3<T> : CustomBaseClass

5-26 Creating g a Class Hierarchy by Using Inheritanc ce

Cr reating Ex xtension Methods M

In most cases, if f you want to extend the fu unctionality of f a class, you u use inheritanc ce to create a derived cla ass. However, this is not alw ways possible. Many built-in n types are sealed to prevent inheritance e. For exa ample, you ca annot create a class that ex xtends the Sys stem.String type. As an alternative e to using inh heritance to ex xtend a type, you can creat te extension m methods. When you cre eate extension n methods, yo ou are creating methods th hat you can ca all on a particu ular type without act tually modifyi ing the under rlying type. An n extension m method is a typ pe of static method. To create an ext tension metho od, you create e a static method within a static class. Th he first param meter of the method spe ecifies the typ pe you want to o extend. By p preceding the e parameter w with the this k keyword, you indicate to the e compiler tha at your metho od is an exten nsion method to that type. The following ex xample shows s how to creat te an extensio on method for the System. .String type: Creating an Extension Meth hod
n namespace Fou urthExtensio onMethods; { public sta atic class F FourthCoffee eExtensions { public static bool l ContainsNu umbers(this String S s) { // U Use regular expressions s to determin ne whether t the string c contains any n numerical dig gits. retu urn Regex.Is sMatch(s, @"\d"); } } }

To o use an exten nsion method, you must exp plicitly import t the namespa ace that conta ains your exte ension me ethod by using a using dire ective: Br ringing an Ex xtension Method Into Sco ope
u using FourthE ExtensionMet thods;

Yo ou can then ca all the extensio on method as s if it was an in nstance method on the typ pe that it extends:

Programming in Visual C# 5-27

Calling an Extension Method


Console.WriteLine("Please type some text that contains numbers and then press Enter"); string text = Console.ReadLine(); if(text.ContainsNumbers) { Console.WriteLine("Your text contains numbers. Well done!"); } else { Console.WriteLine("Your text does not contain numbers. Please try again."); }

5-28 Creating g a Class Hierarchy by Using Inheritanc ce

Demonstration: Refa actoring C Common Functiona ality into t the User C Class Lab

In this demonstration, you wi ill learn about t the tasks tha at you will per rform in the la ab for this mo odule.

Programming in i Visual C#

5-29 9

Lab: Refacto oring Commo C n Functionalit ty into the Use er s Class

S Scenario
You have noti Y iced that the Student and T Teacher classe es in the Grad des application n contain som me duplicated To make the application m f functionality. more maintainable, you dec cide to refacto or this commo on f functionality t to remove the e duplication. You are also c Y concerned abo out security. T Teachers and students all re equire a passw word, but it is s important to o m maintain conf fidentiality and at the same e time ensure that students s (who are children) do not have to r remember lon ng and compl lex passwords s. You decide t to implement t different pas ssword policie es for teachers s a students; teachers' pas and sswords must be stronger and a more diffi icult to guess than student passwords. Also, you have A e been asked to update the e application to limit the number of stud dents that can n be added to o a class. You de ecide to add c code that thro ows a custom exception if a user tries to o enroll a student in a class t that is already y at capacity.

O Objectives
A After complet ting this lab, you y will be able to: Use inher ritance to fact tor common f functionality in nto a base cla ass. Implemen nt polymorph hism by using an abstract method. m Create a c custom excep ption class.

E Estimated Tim me: 60 minutes Virtual Machine: 20483 3A-SEA-DEV11-05, MSL-TM MG1 User Nam me: Student Password d: Pa$$w0rd

5-30

Creating a Class Hierarchy by Using Inheritance

Exercise 1: Creating and Inheriting from the User Base Class


Scenario
In this exercise, you will create an abstract base class called User that contains the UserName and Password properties, and the VerifyPassword method that is common to the Student and Teacher classes. You will modify the definitions of the Student and Teacher classes to inherit from the User class, and remove the UserName and Password properties and the VerifyPassword method from these classes. Finally, you will build and run the application without making any other changes to the application, and then verify that it still works correctly. The main tasks for this exercise are as follows: 1. Create the User abstract base class 2. Modify the Student and Teacher classes to inherit from the User class 3. Run the application and test the log on functionality

X Task 1: Create the User abstract base class


1. 2. 3. 4. 5. 6. Start the MSL-TMG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-05 virtual machine and log on as Student with the password Pa$$word. Start Visual Studio and open the GradesPrototype.sln solution from the E:\Labfiles\Starter\Exercise 1 folder. In the Grade.cs file in the Data folder, create a new abstract class called User. Add the UserName and Password properties to the User class. Add the VerifyPassword method to the User class.

Note: Copy the code for the UserName and Password properties and the VerifyPassword method from either the Student class or the Teacher class. You must also add the private _password field to the UserName class; this field provides the storage for the Password property.

X Task 2: Modify the Student and Teacher classes to inherit from the User class
1. In the Grade.cs file, modify the Student class to inherit from the User class. Remove the UserName and Password properties, and the private _password field. Also remove the VerifyPassword method from the Student class. Modify the Teacher class to inherit from the User class. Remove the UserName and Password properties, and the private _password field. Also remove the VerifyPassword method from the Teacher class.

2.

X Task 3: Run the application and test the log on functionality


1. 2. 3. 4. Build the solution and resolve any compilation errors. Run the application. Log on as vallee (a teacher) with a password of password. Verify that a list of students for this teacher appears in The School of Fine Arts window.

Programming in Visual C# 5-31

5. 6. 7. 8. 9.

Select student Kevin Liu and verify that the report card listing the grades for this student appears. Log off and then log on as liuk (a student) with a password of password. Verify that the report card for Kevin Liu is displayed again. Log off and then close the application In Visual Studio, close the solution.

Results: After completing this exercise, you should have removed the duplicated code from the Student and Teacher classes, and moved the code to an abstract base class called User.

5-32

Creating a Class Hierarchy by Using Inheritance

Exercise 2: Implementing Password Complexity by Using an Abstract Method


Scenario
In this exercise, you will add an abstract method called SetPassword to the User class. In the Teacher and Student classes you will implement the SetPassword method. This method will set the password for the user (either a teacher or a student). The SetPassword method for a teacher will check that the password is at least eight characters long and contains at least two numeric characters. The SetPassword method for a student will check that the password is at least six characters long. If the password meets these requirements, it is set and the method will return true, otherwise it will return false. You will then modify the set accessor of the Password property in the User class to call the SetPassword method to change the user's password. Next, you will integrate this feature into the user interface of the application to enable a user to change their password. Finally, you will build and run the application to test the password functionality. The main tasks for this exercise are as follows: 1. Define the SetPassword abstract method 2. Implement the SetPassword method in the Student and Teacher classes 3. Set the password for a new student 4. Change the password for an existing user 5. Run the application and test the change password functionality

X Task 1: Define the SetPassword abstract method


1. 2. In Visual Studio, open the GradesPrototype.sln solution from the E:\Labfiles\Starter\Exercise 2 folder. In the User class, define a public abstract method called SetPassword. This method should take a string parameter containing the password and return a Boolean value indicating whether the password has been set successfully. In the User class, modify the set accessor of the Password property to call the SetPassword method rather than directly writing to the _password field. Throw an ArgumentException exception if the SetPassword method returns false.

3.

X Task 2: Implement the SetPassword method in the Student and Teacher classes
1. 2. In the User class, make the _password field protected rather than private; it needs to be accessible in the Student and Teacher classes. In the Student class, implement the SetPassword method. The method should verify that the password specified as the parameter is at least six characters long. If the password is of sufficient length, then populate the _password field and return true; otherwise, return false. In the Teacher class, implement the SetPassword method. The method should verify that the password specified as the parameter is at least eight characters long and contains at least two numeric characters. If the password is of sufficient complexity, then populate the _password field and return true; otherwise, return false.

3.

Note: You will need to use the following regular expression to verify the validity of the password:

Programming in Visual C# 5-33

Match numericMatch = Regex.Match(pwd, @".*[0-9]+.*[0-9]+.*");

X Task 3: Set the password for a new student


1. 2. In the code for the StudentsPage view, locate the NewStudent_Click method. This method runs when a teacher creates a new student. In this method, modify the statement that sets the password for the new student to call the SetPassword method. If the password is not sufficiently complex and the method returns false, throw an Exception with a suitable error message.

Note: If you were happy with the default exception thrown by using the Password property, you could retain the code as is. However, in this case you have decided to throw a different exception with a more meaningful and less generic error message, so you chose to call the SetPassword method directly.

X Task 4: Change the password for an existing user


1. 2. Build the solution. In the XAML definition of the MainWindow window, find the definition of the Change Password button. When the application runs, this button appears at the top of the page. If the user clicks this button, the ChangePassword_Click method runs. In the MainWindow.xaml.cs file, review the ChangePassword_Click method. This method displays a dialog called ChangePasswordDialog that enables a user to change their password. In the Controls folder, review the ChangePasswordDialog.xaml window. This window contains three text boxes that prompt the user to provide their old password, enter a new password, and confirm the new password. When the user clicks OK the new password is set. The ChangePasswordDialog window looks like this:

3. 4.

FIGURE 5.1: THE CHANGEPASSWORDDIALOG WINDOW 5. 6. Examine the code in the ok_Click method in the ChangePassword.xaml.cs file. This method runs when the user clicks OK in the Change Password dialog box. Currently, this method does nothing. Implement the logic for the ok_Click method: a. Get the details for the current user.

5-34

Creating a Class Hierarchy by Using Inheritance

Note: You can use the SessionContext.UserRole property to determine if the current user is a teacher or a student and then use either the CurrentTeacher property or CurrentStudent property of the SessionContext object to access the user details. b. Verify that the old password specified in the dialog is correct by using the VerifyPassword method of the User class. If the password is incorrect, display a message and return from the method without changing the password. Verify that the new password and confirm password text boxes in the dialog contain the same value. If they are different, display a message and return from the method without changing the password. Set the password by using the SetPassword method of the current user. If this method returns false, display a message and return without changing the password.

c.

d.

X Task 5: Run the application and test the change password functionality
1. 2. 3. Build the solution and resolve any compilation errors. Run the application. Log on as vallee (a teacher) with a password of password99.

Note: The passwords for all teachers have changed to password99 to ensure that they meet the complexity requirements. The password for all students is still password. 4. 5. 6. 7. 8. Change the password for the current user. First try setting it to a password that is insufficiently complex, and then change it to password101. Log out and then log back in again as vallee, and verify that the password has been changed to password101. Create a new student and verify that the student password must be at least six characters long. Use the Enroll Student feature to verify that the student is successfully created. Log off and then close the application. In Visual Studio, close the solution.

Results: After completing this exercise, you should have implemented a polymorphic method named SetPassword that exhibits different behavior for students and teachers. You will also have modified the application to enable users to change their passwords.

Programming in Visual C# 5-35

Exercise 3: Creating the ClassFullException Custom Exception


Scenario
In this exercise, you will create a new custom exception class called ClassFullException. You will modify the EnrollInClass method of the Teacher class to raise this exception if too many students are added to a teacher's class. You will update the application to catch this exception, and then you will build and run the application to test this feature. The main tasks for this exercise are as follows: 1. Implement the ClassFullException class 2. Throw and catch the ClassFullException 3. Build and test the solution

X Task 1: Implement the ClassFullException class


1. 2. 3. In Visual Studio, open the GradesPrototype.sln solution from the E:\Labfiles\Starter\Exercise 3 folder. Review the ClassFullException class in the Services folder. Notice that the class inherits from the Exception class, but most of the functionality has yet to be defined. Add a private string field called _className and a public virtual read-only string property called ClassName to the ClassFullException class. This property should return the value in the _className field. The _className field will hold the name of the class that is full when the exception is raised. Add a default public constructor to the ClassFullException class. This constructor should simply delegate its responsibilities to the equivalent constructor in the Exception class. Add a public constructor to the ClassFullException class that takes a string parameter containing the exception message. This constructor should also delegate its functionality to the equivalent constructor in the Exception class. Add a public constructor to the ClassFullException that takes a string parameter holding the exception message and an Exception object containing an inner exception. Like the previous constructors, this constructor should delegate its functionality to the equivalent constructor in the Exception class. Add a public custom constructor that takes the exception message and the name of the class that is full as parameters. Invoke the Exception constructor with the exception message, but store the name of the class in the _className field. Add a public custom constructor that takes the exception message, the name of the class that is full, and an Exception object containing an inner exception as parameters. Invoke the Exception constructor with the exception message and the inner exception, but store the name of the class in the _className field.

4. 5.

6.

7.

8.

X Task 2: Throw and catch the ClassFullException


1. 2. In the Teacher class, add a private constant integer field called MAX_CLASS_SIZE and initialize it with the value 8. This field specifies the maximum class size for a teacher. In the EnrollInClass method of the Teacher class, if the current number of students is already equal to the value in MAX_CLASS_SIZE, then throw a ClassFullException with a suitable message and the name of the class that is full (the name of the class is available in the Class property of the Teacher). Students are enrolled in a class by using the AssignStudentDialog window. Open the AssignStudentDialog.xaml.cs file and review the code in the Student_Click method. This method

3.

5-36

Creating a Class Hierarchy by Using Inheritance

runs when the user selects a student to add to a class. Notice that the try block in this method includes the following statement:
SessionContext.CurrentTeacher.EnrollInClass(student);

4.

Add a catch handler after the try block that catches the ClassFullException. In this catch handler, display a suitable message that includes the exception message and class name from the exception.

X Task 3: Build and test the solution


1. 2. 3. 4. 5. 6. 7. Build the solution and resolve any compilation errors. Run the application. Log on as vallee (a teacher) with a password of password99. Create four new students. Try to enroll all four students in the class for Esther Valle; this teacher currently has five students, so attempting to add the final student should fail with a ClassFullException exception. Log off and then close the application. In Visual Studio, close the solution.

Results: After completing this exercise, you should have created a new custom exception class and used it to report when too many students are enrolled in a class.

Programming in i Visual C#

5-37 7

Module Rev view an nd Take eaways

M Module Rev view


In this module I e, you have le earned how to o use inheritan nce and exten nsion methods to extend th he f functionality o of existing typ pes. T Test Your Kno owledge Question Which of the following types t of meth hod must you u implement i in derived cla asses? Select the correct answer r. Abst tract methods s. Prot tected method ds. Public methods. Static methods. Virtu ual methods. T Test Your Kno owledge Question You want to o create an ex xtension meth hod for the St tring class. Yo ou create a st tatic method within a stat tic class. How w do you indic cate that your method ext tends the Stri ing type? Select the correct answer r. The return type o of the method d must be a St tring.

5-38

Creating a Class Hierarchy by Using Inheritance

Question The first parameter of the method must be a String. The class must inherit from the String class. The method declaration must include String as a type argument. The method declaration must be preceded by String.

6-1

Module 6
Reading and Writing Local Data
Contents:
Module Overview Lesson 1: Reading and Writing Files Lesson 2: Serializing and Deserializing Data Lesson 3: Performing I/O by Using Streams Lab: Generating the Grades Report Module Review and Takeaways 6-2 6-3 6-17 6-33 6-44 6-50

6-2

Reading a and Writing Local D Data

Modu ule Ove erview

Re eading and wr riting data are e core requirements for many application ns, such as a t text file editor r saving a file e to the file sy ystem, or a Wi indows service e writing erro or messages to o a custom log g file. The local file sys stem provides s the perfect e environment for f an applica ation to read a and write such h data, becaus se access is fas st and the loca ation is readily available. Th he Microsoft .NET . Framewo ork provides a variety of I/O O classes tha at simplify the e process of im mplementing I/O functiona ality in your ap pplications. In this module, y you will learn how to read and write dat ta by using atomic file syste em I/O operat tions, how to serialize and deserialize da stem by ata to the file system, and h how to read and write data a to the file sys usi ing streams.

Ob bjectives
Aft ter completing this module e, you will be able to: write data to a and from the f file system by using file I/O O. Read and w Convert dat ta into a form mat that can be e written to o or read from a file or other data source. Use streams s to send and receive data to or from a file f or data so ource

Programming g in Visual C#

6-3 3

Lesson 1

Read ding and d Writing File es

The .NET Fram T mework provid des the Syste em.IO namesp pace, which co ontains a num mber of classes s that help s simplify applic cations that re equire I/O fun nctionality. In this lesson, you will learn I n how to use the t classes in this namespace to read and write data t to and from f files, and to manipulate m file es and directo ories on the file system.

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Read and d write data by y using the File class. Manipula ate files by using the FileInf fo and the Fil le classes. Manipula ate directories s by using the DirectoryInf fo and Direct tory classes. Manipula ate file and dir rectory paths by using the Path class.

6-4

Reading a and Writing Local D Data

Re eading an nd Writing g Data by Using the e File Class s

The File class in n the System.IO namespace e exposes sev veral static me ethods that yo ou can use to perform ato omic operatio ons for direct reading and w writing of files s. These metho ods are atomic because the ey wrap sev veral underlying functions into a single m method call. T Typically, to re ead data from m a file, you: 1. 2. 3. 4. e file handle. Acquire the Open a stre eam to the file e. Buffer the d data from the file into mem mory. Release the e file handle so o that it can b be reused.

ods that the F File class expo oses are conve enient becaus se they encaps sulate intricat te, low-level The static metho nctions. Howe ever their convenience and the fact that they shield th he developer from the underlying fun fun nctionality me eans in some cases they do ont offer the c control or flex xibility that ap pplications req quire. For exa ample, the Re eadAllText m method will rea ad the entire c contents of a file into mem mory. For smal ll files this will be fine, but for large files s it can presen nt scalability is ssues, and ma ay result in an unresponsive e UI in your ap pplication.

Re eading Data a from Files


The File class pr rovides severa al methods that you can us se to read data a from a file. T The format of f your data and how your application int tends to proce ess it will influ uence the met thod that you should use. T The fol llowing list de escribes some of these methods: The ReadA AllText metho od enables you u to read the contents of a file into a single string variable. The following co ode example shows how to o read the con ntents of the settings.txt s file e into a string g named settings. string fileP Path = "C:\\fo ourthCoffee\\s settings.txt";
string se ettings = File.ReadAllText(filePath h);

The ReadA AllLines metho od enables yo ou to read the e contents of a file and store each line at a new index in a string array. Th he following c code example e shows how t to read the co ontents of the settings.txt file and store each line in n the string ar rray named se ettingsLineBy yLine.
string fi ilePath = "C C:\\fourthCoff fee\\settings s.txt"; string[] settingsLin neByLine = File.ReadAllL Lines(filePa ath);

Programming in Visual C# 6-5

The ReadAllBytes method enables you to read the contents of a file as binary data and store the data in a byte array. The following code example shows how to read the contents of the settings.txt file into a byte array named rawSettings.
string filePath = "C:\\fourthCoffee\\settings.txt"; byte[] rawSettings = File.ReadAllBytes(filePath);

Each of these methods enables you to read the contents of a file into memory. You could use the ReadAllText method if you wanted to cache the entire file in memory in a single operation. Alternatively, if you wanted to process a file line-by-line, you could use the ReadAllLines method to read each line into an array.

Writing Data to Files


The File class also provides methods that you can use to write different types of data to a file. For each of the different types of data you can write, the File class provides two methods: If the specified file does not exist, the Writexxx methods create a new file with the new data. If the file does exist, the Writexxx methods overwrite the existing file with the new data. If the specified file does not exist, the Appendxxx methods also create a new file with the new data. However, if the file does exist, the new data is written to the end of the existing file.

The following list describes some of these methods: The WriteAllText method enables you to write the contents of a string variable to a file. If the file exists, its contents will be overwritten. The following code example shows how to write the contents of a string named settings to a new file named settings.txt.
string filePath = "C:\\fourthCoffee\\settings.txt"; string settings = "companyName=fourth coffee;"; File.WriteAllText(filePath, settings);

The WriteAllLines method enables you to write the contents of a string array to a file. Each entry in the string array represents a new line in the file. The following code example shows how to write the contents of a string array named hosts to a new file named hosts.txt.
string filePath = "C:\\fourthCoffee\\hosts.txt "; string[] hosts = { "86.120.1.203", "113.45.80.31", "168.195.23.29" }; File.WriteAllLines(filePath, hosts);

The WriteAllBytes method enables you to write the contents of a byte array to a binary file. The following code example shows how to write the contents of a byte array named rawSettings to a new file named settings.txt.
string filePath = "C:\\fourthCoffee\\setting.txt "; byte[] rawSettings = {99,111,109,112,97,110,121,78,97,109,101,61,102,111, 117,114,116,104,32,99,111,102,102,101,101}; File.WriteAllBytes(filePath, rawSettings);

The AppendAllText method enables you to write the contents of a string variable to the end of an existing file. The following code example shows how to write the contents of a string variable named settings to the end of the existing settings.txt file.
string filePath = "C:\\fourthCoffee\\settings.txt"; string settings = "companyContact= Dean Halstead"; File.AppendAllText(filePath, settings);

6-6

Reading and Writing Local Data

The AppendAllLines method enables you to write the contents of a string array to the end of an existing file. The following code example shows how to write the contents of a string array named newHosts to the existing hosts.txt file.
string filePath = "C:\\fourthCoffee\\hosts.txt "; string[] newHosts = { "97.11.1.195", "203.194.40.177" }; File.WriteAllLines(filePath, newHosts);

Each of these methods enables you to write data to a file. If you want to add data to an existing file that may already exist, then you should use an Appendxxx method. If you want to overwrite an existing file, then you should use a Writexxx method. Then, depending on how you want the information is stored (whether as binary data, a textual blob in a string, or an array of strings representing each individual line) use the xxxAllBytes, xxxAllText, or xxxAllLines method.

Programming g in Visual C#

6-7 7

M Manipulat ting Files

As well as reading from and A d writing to fi iles, applicatio ons typically re equire the ability to interac ct with files s stored on the file system. F For example, your y applicatio on may need to copy a file e from the syst tem directory y t a temporar to ry location be efore performi ing some further processing, or your app plication may y need to read d s some metadata associated with the file, such as the file creation tim me. You can im mplement this type of f functionality b by using the F File and FileIn nfo classes.

F Manipu File ulation by using u the F File Class


The File class provides static methods th T hat you can us se to perform basic file manipulation. Th he following l describes s list some of these e methods: The Copy y method ena ables you to co opy an existin ng file to a dif fferent directo ory on the file system. The following g code example shows how w to copy the s settings.txt file e from the C:\ \fourthCoffee\ \ directory to the C:\tem mp\ directory y.
string sourceSettingsPath = "C C:\\fourthCo offee\\settings.txt"; string destinationSettingsPath h = "C:\\tem mp\\settings.txt"; bool ov verWrite = true; File.Co opy(sourceSettingsPath, destination nSettingsPath, overWrite e);

Note: T The overwrite parameter pa assed to the Copy C method call indicates that the copy y process should overwrite an existing file if it exists at t p the destinatio on path. If you u pass false to o the C Copy method d call, and the e file already e exists, the Com mmon Langua age Runtime ( (CLR) will thro ow a S System.IO.IO OException. The Delete method en nables you to delete an exis sting file from m the file syste em. The follow wing code example shows how to o delete the ex xisting setting gs.txt file.
string filePath = "C:\\fourthC Coffee\\sett tings.txt"; File.De elete(filePath);

The Exist ts method ena ables you to c check whether a file exists o on the file system. The follo owing code example shows how to o check wheth her the setting gs.txt file exist ts.
string filePath = "C:\\fourthC Coffee\\sett tings.txt";

6-8

Reading and Writing Local Data

bool persistedSettingsExist = File.Exists(filePath);

The GetCreationTime method enables you to read the date time stamp that describes when a file was created, from the metadata associated with the file. The following code example shows how you can determine when the settings.txt file was created.
string filePath = "C:\\fourthCoffee\\settings.txt"; DateTime settingsCreatedOn = File.GetCreationTime(filePath);

There are many other operations and metadata associated with files that you can utilize in your applications. The FileInfo class provides access to these through a number of instance members.

File Manipulation by using the FileInfo class


The FileInfo class provides instance members that you can use to manipulate an existing file. In contrast to the File class that provides static methods for direct manipulation, the FileInfo class behaves like an inmemory representation of the physical file, exposing metadata associated with the file through properties, and exposing operations through methods. The following code example shows how to create an instance of the FileInfo class that represents the settings.txt file. Instantiating the FileInfo Class
string filePath = "C:\\fourthCoffee\\settings.txt"; FileInfo settings = new FileInfo(filePath);

After you have created an instance of the FileInfo class, you can use the properties and methods that it exposes to interact with the file. The following list describes some of these properties and methods: The CopyTo method enables you to copy an existing file to a different directory on the file system. The following code example shows how to copy the settings.txt file from the C:\fourthCoffee\ directory to the C:\temp\ directory.
string sourceSettingsPath = "C:\\fourthCoffee\\settings.txt"; string destinationSettingsPath = "C:\\temp\\settings.txt"; bool overwrite = true; FileInfo settings = new FileInfo(sourceSettingsPath); settings.CopyTo(destinationSettingsPath, overwrite);

Note: The overwrite parameter passed to the CopyTo method call indicates that the copy process should overwrite an existing file if it exists at the destination path. If you pass false to the CopyTo method call, and the file already exists, the CLR will throw a System.IO.IOException. The Delete method enables you to delete a file. The following code example shows how to delete the settings.txt file.
string filePath = "C:\\fourthCoffee\\settings.txt"; FileInfo settings = new FileInfo(filePath); settings.Delete();

The DirectoryName property enables you to get the directory path to the file. The following code example shows how to get the path to the settings.txt file.
string filePath = "C:\\fourthCoffee\\settings.txt"; FileInfo settings = new FileInfo(filePath); string directoryPath = settings.DirectoryName; // returns C:\\fourthCoffee

Programming in Visual C# 6-9

The Exists method enables you to determine if the file exists within the file system. The following code example shows how to check whether the settings.txt file exists.
string filePath = "C:\\fourthCoffee\\settings.txt"; FileInfo settings = new FileInfo(filePath); bool persistedSettingsExist = settings.Exists;

The Extension property enables you to get the file extension of a file. The following code example shows how to get the extension of a path returned from a method call.
string filePath = FourthCoffeeDataService.GetDataPath(); FileInfo settings = new FileInfo(filePath); string extension = settings.Extension;

The Length property enables you to get the length of the file in bytes. The following code example shows how to get the length of the settings.txt file.
string filePath = "C:\\fourthCoffee\\settings.txt"; FileInfo settings = new FileInfo(filePath); long length = settings.Length;

6-10 Reading g and Writing Local Data

M Manipulati ng Directo ories

It i is a common requirement for f applications to interact and manipula ate the file system director ry structure, wh hether to chec ck that a direc ctory exists be efore writing a file or to rem move director ries when runn ning a sys stem cleanup process. The .NET Framew work class libra ary provides th he Directory and Director ryInfo cla asses for such operations.

Manipulating g Directorie es by using g the Direct tory Class


Sim milar to the Fi ile class, the Directory D clas ss provides sta atic methods t that enable yo ou to interact t with dir rectories, with hout instantiat ting a directory-related obj ject in your co ode. The following list desc cribes some of these static m methods: The CreateDirectory me ethod enables s you to create a new direc ctory on the file system. The e following example shows how to create the C:\f fourthCoffee\t tempData dire ectory.
string di irectoryPath h = "C:\\fourthCoffee\\t tempData"; Directory y.CreateDire ectory(directoryPath);

The Delete method enab bles you to de elete a directo ory at a specif fic path. The fo ollowing code e example shows how to delete the C:\fourthCof ffee\tempData a directory, an nd all its conte ents.
string di irectoryPath h = "C:\\fourthCoffee\\t tempData"; bool recu ursivelyDele eteSubContent = true; Directory y.Delete(dir rectoryPath, recursively yDeleteSubCo ontent);

Note: The e recursivelyD DeleteSubCo ontent parame eter passed in nto the Delete e method call l ind dicates whether the delete process should delete any content that may exist in t the directory. If you pass false into the Delet te method cal ll, and the dire ectory is not e empty, the CL LR will throw a Sy ystem.IO.IOEx xception. The Exists method m enables you to det termine if a directory exists s on the file sy ystem. The fol llowing code examp ple shows how w to determin ne if the C:\fou urthCoffee\tempData direc ctory exists.
string di irectoryPath h = "C:\\fourthCoffee\\t tempData"; bool temp pDataDirecto oryExists = Directory.Ex xists(direct toryPath);

Programming in Visual C# 6-11

The GetDirectories method enables you to get a list of all subdirectories within a specific directory on the file system. The following code example shows how to get a list of all the sub directories in the C:\fourthCoffee\tempData directory.
string directoryPath = "C:\\fourthCoffee\\tempData"; string[] subDirectories = Directory.GetDirectories(directoryPath);

The GetFiles method enables you to get a list of all the files within a specific directory on the file system. The following example shows how to get a list of all the files in the C:\fourthCoffee\tempData directory.
string directoryPath = "C:\\fourthCoffee\\tempData"; string[] files = Directory.GetFiles(directoryPath);

The DirectoryInfo class provides instance members that enable you to access directory metadata and manipulate the directory structure.

Manipulating Directories by using the DirectoryInfo Class


The DirectoryInfo class acts as an in-memory representation of a directory. Before you can access the properties and execute the methods that the DirectoryInfo class exposes, you must create an instance of the class. The following code example shows how to create an instance of the DirectoryInfo class that represents the C:\\fourthCoffee\\tempData directory. Instantiating the DirectoryInfo Class
string directoryPath = "C:\\fourthCoffee\\tempData"; DirectoryInfo directory = new DirectoryInfo(directoryPath);

When you have created an instance of the DirectoryInfo class, you can then use its properties and methods to interact with the directory. The following list describes some of these properties and methods: The Create method enables you to create a new directory on the file system. The following example shows how to create the C:\fourthCoffee\tempData directory.
string directoryPath = "C:\\fourthCoffee\\tempData"; DirectoryInfo directory = new DirectoryInfo(directoryPath); directory.Create();

The Delete method enables you to delete a directory at a specific path. The following code example shows how to delete the C:\fourthCoffee\tempData directory, and all its contents.
string directoryPath = "C:\\fourthCoffee\\tempData"; bool recursivelyDeleteSubContent = true; DirectoryInfo directory = new DirectoryInfo(directoryPath); directory.Delete(recursivelyDeleteSubContent);

Note: The recursivelyDeleteSubContent parameter passed to the Delete method call indicates whether the delete process should delete any content that may exist in the directory. If you pass false to the Delete method call, and the directory is not empty, the CLR will throw a System.IO.IOException. The Exists property enables you to determine if a directory exists on the file system. The following code example shows how to determine if the C:\fourthCoffee\tempData directory exists.
string directoryPath = "C:\\fourthCoffee\\tempData";

6-12

Reading and Writing Local Data

DirectoryInfo directory = new DirectoryInfo(directoryPath); bool tempDataDirectoryExists = directory.Exists;

The FullName property enables you to get the full path to the directory. The following example shows how to get the full path to the tempData directory.
string directoryPath = "C:\\fourthCoffee\\tempData"; DirectoryInfo directory = new DirectoryInfo(directoryPath); string fullPath = directory.FullName;

The GetDirectories method enables you to get a list of all subdirectories within a specific directory on the file system. In contrast to the static File.GetDirectories method, this instance method returns an array of type DirectoryInfo, which enables you to use each of the instance properties for each subdirectory. The following code example shows how to get all of the sub directories in the C:\fourthCoffee\tempData directory.
string directoryPath = "C:\\fourthCoffee\\tempData"; DirectoryInfo directory = new DirectoryInfo(directoryPath); DirectoryInfo[] subDirectories = directory.GetDirectories();

The GetFiles method enables you to get a list of all the files within a specific directory on the file system. In contrast to the static File.GetFiles method, this instance method returns an array of type FileInfo, which enables you to use each of the instance properties for each file. The following example shows how to get all of the files in the C:\fourthCoffee\tempData directory.
string directoryPath = "C:\\fourthCoffee\\tempData"; DirectoryInfo directory = new DirectoryInfo(directoryPath); FileInfo[] subFiles = directory.GetFiles();

Depending on whether you require a simple one-line-of-code approach to manipulate a directory, or something that offers slightly more flexibility, either the static Directory or instance DirectoryInfo class should fulfill your requirements.

Programming in i Visual C#

6-13 3

M Manipulat ting File a and Direct tory Paths s

All files and all directories h A have a name, which when c combined to p point to a file in a directory y, constitute a p path. Differen nt file systems can have diff ferent conventions and rule es for what co onstitutes a pa ath. The .NET F Framework pr rovides the Pa ath class, whic ch encapsulat tes a variety o of file system u utility function ns that you c use to parse and construct valid file names, direct can tory names, and paths with hin the Windo ows file s system. These e functions can n be useful if your application needs to w write a file to a temporary location, e extract an element from a f file system pa ath, or even ge enerate a rand dom file name. T following code shows how to create The e a new direct tory on the root of the C: drive. C Creating a Te emporary Dir rectory the H Hard Way
string temp pDirectoryPa ath = "C:\\fourthCoffee\ \\tempData"; if (!Direct tory.Exists( (tempDirectoryPath)) Directo ory.CreateDirectory(tempDirectoryPa ath);

However, with H h the above approach, you are making m many assumpt tions, includin ng whether yo our a application ha as the necessa ary privileges to perform I/O O at the root of the C drive e, and whethe er the C drive a actually exists s. A better way is to use the s static GetTem mpPath metho od provided by b the Path class to get the e path to the c current users Windows tem mporary directory. G Getting the P Path to the W Windows Tem mporary Directory
string temp pDirectoryPa ath = Path.GetTempPath() );

The Path class includes ma T any other stati ic methods th hat provide a good g starting point for any y custom I/O t type functiona ality that your application may require. These T method ds include the e following: The HasE Extension me ethod enables you to determine if the pa ath your appli ication is proc cessing has an n extension n. This provide es a convenien nt way for you u to determin ne if you are p processing a file or a directory. . The following example shows how to c check whether r the path has s an extension n.
string settingsPath = "..coul ld be anything here.."; bool ha asExtension = Path.HasEx xtension(set ttingsPath);

6-14

Reading and Writing Local Data

The GetExtension method enables you to get the extension from a file name. This method is particularly useful when you want to ascertain what type of file your application is processing. The following code example shows how to check whether the settingsPath variable contains a path that ends with the .txt extension.
string settingsPath = "..could be anything here.."; string pathExt = Path.GetExtension(settingsPath); if (pathExt == ".txt") { // More processing here. }

The GetTempFileName enables you to create a new temp file in your local Windows temporary directory in a single atomic operation folder. This method then returns the absolute path to that file, ready for further processing. The following code shows how to invoke the GetTempFileName method.
string tempPath = Path.GetTempFileName(); // Returns C:\Users\LeonidsP\AppData\Local\Temp\tmp1C79.tmp

Additional Reading: For more information about the Path class, see the Path Class page at http://go.microsoft.com/fwlink/?LinkID=267805.

Programming in i Visual C#

6-15 5

D Demonstr ration: Manipulatin ng Files, D Directories s, and Paths

In this demon I nstration, you will use the File, Directory y, and Path classes to build d a utility that combines m multiple files into a single f file.

D Demonstra ation Steps


1 1. 2 2. 3 3. Start the MSL-TMG1 vi irtual machine e if it is not already running g. Start the 20483A-SEA-DEV11-06 vir rtual machine. . Log on to o Windows 8 as a Student with the passwo rd. ord Pa$$w0r Note: If f necessary, click Switch Us ser to display the list of use ers. 4 4. 5 5. 6 6. 7 7. 8 8. 9 9. Switch to the Windows s 8 Start wind dow. Open File e Explorer and d browse to th he E:\Democo ode\Data\Lo ogs folder. In the E:\Democode\D Data\Logs folder, double-click each of the e text files, an nd view the co ontents in Notepad. . Close Not tePad. Switch to the Windows s 8 Start wind dow. Click Visu ual Studio 201 12.

1 In Visual Studio, on the 10. e File menu, p point to Open n, and then click Project/Solution. 1 In the Op 11. pen Project dia alog box, brow wse to E:\Dem mocode\Starte er\FourthCoff fee.LogProcessor folder, click Four rthCoffee.LogProcessor.sln, , and then clic ck Open. 1 In Visual Studio, on the 12. e View menu, , click Task Li ist. 1 In the Tas 13. sk List windo ow, in the Cate egories list, click Commen nts. 1 Double-c 14. click the TODO O: 01: Ensure log file directo ory exists. task. 1 In the cod 15. de editor, click in the blank k line below th he comment, and then type e the followin ng code:
if (!Dir rectory.Exis sts(logDirectoryRoot))

6-16

Reading and Writing Local Data

throw new DirectoryNotFoundException();

16. In the Task List window, double-click the TODO: 02: Get all log file paths. task. 17. In the code editor, click in the blank line below the comment, and then type the following code:
return Directory.GetFiles(this._logDirectoryPath, "*.txt");

18. In the Task List window, double-click the TODO: 03: Check for existing combined log file and delete if it already exists. task. 19. In the code editor, click in the blank line below the comment, and then type the following code:
if (File.Exists(combinedLogPath)) File.Delete(combinedLogPath);

20. In the Task List window, double-click the TODO: 04: Write the heading to the combined log file. task. 21. In the code editor, click in the blank line below the comment, and then type the following code:
File.AppendAllLines(combinedLogPath, heading);

22. In the Task List window, double-click the TODO: 05: Get the log file name without the file extension. task. 23. In the code editor, click in the blank line below the comment, and then type the following code:
var logName = Path.GetFileNameWithoutExtension(logPath);

24. In the Task List window, double-click the TODO: Task 06: Read the contents of the existing log file. task. 25. In the code editor, click in the blank line below the comment, and then type the following code:
var logText = File.ReadAllText(logPath);

26. In the Task List window, double-click the TODO: Task 07: Write the log file contents to the combined log file. task. 27. In the code editor, click in the blank line below the comment, and then type the following code:
File.AppendAllLines(combinedLogPath, logContent);

28. On the Build menu, click Build Solution. 29. On the Debug menu, click Start Without Debugging. 30. In the Command Prompt window, when prompted to press any key to continue, press Enter. 31. Open File Explorer and browse to the E:\Democode\Data\Logs folder. 32. Double-click CombinedLog.txt, verify that the file contains a heading, and then verify the contents of each log file. 33. Close Notepad, close File Explorer, and then close Visual Studio.

Programming in i Visual C#

6-17 7

Lesson 2

Seria alizing a and Deserializing Dat ta

Serialization is S s the process of converting g data to a for rmat that can be persisted o or transported d. n is the proce D Deserializatio ess of converti ing serialized data back to objects. In this lesson, you will learn I n how to seria alize objects to o binary, XML L, and JavaScri ipt Object No otation ( (JSON), and h how to create a custom serializer so that you can seria alize objects in nto any forma at you choose.

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Describe the purpose o of serialization n, and the for rmats that the e .NET Framew work supports s. Create a c custom type t that is serializa able. Serialize a an object as b binary. Serialize a an object as X XML. Serialize a an object as JSON. Create a c custom seriali izer by implem menting the IFormatter interface.

6-18 Reading g and Writing Local Data

W What Is Ser rialization?

Ap pplications typ pically process s data. Data is s read into me emory, perhap ps from a file or web service call, pro ocessed, and then passed t to another component in th he system for further proce essing. The co omponents of a system may y run on the same s machine e, but commonly components run on dif fferent platfor rms, on dif fferent hardwa are, and even n in different geographical g l locations. The e format of the data also ne eeds to be lightweight so that it can be transported o over a variety of protocols, such as HTTP or SOAP. Ser rialization is the e process of c converting the e state of an o object into a form that can be persisted o or transported d.

Se erializable F Formats
The requiremen nts of your sys stem, and how w you intend to t transport th he data, will in nfluence the serialization s for rmat you choo ose. The following table de escribes some of the comm mon formats av vailable. F Format B Binary Descript tion Serializing data into t the machine-readable bina ary format ena ables you to p preserve the an object betw ween different t instances of your applicat tion. Binary fidelity and state of a ation is also fa ast and lightw weight, becaus se the binary f format does n not require the e serializa processing and storage of unnecessary formatti ing constructs s. Binary s serialization is s commonly used when per rsisting and tr ransporting ob bjects betwee en applicat tions running on the same platform. Binary E Example
010002552552552551 100000001220 000727311010570105108101 183101114105 597108 105122101114443286 610111411510 051111106149464846484648 844326711710 081161 171141016111010111 171161149710 084432801179810810599751 101121841111 107101 110611101171081085 510003873110 010570105108101831011141 105971081051 122101 114468310111411810 059910167111 111010210510311711497116 610511111030 000106 711111010210510378 897109101166 689711697989711510172111 111511678971 109101 196511211210810599 997116105111 111068971169780971161041 111200063000 020701 111171141161046711 111021021011 101956810110297117108116 664000281009 971169 798971151015048574 461021111171 114116104991111021021011 101469911110 096500 032675892102111117 711411610499 911110210210110192971121 112108105999 971161 051111101009711697 79211

X XML

Serializing data into t the XML form mat enables yo ou to utilize an n open standa ard that can be b plication, rega ardless of plat tform. In cont trast to binary y, XML does not processed by any app e type fidelity y; it only lets you y serialize p public membe ers that your ty ype exposes. preserve

Programming in Visual C# 6-19

Format

Description The XML format is more verbose than binary, as the serialized data is formatted with XML constructs. This makes the XML format less efficient and more processor intensive during the serializing, deserializing, and transporting processes. XML serialization is commonly used to serialize data that can be transported via the SOAP protocol to and from web services. XML Example
<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP- ENV=http://schemas.xmlsoap.org/soap/envelope/ xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <a1:ServiceConfiguration id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/ FourthCoffeeSerializer/%2C%20Version%3D1.0.0.0%2C%20 Culture%3Dneutral%2C%20PublicKeyToken%3Dnull"> <ConfigName id="ref-3"> FourthCoffee_Default </ConfigName> <DatabaseHostName id="ref-4"> database209.fourthcoffee.com </DatabaseHostName> <ApplicationDataPath id="ref-5"> C:\fourthcoffee\applicationdata\ </ApplicationDataPath> </a1:ServiceConfiguration> </SOAP-ENV:Body> </SOAP-ENV:Envelope>

JSON

Serializing data into the JSON format enables you to utilize a lightweight, datainterchange format that is based on a subset of the JavaScript programming language. JSON is a simple text format that is human readable and also easy to parse by machine, irrespective of platform. JSON is commonly used to transport data between Asynchronous JavaScript and XML (AJAX) calls because unlike XML, you are not limited to just communicating within the same domain. JSON Example
{ "ConfigName":"FourthCoffee_Default", "DatabaseHostName":"database209.fourthcoffee.com", "ApplicationDataPath":"C:\\fourthcoffee\\applicationdata\\" }

Alternatively, if you want to serialize your data to a format that the .NET Framework does not natively support, you can implement your own custom serializer class.

6-20 Reading g and Writing Local Data

Cr reating a S Serializable Type

The .NET Frame ework provide es many classe es that are ser rializable. If yo ou want to cre eate your own n types that are e serializable, you need to e ensure that th he type definit tion incudes t the necessary configuration n and fun nctionality for r the serilalize er to consume e. The .NET Fra amework prov vides the Syst tem and Sy ystem.Runtim me.Serializatio on namespaces, which provide classes to o enable seria alization support. To o create a seria alizable type, perform the f following step ps: 1. Define a de efault construc ctor.
public cl lass Service eConfiguratio on { public c ServiceCon nfiguration() { ... . } }

2.

Decorate th he class with the t Serializab ble attribute p provided in the System nam mespace.
[Serializ zable] public cl lass Service eConfiguratio on { ... }

3.

Implement the ISerializa able interface e provided in t the System.R Runtime.Seria alization nam mespace. The GetObj jectData met thod enables you to extract t the data from your object t during the s serialization process.
[Serializ zable] public cl lass Service eConfiguratio on : ISerial lizable { ... public c void GetOb bjectData(SerializationI Info info, S StreamingContext context t) { ... . } }

Programming in Visual C# 6-21

4.

Define a deserialization constructor, which accepts SerializationInfo and StreamingContext objects as parameters. This constructor enables you to rehydrate your object during the deserialization process.
[Serializable] public class ServiceConfiguration : ISerializable { ... public ServiceConfiguration(SerializationInfo info, StreamingContext ctxt) { ... } }

5.

Define the public members that you want to serialize. You can instruct the serializer to ignore private fields by decorating them with the NonSerialized attribute.
... [NonSerialized] private Guid _internalId; public string ConfigName { get; set; } public string DatabaseHostName { get; set; } public string ApplicationDataPath { get; set; } ...

The following code example shows the complete ServiceConfiguration class, which is serializable by any of the .NET Framework IFormatter implementations. Serializable Type
[Serializable] public class ServiceConfiguration : ISerializable { [NonSerialized] private Guid _internalId; public string ConfigName { get; set; } public string DatabaseHostName { get; set; } public string ApplicationDataPath { get; set; } public ServiceConfiguration() { } public ServiceConfiguration(SerializationInfo info, StreamingContext ctxt) { this.ConfigName = info.GetValue("ConfigName", typeof(string)).ToString(); this.DatabaseHostName = info.GetValue("DatabaseHostName", typeof(string)).ToString(); this.ApplicationDataPath = info.GetValue("ApplicationDataPath", typeof(string)).ToString(); } public void GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue("ConfigName", this.ConfigName); info.AddValue("DatabaseHostName", this.DatabaseHostName); info.AddValue("ApplicationDataPath", this.ApplicationDataPath); } }

6-22 Reading g and Writing Local Data

Se erializing O Objects as s Binary

The .NET Frame ework provide es the BinaryF Formatter cla ass in the Sy ystem.Runtim me.Serializatio on.Formatters.Binary nam mespace, whic ch you can use to serialize a and de eserialize objec cts as binary. Note: The e BinaryForm matter and So oapFormatter r classes imple ement the IFo ormatter int terface. You ca an also implement the IFor rmatter inter rface to create e your own cu ustom serialize er.

Se erialize an Object O by Using U the BinaryForma atter Class


To o serialize an object o by using the BinaryF Formatter cla ass, perform the following steps: s 1. 2. 3. 4. Obtain a reference to the e object you w want to seriali ize. nstance of the e BinaryForm matter that yo ou want to use e to serialize y your type. Create an in Create a str ream that you u will use as a buffer to stor re the serialize ed data. Invoke the BinaryForma atter.Serialize e method, pas ssing in stream m that the ser rialized data will w be buffered to, and the obje ect you want t to serialize.

ode example shows how to o use the Bina aryFormatter r class to seria alize an object t as binary. The following co naryFormatter Serialize E Example Bin
/ // Create the e object you u want to se erialize. S ServiceConfig guration con nfig = ServiceConfigurat tion.Default t; / // Create the e formatter you want to o use to seri ialize the o object. I IFormatter fo ormatter = n new BinaryFo ormatter(); / // Create the e stream tha at the seria alized data will w be buff fered to. F FileStream bu uffer = File e.Create("C:\\fourthcoff fee\\config. .txt"); / // Invoke the e Serialize method. f formatter.Serialize(buff fer, config); / // Close the stream. b buffer.Close();

This example, se erializes the ServiceConfig guration object, and writes s the serialized d data to a file e. It is important to no ote that seriali ization doesn t just imply w writing data to o a file. Serializ zation is the p process of

Programming in Visual C# 6-23

transforming a type into another format, which you can then write to a file or database, or send over HTTP to a web service.

Deserialize an Object by Using the BinaryFormatter Class


Deserializing is the process of transforming your serialized object back into a format that your application can process. To deserialize an object by using the BinaryFormatter class, perform the following steps: 1. 2. 3. 4. Create an instance of the BinaryFormatter that you want to use to deserialize your type. Create a stream to read the serialized data. Invoke the BinaryFormatter.Deserialize method, passing in stream that contains the serialized data. Cast the result of the BinaryFormatter.Deserialize method call into the type of object that you are expecting.

The following code example shows how to use the BinaryFormatter class to deserialize binary data to an object. BinaryFormatter Deserialize Example
// Create the formatter you want to use to serialize the object. IFormatter formatter = new BinaryFormatter(); // Create the stream that the serialized data will be buffered too. FileStream buffer = File.OpenRead("C:\\fourthcoffee\\config.txt"); // Invoke the Deserialize method. ServiceConfiguration config = formatter.Deserialize(buffer) as ServiceConfiguration; // Close the stream. buffer.Close();

The above example reads the serialized binary data from a file, and then deserializes the binary into a ServiceConfiguration object. The process is the same for serializing and deserializing objects by using any formatters that implement the IFormatter interface. This includes the SoapFormatter class, and any custom formatters that you may implement.

6-24 Reading g and Writing Local Data

Se erializing O Objects as s XML

The .NET Frame ework provide es the SoapFo ormatter class s in the Sy ystem.Runtim me.Serializatio on.Formatters.Soap name espace, which h you can use to serialize an nd de eserialize objec cts as XML.

Se erialize an Object O by Using U the So oapFormat tter Class


The process for serializing da ata as XML is s similar to the process of ser rializing to bin nary, with the e exception tha at you use the e SoapForma atter class. The following co ode example shows how to o use the Soap pFormatter c class to serializ ze an object a as XML. So oapFormatter r Serialize Example
/ // Create the e object you u want to se erialize. S ServiceConfig guration con nfig = ServiceConfigurat tion.Default t; / // Create the e formatter you want to o use to seri ialize the o object. I IFormatter fo ormatter = n new SoapForm matter(); / // Create the e stream tha at the seria alized data will w be buff fered too. F FileStream bu uffer = File e.Create("C:\\fourthcoff fee\\config. .xml"); / // Invoke the e Serialize method. f formatter.Serialize(buff fer, config); / // Close the stream. b buffer.Close();

De eserialize an Object by y Using the e SoapForm matter Class s


The process for deserializing data from XM ML to an objec ct is identical to the proces ss of deserializ zing binary data, with the exception that you use the SoapFormatt S ter class. The following co ode example shows how to o use the Soap pFormatter c class to deseri ialize XML dat ta to an ob bject. So oapFormatter r Deserialize Example
/ // Create the e formatter you want to o use to seri ialize the o object. I IFormatter fo ormatter = n new SoapForm matter(); / // Create the e stream tha at the seria alized data will w be buff fered too. F FileStream bu uffer = File e.OpenRead("C:\\fourthco offee\\confi ig.xml"); / // Invoke the e Deserializ ze method. S ServiceConfig guration con nfig = forma atter.Deseria alize(buffer r) as Servic ceConfigurati ion;

Programming in Visual C# 6-25

// Close the stream. buffer.Close();

6-26 Reading g and Writing Local Data

Se erializing O Objects as s JSON

The .NET Frame ework also sup pports serializing objects as s JSON by usin ng the DataC ContractJsonS Serializer cla ass in the Syst tem.Runtime e.Serialization n.Json names space. The JSO ON serializatio on steps are d different be ecause the DataContractJs sonSerializer class is derive ed from the ab bstract XmlObjectSerialize er class, and it is not an implementati ion of the IFo ormatter inter rface.

Se erialize an Object O by Using U the DataContrac D ctJsonSerializer Class


To o serialize an object o by using the DataCo ontractJsonSe erializer class s, perform the e following ste eps: 1. 2. Obtain a reference to the e object that y you want to serialize. s nstance of the e DataContra actJsonSeriali t you want to use to serializ ze your Create an in izer class that type. The co onstructor also requires you to pass in a Type object, representing the type of o object you want to serialize. Create a str ream that you u will use as a buffer to stor re the serialize ed data. Invoke the DataContrac ctJsonSerializ zer.WriteObje ect method, p passing in stre eam that the s serialized data will be e buffered too o, and the obje ect you want to serialize.

3. 4.

The following co ode example shows how to o use the Data aContractJso onSerializer class c to serializ ze an ob bject as JSON. Da ataContractJs sonSerializer r Serialize Exa ample
/ // Create the e object you u want to se erialize. S ServiceConfig guration con nfig = ServiceConfigurat tion.Default t; / // Create a D DataContract tJsonSerializer object that t you wil ll use to se erialize the / // object to JSON. D DataContractJ JsonSerializ zer jsonSerializer = new Data aContractJso onSerializer r(config.GetT Type()); / // Create the e stream tha at the seria alized data will w be buff fered too. F FileStream bu uffer = File e.Create("C:\\fourthcoff fee\\config. .txt"); / // Invoke the e WriteObjec ct method. jsonSerialize er.WriteObje ect(buffer, config); / // Close the stream. b buffer.Close();

Programming in Visual C# 6-27

Deserialize an Object by using the DataContractJsonSerializer Class


To deserialize JSON to an object by using the DataContractJsonSerializer class, perform the following steps: 1. Create an instance of the DataContractJsonSerializer class that you want to use to serialize your type. The constructor also requires you to pass in a Type object, representing the type of object you want to deserialize. Create a stream that will read the serialized JSON into memory. Invoke the DataContractJsonSerializer.ReadObject method, passing in the stream that contains the serialized data. Cast the result of the DataContractJsonSerializer.ReadObject method call into the type of object you are expecting.

2. 3. 4.

The following code example shows how to use the DataContractJsonSerializer class to deserialize JSON data to an object. DataContractJsonSerializer Deserialize Example
// Create a DataContractJsonSerializer object that you will use to // deserialize the JSON. DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(ServiceConfiguration)); // Create a stream that will read the serialized data. FileStream buffer = File.OpenRead("C:\\fourthcoffee\\config.txt"); // Invoke the ReadObject method. ServiceConfiguration config = jsonSerializer.ReadObject(buffer) as ServiceConfiguration; // Close the stream. buffer.Close();

6-28 Reading g and Writing Local Data

Cr reating a C Custom Serializer

Yo ou may want t to serialize dat ta into a form mat other than n binary, XML, , or JSON. The e .NET Framew work pro ovides the IFo ormatter inte erface in the S System.Runtime.Serializat tion namespa ace, so you can create your own forma atter. Your cus stom formatte er will then fo ollow the same e pattern as th he BinaryFor rmatter and So oapFormatter r classes. To o create your o own formatter, perform the e following ste eps: 1. 2. 3. Create a cla ass that implements the IFo ormatter inte erface. Create impl lementations for the Surro ogateSelector r, Binder, and d Context pro operties. Create impl lementations for the Deser rialize and Se erialize metho ods.

ode example shows a custo om formatter that can seria alize and dese erialize objects s to the .ini The following co rmat. for Cu ustom IniForm matter
u using System; u using System.Collections s.Generic; u using System.IO; u using System.Reflection; ; u using System.Runtime.Ser rialization; n namespace Fou urthCoffee.S Serializer { class IniFormatter : IFormatter { static readonly ch har[] _delim m = new char[] { '=' }; public ISurrogateS Selector Sur rrogateSelect tor { get; s set; } public Serializati ionBinder Binder { get; set; } public StreamingCo ontext Conte ext { get; se et; } public IniFormatte er() { this s.Context = new Stream mingContext( (StreamingCon ntextStates. .All); } public object Dese erialize(Str ream serializ zationStream m) { Stre eamReader bu uffer = new Stream mReader(serializationStream); // G Get the type e from the s serialized da ata.

Programming in Visual C# 6-29

Type typeToDeserialize = this.GetType(buffer); // Create default instance of object using type name. Object obj = FormatterServices.GetUninitializedObject(typeToDeserialize); // Get all the members for the type. MemberInfo[] members = FormatterServices.GetSerializableMembers(obj.GetType(), this.Context); // Create dictionary to store the variable names and any serialized data. Dictionary<string, object> serializedMemberData = new Dictionary<string, object>(); // Read the serialized data, and extract the variable names // and values as strings. while (buffer.Peek() >= 0) { string line = buffer.ReadLine(); string[] sarr = line.Split(_delim); // key = variable name, value = variable value. serializedMemberData.Add( sarr[0].Trim(), // Variable name. sarr[1].Trim()); // Variable value. } // Close the underlying stream. buffer.Close(); // Create a list to store member values as their correct type. List<object> dataAsCorrectTypes = new List<object>(); // For each of the members, get the serialized values as their correct type. for (int i = 0; i < members.Length; i++) { FieldInfo field = members[i] as FieldInfo; if(!serializedMemberData.ContainsKey(field.Name)) throw new SerializationException(field.Name); // Change the type of the value to the correct type // of the member. object valueAsCorrectType = Convert.ChangeType( serializedMemberData[field.Name], field.FieldType); dataAsCorrectTypes.Add(valueAsCorrectType); } // Populate the object with the deserialized values. return FormatterServices.PopulateObjectMembers( obj, members, dataAsCorrectTypes.ToArray()); } public void Serialize(Stream serializationStream, object graph) { // Get all the fields that you want to serialize. MemberInfo[] allMembers = FormatterServices.GetSerializableMembers(graph.GetType(), this.Context); // Get the field data. object[] fieldData = FormatterServices.GetObjectData(graph, allMembers); // Create a buffer to write the serialized data too. StreamWriter sw = new StreamWriter(serializationStream); // Write the name of the class to the firstline. sw.WriteLine("@ClassName={0}", graph.GetType().FullName); // Iterate the field data. for (int i = 0; i < fieldData.Length; ++i) { sw.WriteLine("{0}={1}", allMembers[i].Name, // Member name. fieldData[i].ToString()); // Member value. } sw.Close(); } private Type GetType(StreamReader buffer) { string firstLine = buffer.ReadLine();

6-30

Reading and Writing Local Data

string[] sarr = firstLine.Split(_delim); string nameOfClass = sarr[1]; return Type.GetType(nameOfClass); } } }

Programming in i Visual C#

6-31 1

D Demonstr ration: Se erializing to t XML

In this demon I nstration, you will serialize a and deserialize a custom ty ype to XML by y using the S SoapFormatt ter class.

D Demonstra ation Steps


1 1. 2 2. 3 3. 4 4. 5 5. 6 6. 7 7. 8 8. Switch to the Windows s 8 Start wind dow. Click Visu ual Studio 201 12. In Visual Studio, on the e File menu, p point to Open n, and then click Project/Solution. In the Op pen Project dia alog box, brow wse to E:\Dem mocode\Starte er\FourthCoff fee.ExceptionL Logger, click FourthCo offee.Exception nLogger.sln, a and then click k Open. In Visual Studio, on the e View menu, , click Task Li ist. In the Tas sk List windo ow, in the Cate egories list, click Commen nts. Double-c click the TODO O: 01: Decorat te the type wi ith the Serializ zable attribute e. task. In the cod de editor, click in the blank k line below th he comment, and then type e the followin ng code:
[Seriali izable]

9 9.

In the Tas sk List window w, double-click the TODO: 0 02: Implemen nt the ISerializ zable interface e. task.

1 In the cod 10. de editor, click in the blank k line below th he comment, and then type e the followin ng code:
: ISeria alizable

1 Right-clic 11. ck the text ISe erializable, poi int to Implement Interface, and then clic ck Implement Interface. 1 In the Ge 12. etObjectData method, repl lace the existing code to th hrow a new NotImple ementedExce eption object t with the follo owing code:
info.Add dValue("Titl le", this.Title); info.Add dValue("Deta ails", this.Details);

1 In the Tas 13. sk List window w, double-click the TODO: 0 03: Add a des serialization co onstructor. task.

6-32

Reading and Writing Local Data

14. In the code editor, click in the blank line below the comment, and then type the following code:
public ExceptionEntry( SerializationInfo info, StreamingContext context) { this.Title = info.GetString("Title"); this.Details = info.GetString("Details"); }

15. In the Task List window, double-click the TODO: 04: Create a SoapFormatter object and serialize the entry object. task. 16. In the code editor, click in the blank line below the comment, and then type the following code:
var formatter = new SoapFormatter(); formatter.Serialize(stream, entry);

17. In the Task List window, double-click the TODO: 05: Create a SoapFormatter object and deserialize the stream to the entry object. task. 18. In the code editor, click in the blank line below the comment, and then type the following code:
var formatter = new SoapFormatter(); entry = formatter.Deserialize(stream) as ExceptionEntry;

19. On the Build menu, click Build Solution. 20. On the Debug menu, click Start Without Debugging. 21. In the Exception Logger window, create a new exception entry by using the following information, and then click Save: a. b. Title: Critical database error Details: Could not find database server

22. In the Save Successful message box, click OK. The exception entry has now been serialized. 23. Close the Exception Logger application. 24. Open File Explorer and browse to the E:\Democode\Data\Exceptions folder. 25. In the E:\Democode\Data\Exceptions folder, double-click the Exception_<date and time>.txt file. 26. In Notepad, find the Title and Details XML elements. 27. Switch to Visual Studio, and on the Debug menu, click Start Without Debugging. 28. In the Exception Logger window, in the File list, click E:\Democode\Data\Exceptions\Exception_<date and time>.txt, and then click Load. The ExceptionEntry object has now been deserialized. 29. Close the application, close Visual Studio, and then close File Explorer.

Programming in i Visual C#

6-33 3

Lesson 3

Perfo orming I/O by y Using Stream ms

When you wo W ork with data, whether the data d is stored in a file on th he file system or on a web s server a accessible ove er HTTP, the d data sometime es becomes to oo large to load into memo ory and transm mit in a single e a atomic operat tion. For exam mple, imagine trying to load d a 200-gigab byte video file e from the file e system into m memory in a single s operati ion. Not only would the op peration take a long time, b but it would also consume a large amoun nt of memory y. In this lesson, you will learn I n how to use streams s to rea ad from and w write to files w without having g to cache t entire file in memory. the

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Describe the purpose o of a stream. Describe the different types of strea ams provided in the .NET Fr ramework. Describe how to use a stream.

6-34 Reading g and Writing Local Data

W What are St treams?

The .NET Frame ework enables s you to use st treams. A stream is a seque ence of bytes, which could come from af file on the file system, a net twork connection, or memo ory. Streams e enable you to o read from or r write to a data source in small, manage eable data pac ckets. Typically, streams pro ovide the follo owing operati ions: i a type, su uch as a byte array. Reading chunks of data into unks of data fr rom a type to o a stream. Writing chu Querying th he current position in the stream and mo odifying a spe ecific selection n of bytes at t the current position.

St treaming in n the .NET Framework F k


The .NET Frame ework provide es several strea am classes tha at enable you to work with a variety of data d and data sources. W When choosing g which stream m classes to use, you need to consider th he following: What type o of data you are reading or writing, for ex xample, binar ry or alphanum meric. Where the d data is stored, for example, on the local file system, in n memory, or on a web serv ver over a network.

The .NET Frame ework class lib brary provides several classe es in the Syste em.IO names space that you u can use to rea ad and write f files by using streams. At th he highest level of abstracti ion, the Strea am class defin nes the common functio onality that al ll streams provide. The clas ss provides a g generic view o of a sequence e of bytes, tog gether with th he operations and properties that all stre eams provide. . Internally, a Stream objec ct maintains ap pointer that re efers to the cu urrent location n in the data source. When n you first con nstruct a Strea am object ov ver a data source, this point ter is positione ed immediate ely before the first byte. As you read and d write data, the e Stream clas ss advances th his pointer to the end of the e data that is read or writte en. Yo ou cannot use the Stream c class directly. Instead, you instantiate spe ecializations o of this class that are op ptimized to pe erform stream m-based I/O fo or specific type es of data sou urces. For exam mple, the File eStream cla ass implement ts a stream that uses a disk k file as the da ata source, and d the Memor ryStream clas ss implements a st tream that use es a block of m memory as th he data source e.

Programming in i Visual C#

6-35 5

T Types of S Streams in n the .NET T Framewo ork

The .NET Fram T mework provid des many stre eam classes th hat you can us se to read and d write differe ent types of d data from diff ferent types o of data source es. The following table desc cribes some of f these stream m classes, and se them. w when you mig ght want to us Stream class s FileStream Descriptio on Enables y you to establis sh a stream to o a file on the file system. The FileStream m class hand dles operation ns such as ope ening and clo osing the file, and a provides access to the file through a raw sequ uence of byte es. Enables y you to establis sh a stream to o a location in memory. The e MemoryS Stream class handles opera ations such as s acquiring the in-memory storage, a and provides access a to the memory locat tion through a raw sequence of bytes. Enables y you to establis sh a stream to o a network lo ocation in mem mory. The Network kStream class handles oper rations such as s opening and d closing a connectio on to the netw work location, and provides s access to the e network location t through a raw w sequence of bytes.

MemoryStre eam

NetworkStream

A stream that t is established d by using a F FileStream, M MemoryStream m, or Networ rkStream obj ject is just a r sequence raw e of bytes. If th he source data a is structured d, you must co onvert the byt te sequence into the a appropriate ty ypes. This can n be a time-co onsuming and d error-prone task. Howeve er, the .NET Fra amework c contains classes that you ca an use to read d and write te extual data and primitive ty ypes in a stream that you h have opened by using the FileStream, MemoryStrea M am, or Netwo orkStream cla asses. The following table d describes som me of the strea am reader and d writer classe es. Stream class s StreamRead der StreamWriter BinaryReade er Description Enables you u to read textu ual data from m an underlying data source e stream, such h as a FileStream, MemoryS Stream, or Ne etworkStream m object. Enables you u to write text tual data to an n underlying d data source st tream, such as a FileStream m, MemoryStr ream, or Netw workStream object. Enables you u to read bina ary data from an underlying g data source stream, such as

6-36

Reading and Writing Local Data

Stream class

Description a FileStream, MemoryStream, or NetworkStream object.

BinaryWriter

Enables you to write binary data to an underlying data source stream, such as a FileStream, MemoryStream, or NetworkStream object.

Programming in i Visual C#

6-37 7

R Reading a and Writin ng Binary Data by U Using Stre eams

M Many applicat tions store da ata in raw bina ary form for a number of re easons, such a as the followin ng: Writing b binary data is fast. f Binary da ata takes up le ess space on d disk. Binary da ata is not hum man readable.

You can read and write dat Y ta in a binary format in you ur .NET Frame ework applicat tions by using g the B BinaryReade r and BinaryW Writer classes s. To read or write binary dat T ta, you constru uct a BinaryR Reader or Bin naryWriter ob bject by provid ding a stream m t that is connec cted to the source of the da ata that you want w to read o or write, such as a FileStrea am or M MemoryStrea am object. The following code example shows how to initialize th T he BinaryRea ader and Bina aryWriter classes, passing a FileStream object. I Initializing a BinaryReade er and Binary yWriter Obje ect
string file ePath = "C:\ \\fourthcoffee\\applicat tiondata\\se ettings.txt"; FileStream file = new FileStream(filePath); ... BinaryReade er reader = new BinaryReader(file); ; ... BinaryWrite er writer = new BinaryWriter(file); ;

After you hav A ve created a BinaryReader object, you can use its members to read d the binary d data. The f following list d describes som me of the key members: The Base eStream property enables y you to access the underlyin ng stream that t the BinaryR Reader object uses. The Close e method ena ables you to c close the BinaryReader obj ject and the underlying u stre eam. The Read d method enables you to re ead the numb ber of remaining bytes in th he stream from m a specific index. The Read dByte method d enables you to read the n next byte from m the stream, and advance the stream to o the next b byte.

6-38

Reading and Writing Local Data

The ReadBytes method enables you to read a specified number of bytes into a byte array.

Similarly, the BinaryWriter object exposes various members to enable you to write data to an underlying stream. The following list describes some of the key members. The BaseStream property enables you to access the underlying stream that the BinaryWiter object uses. The Close method enables you to close the BinaryWiter object and the underlying stream. The Flush method enables you to explicitly flush any data in the current buffer to the underlying stream. The Seek method enables you to set your position in the current stream, thus writing to a specific byte. The Write method enables you to write your data to the stream, and advance the stream. The Write method provides several overloads that enable you to write all primitive data types to a stream.

Reading Binary Data


The following code example shows how to use the BinaryReader and FileStream classes to read a file that contains a collection of bytes. This example uses the Read method to advance through the stream of bytes in the file. BinaryReader Example
// Source file path. string sourceFilePath = "C:\\fourthcoffee\\applicationdata\\settings.txt "; // Create a FileStream object so that you can interact with the file // system. FileStream sourceFile = new FileStream( sourceFilePath, // Pass in the source file path. FileMode.Open, // Open an existing file. FileAccess.Read);// Read an existing file. // Create a BinaryWriter object passing in the FileStream object. BinaryReader reader = new BinaryReader(sourceFile); // Store the current position of the stream. int position = 0; // Store the length of the stream. int length = (int)reader.BaseStream.Length; // Create an array to store each byte from the file. byte[] dataCollection = new byte[length]; int returnedByte; while ((returnedByte = reader.Read()) != -1) { // Set the value at the next index. dataCollection[position] = (byte)returnedByte; // Advance our position variable. position += sizeof(byte); } // Close the streams to release any file handles. reader.Close(); sourceFile.Close();

Writing Binary Data


The following code example shows how to use the BinaryWriter and FileStream classes to write a collection of four byte integers to a file. BinaryWriter Example
string destinationFilePath = "C:\\fourthcoffee\\applicationdata\\settings.txt"; // Collection of bytes. byte[] dataCollection = { 1, 4, 6, 7, 12, 33, 26, 98, 82, 101 };

Programming in Visual C# 6-39

// Create a FileStream object so that you can interact with the file // system. FileStream destFile = new FileStream( destinationFilePath, // Pass in the destination path. FileMode.Create, // Always create new file. FileAccess.Write); // Only perform writing. // Create a BinaryWriter object passing in the FileStream object. BinaryWriter writer = new BinaryWriter(destFile); // Write each byte to stream. foreach (byte data in dataCollection) { writer.Write(data); } // Close both streams to flush the data to the file. writer.Close(); destFile.Close();

6-40 Reading g and Writing Local Data

Re eading an nd Writing g Text Dat ta by Using Streams s

In addition to st toring data as s raw binary data, you can also a store data as plain text t. You may wa ant to do thi is in your application if the persisted dat ta needs to be e human read dable. The process for reading from m and writing plain p text to a file is very sim ng binary milar to reading and writin data, except tha at you use the e StreamRead der and Strea amWriter clas sses. Wh hen you initia alize the Strea amReader or StreamWrite er classes, you u must provide a stream ob bject to handle the inter raction with th he data source. ode example shows how to o initialize the e StreamRead der and Strea amWriter clas sses, The following co passing a FileSt tream object. Ini itializing a St treamReader r and StreamWriter Objec ct
s string destin nationFilePa ath = "C:\\f fourthcoffee\ \\applicatio ondata\\sett tings.txt"; F FileStream fi ile = new Fi ileStream(de estinationFil lePath); ... S StreamReader reader = ne ew StreamRea ader(file); ... S StreamWriter writer = ne ew StreamWriter(file);

Aft ter you have created c a Stre eamReader o object, you can n use its mem mbers to read the plain text. The fol llowing list de escribes some of the key members: The Close m method enabl les you to clos se the Stream mReader obje ect and the un nderlying strea am. The EndOfS Stream prope erty enables y you to determ mine whether y you have reac ched the end of the stream. method enable es you to get the next available characte er in the stream, but does n not The Peek m consume it. . The Read m method enables you to get and consume e the next ava ailable charact ter in the stream. This method ret turns an int va ariable that re epresents the binary of the character, wh hich you may need to explicitly co onvert. The ReadBlock method enables you to t read an entire block of c characters from a specific in ndex from the stream.

Programming in Visual C# 6-41

The ReadLine method enables you to read an entire line of characters from the stream. The ReadToEnd method enables you to read all characters from the current position in the stream.

Similarly, the StreamWriter object exposes various members to enable you to write data to an underlying stream. The following list describes some of the key members: The AutoFlush property enables you to instruct the StreamWriter object to flush data to the underlying stream after every write call. The Close method enables you to close the StreamWriter object and the underlying stream. The Flush method enables you to explicitly flush any data in the current buffer to the underlying stream. The NewLine property enables you to get or set the characters that are used for new line breaks. The Write method enables you to write your data to the stream, and to advance the stream. The WriteLine method enables you to write your data to the stream followed by a new line break, and then advance the stream.

These members provide many options to suit many different requirements. If you do not want to store the entire file in memory in a single chunk, you can use a combination of the Peek and Read methods to read each character, one at a time. Similarly, if you want to write lines of text to a file one at time, you can use the WriteLine method.

Reading Plain Text


The following code example shows how to use the StreamReader and FileStream classes to read a file that contains plain text. This example uses the Peak method to advance through the stream of characters in the file. StreamReader Example
string sourceFilePath = @"C:\\fourthcoffee\\applicationdata\\settings.txt "; // Create a FileStream object so that you can interact with the file // system. FileStream sourceFile = new FileStream( sourceFilePath, // Pass in the source file path. FileMode.Open, // Open an existing file. FileAccess.Read);// Read an existing file. StreamReader reader = new StreamReader(sourceFile); StringBuilder fileContents = new StringBuilder(); // Check to see if the end of the file // has been reached. while (reader.Peek() != -1) { // Read the next character. fileContents.Append((char)reader.Read()); } // Store the file contents in a new string variable. string data = fileContents.ToString(); // Always close the underlying streams release any file handles. reader.Close(); sourceFile.Close();

Writing Plain Text


The following code example shows how to use the StreamWriter and FileStream classes to write a string to a new file on the file system.

6-42

Reading and Writing Local Data

StreamWriter Example
string destinationFilePath = @"C:\\fourthcoffee\\applicationdata\\settings.txt "; string data = "Hello, this will be written in plain text"; // Create a FileStream object so that you can interact with the file // system. FileStream destFile = new FileStream( destinationFilePath, // Pass in the destination path. FileMode.Create, // Always create new file. FileAccess.Write); // Only perform writing. // Create a new StreamWriter object. StreamWriter writer = new StreamWriter(destFile); // Write the string to the file. writer.WriteLine(data); // Always close the underlying streams to flush the data to the file // and release any file handles. writer.Close(); destFile.Close();

Programming in i Visual C#

6-43 3

D Demonstr ration: Ge enerating the Grade es Report Lab

I this demon In nstration, you will learn abo out the tasks t that you will p perform in the e lab for this module. m

6-44 Reading g and Writing Local Data

Lab: G Generat ting the e Grade es Repo ort

Sc cenario
Yo ou have been asked to upgrade the Grad des Prototype application to o enable user rs to save a stu udents gra ades as an XM ML file on the local disk. The e user should be able to cli ick a new button on the Stu udentProfile v view that asks the user whe ere they would d like to save the file, displa ays a preview of the data to the user, and asks the user r to confirm th hat they wish to save the file to disk. If th hey do, the ap pplication sho ould save the grade data in n XML format t in the locatio on that the us ser specified.

Ob bjectives
Aft ter completing this lab, you u will be able to: ory stream. Serialize data to a memo m stream. Deserialize data from a memory zed data to a file. Save serializ

timated Time: : 75 minutes Est Virtual Mac chine: 20483A A-SEA-DEV11-06, MSL-TMG G1 User Name : Student Password: Pa$$w0rd P

Programming in Visual C# 6-45

Exercise 1: Serializing Data for the Grades Report as XML


Scenario
In this exercise, you will write code that runs when the user clicks the Save Report button on the Student Profile view. You will enable a user to specify where to save the Grade Report, and to serialize the grades data so it is ready to save to a file. You will use the SaveFileDialog object to ask the user for the file name and location where they want to save the file. They will only be able to save the file in XML format, so you will need to limit the file types displayed in the dialog box. You will extract the grade data from the application data source and store it in a list of Grade objects. You will then write the FormatAsXMLStream method. This method will use an XmlWriter object to create an XML document and populate it with grade information from the list of Grade objects. Finally, you will debug the application and view the data held in the memory stream. The main tasks for this exercise are as follows: 1. Prompt the user for a filename and retrieve the grade data 2. Serialize the grade data to a memory stream 3. Debug the application

X Task 1: Prompt the user for a filename and retrieve the grade data
1. 2. 3. 4. 5. Start the MSL-TMG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-06 virtual machine and log on as Student with the password Pa$$w0rd. Start Visual Studio and from the E:\Labfiles\Starter\Exercise 1 folder, open the GradesPrototype.sln solution. In the Views folder, open the StudentProfile.xaml user interface, and note that it has been updated to include a Save Report button that users will click to generate and save the Grades Report. In StudentProfile.xaml.cs, in the SaveReport_Click method, add code to display a SaveFileDialog to the users, with a default filename of Grades.xml, and with XML documents (*xml) displayed in the Save as type box. Save the return value from the dialog box in a nullable Boolean variable. Check if the return value from the SaveFileDialog contains data. If it does, do the following: a. b. Get the grades for the currently selected student and store them in a generic list. Call the FormatAsXMLStream method, passing the list of grades to it, and store the returned data in a MemoryStream object.

6. 7.

X Task 2: Serialize the grade data to a memory stream


1. 2. 3. In StudentProfile.xaml.cs code file, locate the FormatAsXMLStream method. Add code to save the XML document to a MemoryStream object by using an XmlWriter object. Add code to create the root node of the XML document in the following format:
<Grades Student="Eric Gruber">

4.

Add code to enumerate the grades for the student and add them as child elements of the root node, using the following format:

6-46

Reading and Writing Local Data

<Grade Date="01/01/2012" Subject="Math" Assessment="A-" Comments="Good" />

5. 6. 7. 8.

Add code to finish the XML document with the appropriate end elements. Add code to flush the XmlWriter object and then close it to ensure that all the data is written to the MemoryStream object. Add code to reset the MemoryStream object so that it can be read from the start, and then return it to the calling method. Delete the line of code that throws a NotImplementedException exception.

X Task 3: Debug the application


1. 2. 3. 4. 5. 6. Build the solution and resolve any compilation errors. In the SaveReport_Click method, add a breakpoint to the closing brace of the if block. Debug the application. Log in as vallee with a password of password99. View Kevin Lius report, and then click Save Report to generate the XML document. Add code to save the file in the default location. Note: You will write the code to actually save the report to disk in Exercise 3 of this lab. 7. When you enter Break Mode, use the Immediate Window to view the contents of the MemoryStream object by using the following code:
?(new StreamReader(ms)).ReadToEnd()

8. 9.

Review the grade data that is returned. Stop debugging, delete the breakpoint, and then close the solution.

Results: After completing this exercise, users will be able to specify the location for the Grades Report file.

Programming in Visual C# 6-47

Exercise 2: Previewing the Grades Report


Scenario
In this exercise, you will write code to display a preview of the report to the user before saving it. First, you will add code to the SaveReport_Click method to display the XML document to the user in a message box. To display the document, you need to build a string representation of the XML document that is stored in the MemoryStream object. Finally, you will verify that your code functions as expected by running the application and previewing the contents of a report. The main tasks for this exercise are as follows: 1. Display the string to the user in a message box 2. Build a string representation of the XML document 3. Run the application and preview the data.

X Task 1: Display the string to the user in a message box


1. 2. In Visual Studio, from the E:\Labfiles\Starter\Exercise 2 folder, open the GradesPrototype.sln solution. In StudentProfile.xaml.cs, in the SaveReport_Click method, add code to the end of the if block that calls the FormatXMLData method, passing the MemoryStream object that you created in the previous task, and storing the return value in a string variable. Add code to preview the string version of the report data in a message box with a caption of Preview Report, an OK button, and an information image.

3.

X Task 2: Build a string representation of the XML document


1. 2. 3. In StudentProfile.xaml.cs, in the FormatXMLData method, add code to create a new StringBuilder object used to construct the string. Add code to create a new XmlTextReader object used to read the XML data from the stream. Add code to read the XML data one node at a time, construct a string representation of the node, and append it to the StringBuilder. The possible nodes that can be encountered are XmlDeclaration, Element, and EndElement. Each element may have one or more attributes. Add code to reset the MemoryStream object and return the string containing the formatted data to the calling method. Delete the line of code that throws a NotImplementedException exception.

4. 5.

X Task 3: Run the application and preview the data.


1. 2. 3. 4. 5. Build the solution and resolve any compilation errors. Run the application. Log in as vallee with a password of password99. View Kevin Lius report, and then click Save Report to generate the XML document. Specify to save the file in the default location.

6-48

Reading and Writing Local Data

Note: You will write the code to actually save the report to disk in the next exercise of this lab. 6. 7. Review the XML data displayed in the message box and close the application. In Visual Studio, close the solution.

Results: After completing this exercise, users will be able to preview a report before saving it.

Programming in Visual C# 6-49

Exercise 3: Persisting the Serialized Grade Data to a File


Scenario
In this exercise, you will write the grade data to a file on the local disk. You will begin by modifying the existing preview dialog box to ask the user if they wish to save the file. If they wish to save the file, you will use a FileStream object to copy the data from the MemoryStream to a physical file. Then you will run the application, generate and save a report, and then verify that the report has been saved in the correct location in the correct format. The main tasks for this exercise are as follows: 1. Save the XML document to disk 2. Run the application and verify that the XML document is saved correctly

X Task 1: Save the XML document to disk


1. 2. 3. In Visual Studio, from the E:\Labfiles\Starter\Exercise 3 folder, open the GradesPrototype.sln solution. In StudentProfile.xaml.cs, in the SaveReport_Click method, locate the line of code that displays the report data to the user in a message box. Modify this line of code as follows: a. b. c. d. 4. 5. Save the return value of the MessageBox.Show method in a MessageBoxResult variable Set the caption of the message box to Save Report? Include Yes and No buttons in the message box. Display a question mark image.

If the user clicks Yes to save the report, open the file that the user specified and create a FileStream object to write data to this file. Write the data from the MemoryStream object to the file.

X Task 2: Run the application and verify that the XML document is saved correctly
1. 2. 3. 4. 5. 6. 7. 8. 9. Build the solution and resolve any compilation errors. Run the application. Log on as vallee with a password of password99. View Kevin Lius report card and then click Save Report to generate the XML document. Specify to save the file in the Documents folder by using the default name. Review the XML data displayed in the message box, and then confirm that you want to save the file. Close the application. Open the saved report in Internet Explorer and verify that it contains the expected grade data. In Visual Studio, close the solution.

Results: After completing this exercise, users will be able to save student reports to the local hard disk in XML format.

6-50 Reading g and Writing Local Data

Modu ule Revi iew and d Takea aways

M Module Revie ew
In this module, y you have lear rned how to w work with the file system by y using a num mber of classes s in the Sys stem.IO name espace, and ho ow to serialize e application data to differ rent formats. Question: You Y are a dev veloper workin ng on the Fou urth Coffee W Windows Presentation Foundation n (WPF) client application. Y You have been n asked to sto ore some setti ings in a plain n text file in t the users tem mporary folder r on the file sy ystem. Briefly explain which h classes and methods yo ou could use t to achieve this. Question: You Y are a dev veloper workin ng for Fourth Coffee. A bug g has been raised and you have been asked a to inves stigate. To help reproduce the error, you u have decide ed to add som me logic to per rsist the state of the applica ation to disk, w when the app plication encounters the error. All the types in the e application a are serializable, and it woul ld be advanta ageous if the persisted st tate was huma an readable. What W approac ch will you tak ke? Test Your Know wledge Q Question Y You are a deve eloper workin ng for Fourth h Coffee. You have been as sked to write some c code to proce ess a 100 GB v video file. You ur code needs to transfer t the file from one lo ocation on di isk, to anothe er location on n disk, withou ut reading the e entire file in nto m memory. Whic ch classes wo ould you use to t read and w write the file? S Select the cor rrect answer. The M MemoryStream m, BinaryReade er and BinaryW Writer classes s. The FileStream, Bina aryReader and d BinaryWrite er classes. The Bi inaryReader and BinaryWrit ter classes. The FileStream, Stre eamReader an nd StreamWrit ter classes.

Programming in Visual C# 6-51

Question The MemoryStream, StreamReader and StreamWriter classes.

7-1

Module 7
Accessing a Database
Contents:
Module Overview Lesson 1: Creating and Using Entity Data Models Lesson 2: Querying Data by Using LINQ Lab: Retrieving and Modifying Grade Data Module Review and Takeaways 7-2 7-3 7-16 7-28 7-36

7-2

Accessing g a Database

Modu ule Ove erview

Ma any applicatio ons require ac ccess to data t that is stored in a database. Microsoft Visual Studio 2012 and the Microso oft .NET Framework provide tools and fu unctionality th hat you can us se to easily ac ccess, query, and update data a. In this module, y you will learn how to creat te and use ent tity data models (EDMs) an nd how to que ery many typ pes of data by y using Langu uage-Integrate ed Query (LIN NQ).

Ob bjectives
Aft ter completing this module e, you will be able to: , and customize an EDM. Create, use, Query data by using LINQ.

Programming with w Visual C#

7-3 3

Lesson 1

Creat ting an nd Using g Entity y Data Models s

Data access applications ha D ave traditionally been tedio ous to develop p. They often contain queri ies that are w written as text t strings that cannot be typ pe-checked or r syntax-check ked at compil le time, and re esults are r returned as un ntyped data r records. The A ADO.NET Entit ty Framework k solves these problems and d simplifies t process of the f developing d data access ap pplications by y using EDMs. . In this lesson, you will learn I n how to use the t ADO.NET Entity Data T Tools to create e EDMs, how to t customize t classes tha the at the tools ge enerate, and how h to access s the entities i in the generat ted model.

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Describe the ADO.NET T Entity Frame ework. Use the A ADO.NET Entit ty Data Mode el Tools. Customiz ze generated c classes. Read and d modify data by using the Entity Framew work.

7-4

Accessing g a Database

In ntroductio on to the A ADO.NET Entity Fra amework

His storically whe en you write code to access s data that is s stored in a dat tabase, you have to unders stand the str ructure of the data in the database and h how it all interrelates. Often n it is stored in a normalize ed fashion, wh here tables do o not logically y map to the real-life r object ts that they re epresent. The ADO.NET Ent tity Fra amework enables you to de evelop applica ations that target a concep ptual model in nstead of the normalized database structu ure in the stor rage layer. ork provides t the following: : The ADO.NET Entity Framewo se are models that you can use to map d database table es and queries s to .NET Fram mework EDMs. Thes objects. L (SQL). This is a sto orage independent query language l that t enables Entity Structured Query Language ry and manipu ulate EDM constructs. you to quer Object Serv vices. These are e services that enable you t to work with t the Common Language Ru untime (CLR) objects in a concep ptual model.

ents enable yo ou to: These compone Write code against a con nceptual model that include es types that support inher ritance and re elationships. Update app plications to ta arget a differe ent storage m model without rewriting or r redistributing all of your data access code. dard code that t is not depen ndent on the data d storage system. s Write stand Write data access code that supports c compile-time type-checkin ng and syntax-checking.

The conceptual model that you work with in the Entity Framework describes the semantics of the business ew of the data a. It defines en ntities and relationships in a business sen nse and is mapped to the lo ogical vie mo odel of the un nderlying data a in the data s source. For ex xample, in a hu uman resourc ces application n, entities ma ay include em mployees, jobs, and branch locations. An entity is a des scription of th he items and t their pro operties, and they are linke ed by relationships, such as s an employee e being related to a particu ular branch loc cation. al Reading: F For more infor rmation about the ADO.NE ET Entity Fram mework, see th he Additiona AD DO.NET Entity y Framework p page at http:// /go.microsoft t.com/fwlink/? ?LinkID=2678 806.

Programming with Visual C# 7-5

7-6

Accessing g a Database

Us sing the A ADO.NET Entity Dat ta Model Tools

Vis sual Studio 20 012 provides t the Entity Dat ta Model Tool ls that you can n use to creat te and update e EDMs in your application ns. It supports s both database-first design n and code-fir rst design: Database-fi first design. In database-first t design, you design and cr reate your database before e you generate yo our model. Th his is common nly used when you are deve eloping applic cations agains st an existing dat ta source; how wever, this can n limit the flex xibility of the application in n the long term m. Code-first d design. In code e-first design, you design the entities for r your applica ation and then n create the database st tructure aroun nd these entities. Developers prefer this method because it enables s you to design your r application around a the bu usiness functio onality that yo ou require. Ho owever, in rea ality, you often have to work with an existing da ata source.

Us sing the Entity Data M Model Tools s


Vis sual Studio 20 012 provides t the ADO.NET Entity Data Model M Tools, w which include the Entity Data Model De esigner for gra aphically creating and relat ting entities in n a model and d three wizard ds for working g with mo odels and dat ta sources. The e following ta able describes the wizards. W Wizard E Entity Data M Model Wizard U Update Mode el Wizard G Generate Data abase Wizard Descript tion Enables s you to generate a new co onceptual mod del from an ex xisting data source by using the d database-first t design meth hod. Enables s you to update an existing g conceptual m model with ch hanges that are mad de to the data a source on which w it is base ed. Enables s you to generate a database from a con nceptual model that you have de esigned in the e Entity Data M Model Design ner by using th he codefirst des sign method.

Wh hen you creat te a model by y using the Entity Data Mod del Wizard, the model open ns in the Desig gner pane, dis splaying the e entities that th he wizard has generated an nd the relation nships betwee en them. You can use thi is pane to add d, modify, and d delete entities and relatio onships. By y default, when n you create a model from a database, t the Entity Des signer automa atically genera ates the ma appings from the data sour rce to the con nceptual mode el. You can vie ew, modify, and delete the ese ma appings in the e Mapping De etails pane.

Programming with Visual C# 7-7

Additional Reading: For more information about the Entity Data Model Tools, see the ADO.NET Entity Data Model Tools page at http://go.microsoft.com/fwlink/?LinkID=267807.

7-8

Accessing g a Database

Demonstration: Crea ating an E Entity Data Model

In this demonstration, you wi ill use the Entity Data Wizard to generat te an EDM for r an existing d database.

De emonstration Steps
1. 2. 3. Start the MSL-TMG1 virtual machine if it is not already running. 0483A-SEA-D DEV11-07 virt tual machine. Start the 20 Log on to W Windows 8 as a Student with the passwo ord Pa$$w0r rd. Note: If necessary, click k Switch User r to display th he list of users s. 4. 5. 6. 7. 8. 9. he Windows 8 Start window w. Switch to th Click Visual Studio 2012 2. udio, on the F File menu, point to Open, and a then click k File. In Visual Stu In the Open n File dialog b box, browse to o the E:\Demo ocode\Databa ase folder, clic ck AttachFourt thCoffeeDatabaseScript.sql l, and then click Open. On the SQL L menu, point t to Transact-SQL Editor, a and then click k Execute. In the Conn nect to Serve er dialog box, in the Server r name box, type (localdb) )\v11.0, and t then click Connect.

he query time es out, in the C Connect to Server dialog box, click OK, and then in Note: If th e Connect to o Server dialog g box, click Connect. the 10 0. When the query q has com mpleted, on th he File menu, click Close. oject. 11. On the File menu, point to New, and then click Pro w Project dialo og box, expan nd Templates s, click Visual C#, and then in the Template list, 12. In the New click Conso ole Applicatio on.

Programming with Visual C# 7-9

13. In the Name box, type FourthCoffee.Employees, in the Location box, type E:\Democode\Demo1\Starter, and then click OK. 14. In Solution Explorer, right-click FourthCoffee.Employees, point to Add, and then click New Item. 15. In the Add New Item FourthCoffee.Employees dialog box, click ADO.NET Entity Data Model, in the Name box, type FourthCoffeeEmployeesModel, and then click Add. 16. In the Entity Data Model Wizard, on the Choose Model Contents page, click Generate from database, and then click Next. 17. On the Choose Your Data Connection page, click New Connection. 18. In the Choose Data Source dialog box, in the Data source list, click Microsoft SQL Server, and then click Continue. 19. In the Connection Properties dialog box, in the Server name box, type (localdb)\v11.0, in the Select or enter a database name list, click FourthCoffee, and then click OK. 20. In the Entity Data Model Wizard, on the Choose Your Data Connection page, click Next. 21. On the Choose Your Database Objects and Settings page, expand Tables, expand dbo, select Branches, Employees, and JobTitles, and then click Finish. 22. In the Security Warning dialog box, select Do not show this message again, and then click OK. 23. On the Build menu, click Build Solution. 24. Review the three entities that have been generated and the associations between them. 25. Right-click the designer surface, and then click Mapping Details. 26. In the Designer pane, click Employee. 27. In the Mapping Details pane, review the mappings between the entity and the data source. 28. In Solution Explorer, expand FourthCoffeeEmployeesModel.edmx, expand FourthCoffeeEmployeesModel.Context.tt, and then double-click FourthCoffeeEmployeesModel.Context.cs. 29. In the code editor, review the code in the FourthCoffeeEntities partial class. 30. In Solution Explorer, expand FourthCoffeeEmployeesModel.tt, and then double-click Employee.cs. 31. Review the Employee partial class and the properties that have been generated. 32. Leave the solution open so that you can refer to it in the following topics.

7-10 Accessin ng a Database

Cu ustomizin ng Generat ted Classe es

Wh hen you use t the Entity Data a Model Wiza ard to create a model, it automatically ge enerates class ses that expose the entit ties in the mo odel to your application cod de. These clas sses contain properties that t provide acc cess to the pr roperties in the entities. The following co ode example shows an Employee class t that the Entity y Data Model Wizard gene erated. ated Classes Wizard-Genera
n namespace Fou urthCoffee.E Employees { using Sys stem; using Sys stem.Collect tions.Generic; public pa artial class s Employee { publi ic int Emplo oyeeID { get t; set; } publi ic string Fi irstName { g get; set; } publi ic string La astName { ge et; set; } publi ic Nullable< <System.Date eTime> DateOf fBirth { get t; set; } publi ic Nullable< <int> Branch h { get; set; } publi ic Nullable< <int> JobTit tle { get; se et; } publi ic virtual B Branch Branc ch1 {get; set t; } publi ic virtual J JobTitle Job bTitle1 {get; set; } } }

Yo ou may find th hat you want to t add custom m business log gic to the enti ity classes; how wever, if at an ny time in the e future you r run the Updat te Model Wiza ard, the classe es will be rege enerated and your code will be re, you can ex ov verwritten. However, the ge enerated classes are defined d as partial cla asses; therefor xtend them to add custom f functionality t to the classes. For example, if y you have a da ate of birth pr roperty in you ur model, you could write a GetAge met thod in a partial class to e enable a run-t time calculatio on of the emp ployees age. The following co ode example shows how yo ou can add bu usiness logic t to a generated d class by usin ng a partial cla ass. Ad dding Busine ess Logic in a Partial Class s
p public partia al class Emp ployee

Programming with Visual C# 7-11

{ public int GetAge() { DateTime DOB = (DateTime)_DateOfBirth; TimeSpan difference = DateTime.Now.Subtract(DOB); int ageInYears = (int)(difference.Days / 365.25); return ageInYears; } }

Additional Reading: For more information about partial classes, see Partial Classes and Methods (C# Programming Guide) at http://go.microsoft.com/fwlink/?LinkID=267808.

7-12 Accessin ng a Database

Re eading an nd Modify ying Data by Using t the Entity y Framewo ork

The automatically generated code files for r a model also o contains a partial class tha at inherits from the Sy ystem.Data.En ntity.DbCont text class. The e DbContext class provides facilities for querying and d working wit th entity data as objects. It contains a de efault constructor which ini itializes the class by using t the connection strin ng that the wizard generate es in the application config guration file. T This defines th he data connection and model definition to use. The DbContex xt class also co ontains a DbS Set property t that exposes a DbSe et(TEntity) cla ass for each entity in your m model. The Db bSet(TEntity) ) class represe ents a typ ped entity set that you can use to read, create, c update e, and delete data. The following co ode example shows the cla ass for the Fou urthCoffeeEnt tities model. Fo ourthCoffeeEntities Class
p public partia al class Fou urthCoffeeEn ntities : DbC Context { public Fo ourthCoffeeE Entities() : base("name= =FourthCoffe eeEntities") { } public Db bSet<Branch> > Branches { get; set; } public Db bSet<Employe ee> Employee es { get; set t; } public Db bSet<JobTitl le> JobTitle es { get; set t; } }

To o use the typed d entity set, y you create an instance of th he DbContext t class and the en access the properties by y using the sta andard dot no otation. The following co ode example shows how to o read and up pdate data by using the Db bSet(TEntity) class. eading Data Re
F FourthCoffeeE Entities DBC Context = ne ew FourthCoff feeEntities( (); / // Print a li ist of emplo oyees. f foreach (FourthCoffee.Em mployees.Emp ployee emp in n DBContext. .Employees) { Console.W WriteLine("{ {0} {1}", em mp.FirstName, emp.LastNa ame); }

Programming with Visual C# 7-13

The DbSet(TEntity) class implements the IEnumerable interface which provides a number of extension methods that enable you to easily locate specific data in the source. For example, the First extension method locates the first match for the specified condition, such as a last name of Prescott. The following code example shows how to use the First extension method to locate an employee and then how to update the data by using standard dot notation. Locating and Modifying Data
// Update the employee with a surname of "Prescott." var emp = DBContext.Employees.First(e => e.LastName == "Prescott"); if (emp != null) { emp.LastName = "Forsyth"; }

Additional Reading: For more information about the DbSet(Entity) class, see the DbSet(Entity) Class page at http://go.microsoft.com/fwlink/?LinkID=267809. For more information about the Enumerable methods, see the Enumerable Methods page at http://go.microsoft.com/fwlink/?LinkID=2678010. After you change the data in the model, you must explicitly apply those changes to the data in the data source. You can do this by calling the SaveChanges method of the ObjectContext object. The following code example shows how to use the SaveChanges method. Persisting Changes To The Database
DBContext.SaveChanges();

7-14 Accessin ng a Database

Demonstration: Reading and Modifying Data in an EDM

In this demonstration, you wi ill use the Obj jectSet(TEnti ity) class to re ead and modi ify data in an EDM.

De emonstration Steps
1. 2. 3. Start the MSL-TMG1 virtual machine if it is not already running. 0483A-SEA-D DEV11-07 virt tual machine. Start the 20 Log on to W Windows as Student with h the passwor rd Pa$$w0rd. Note: If necessary, click k Switch User r to display th he list of users s. 4. 5. 6. 7. 8. 9. he Windows 8 Start window w. Switch to th Click Visual Studio 2012 2. udio, on the F File menu, point to Open, and a then click k Project/Solution. In Visual Stu In the Open n Project dial log box, brow wse to the E:\D Democode\D Demo2\Fourt thCoffee.Emp ployees folder, click k FourthCoff fee.Employee es.sln, and the en click Open n. In Solution Explorer, expand FourthCo offee.Employ yees, and then double-click Program.cs s. Review the definition of the DBConte ext variable.

0. Review the code in the P PrintEmploye eesList metho od that uses th he DBContex xt variable to a access the 10 data in the EDM. Main method that uses the First extensio on method to o retrieve an employee e 11. Review the code in the M and then m modifies that e employees La astName prop perty. bug menu, clic ck Start Witho out Debugging. 12. On the Deb the employee es list is displayed, and then n press Enter. 13. Verify that t 4. Verify that t the employee e named Dian ne Prescott is s now named Diane Forsyt th, and then press 14 Enter. 15. Press Enter to close the a application.

Programming with Visual C# 7-15

7-16 Accessin ng a Database

Lesson 2

Query ying Da ata by U Using LINQ

As an alternative e to using the e Entity Frame ework for que erying data, yo ou can use LIN NQ. This also supports s compile-time sy yntax-checking and type-ch hecking and a also uses Micr rosoft IntelliSe ense in Visual Studio. LIN NQ defines a r range of stand dard query op perators that enable you to o retrieve exac ctly the data t that you req quire in a declarative way. In this lesson, yo ou will learn h how to query data and use anonymous m methods and how to force query exe ecution to override the def fault deferred query execut tion behavior. .

Le esson Obje ectives


Aft ter completing this lesson, you will be ab ble to: Query data. onymous types. Query data by using ano Force query y execution.

Programming wit th Visual C#

7-17 7

Q Querying Data

You can use L Y LINQ to query y data from a w wide range of f data sources s, including .N NET Framewor rk collections, M Microsoft SQL L Server dat tabases, ADO.NET data sets s, and XML do ocuments. In f fact, you can u use it to q query any dat ta source that t implements the IEnumera able interface e. T syntax of all LINQ quer The ries has the sa ame basis, as follows: f f from <variab ble names> in <data source e> s select <variab ble names> However, you H u can customiz ze this syntax in many ways s to retrieve e exactly the dat ta that you re equire in the f format that yo ou want. The following cod de examples a all use LINQ to o Entities to query data in a an EDM; h however, the syntax of the query itself d does not chang ge if you use a different typ pe of data sou urce.

S Selecting D Data
The following code example shows how to use a simp T ple select clau use to return all a of the data a in a single e entity. U Using a selec ct Clause
IQueryable< <Employee> emps e = from e in DBConte ext.Employee es select e;

The return data type from the query is a T an IQueryable e<Employee>, enabling yo ou to iterate t through the d data that is re eturned.

F Filtering Da ata by Row w


The following code example shows how to use the where keyword T d to filter the returned data a by row to th a last name c contain only e employees wit e of Prescott. U Using a wher re Clause
string _Las stName = "Pr rescott"; IQueryable< <Employee> emps e = from e in DBConte ext.Employee es whe ere e.LastName == _LastN Name select e;

7-18

Accessing a Database

Filtering Data by Column


The following code example shows how to declare a new type in which to store a subset of columns that the query returns; in this case, just the FirstName and LastName properties of the Employee entity. Using a New Class to Return a Subset of Columns
private class FullName { public string Forename { get; set; } public string Surname { get; set; } } private void FilteringDataByColumn() { IQueryable<FullName> names = from e in DBContext.Employees select new FullName { Forename = e.FirstName, Surname = e.LastName }; }

Working with the Results


To then work with the data that is returned from any of these queries, you use dot notation to access the properties of the members of the IQueryable<> type, as the following code example shows. Accessing the Returned Data
foreach (var emp in emps) { Console.WriteLine("{0} {1}", emp.FirstName, emp.LastName); }

Programming wit th Visual C#

7-19 9

D Demonstr ration: Qu uerying D Data

I this demon In nstration, you will use LINQ Q to Entities to o query data.

D Demonstra ation Steps


1 1. 2 2. 3 3. Start the MSL-TMG1 vi irtual machine e if it is not already running g. Start the 20483A-SEA A-DEV11-07 v virtual machine. Log on to o Windows 8 as a Student with the passwo rd. ord Pa$$w0r Note: If f necessary, click Switch Us ser to display the list of use ers. 4 4. 5 5. 6 6. 7 7. 8 8. 9 9. Switch to the Windows s 8 Start wind dow. Click Visu ual Studio 20 012. In Visual Studio, on the e File menu, p point to Open n, and then click Project/Solution. In the Op pen Project dialog box, bro owse to the E: :\Democode\ \Demo3\Fou urthCoffee.Em mployees folder, click FourthCo offee.Employ yees.sln, and t then click Ope en. In Solutio on Explorer, ex xpand Fourth hCoffee.Empl loyees, and th hen double-click Program.cs. Review th he LINQ code in each of the e methods.

1 On the Build menu, click Build Solu 10. ution. 1 On the Debug menu, c 11. click Start Wit thout Debugg ging. 1 In the con 12. nsole window w, review the o output of the QueryingDat ta method, an nd then press Enter. 1 Repeat st 13. tep 12 for each of the follow wing methods: a. b. Filter ringDataByRow Filter ringDataByColumn

1 Press Ente 14. er to close the e application. 1 In Visual Studio, on the 15. e File menu, c click Close So olution.

7-20

Accessing a Database

Programming wit th Visual C#

7-21 1

Q Querying Data by Using U Ano onymous T Types

In the exampl I les in the prev vious topic an nd demonstrat tion, the retur rn data was al lways stored in a strongly t typed IQuery yable<Type> variable; how wever, in the filtering by column scenario o, it is necessa ary to define t type conta the aining a subse et of columns s before defining the query y. Although th his is a perfectly valid way o working, it can become tedious to explicitly define multiple classes. of n type as an implicitly You can use a Y anonymous ty ypes to store t the returned d data by declar ring the return t typed local va ariable, a var, and by using the new keyw word in the se elect clause to o create the instance of t type. the

F Filtering Da ata by Colu umn


The following code example shows how to use the va T ar data type and the new keyword k in the e select r the returned c clause to filter d data by colu umn. U Using an Ano onymous Typ pe to Return a Subset of C Columns
var names = from e in DBContext.Employees select n new { e.Firs stName, e.LastName };

A Anonymous ty ypes enable you y to perform m more comp plex queries in n LINQ.

G Grouping D Data
The following code example shows how to use a grou T up clause to g group the retu urned employ yees by their j title ID. job U Using a grou up Clause
var emps = from e in DBContext.Em D ployees gro oup e by e.JobTitle into o eGroup select new { Job = eGroup. .Key, Names = eGroup };

A Aggregatin ng Data
The following code example shows how to use a grou T up clause with h an aggregat te function to o count the n number of em mployees with h each job title e.

7-22

Accessing a Database

Using a group Clause with an Aggregate Function


var emps = from e in DBContext.Employees group e by e.JobTitle into eGroup select new { Job = eGroup.Key, CountOfEmployees = eGroup.Count() };

Navigating Data
The following code example shows how to use navigation properties to retrieve data from the Employees entity and the related JobTitles entity. Using Dot Notation to Navigate Related Entities
var emps = from e in DBContext.Employees select new { FirstName = e.FirstName, LastName = e.LastName, Job = e.JobTitle1.Job };

Programming wit th Visual C#

7-23 3

D Demonstr ration: Qu uerying D Data by Us sing Anony ymous Ty ypes

I this demon In nstration, you will use LINQ Q to Entities to o query data b by using anonymous types.

D Demonstra ation Steps


1 1. 2 2. 3 3. Start the MSL-TMG1 vi irtual machine e if it is not already running g. Start the 20483A-SEA A-DEV11-07 v virtual machine. Log on to o Windows 8 as a Student with the passwo rd. ord Pa$$w0r Note: If f necessary, click Switch Us ser to display the list of use ers. 4 4. 5 5. 6 6. 7 7. 8 8. 9 9. Switch to the Windows s 8 Start wind dow. Click Visu ual Studio 20 012. In Visual Studio, on the e File menu, p point to Open n, and then click Project/Solution. In the Op pen Project dialog box, bro owse to the E: :\Democode\ \Demo4\Fou urthCoffee.Em mployees folder, click FourthCo offee.Employ yees.sln, and t then click Ope en. In Solutio on Explorer, ex xpand Fourth hCoffee.Empl loyees, and th hen double-click Program.cs. Review th he LINQ code in each of the e methods.

1 On the Build menu, click Build Solu 10. ution. 1 On the Debug menu, c 11. click Start Wit thout Debugg ging. 1 In the con 12. nsole window w, review the o output of the UsingAnonymousTypes m method, and t then press Enter. 1 Repeat st 13. tep 12 for each of the follow wing methods: a. b. c. Grou upingData Aggr regatingData Navig gatingData

7-24

Accessing a Database

14. Press Enter to close the application. 15. In Visual Studio, on the File menu, click Close Solution.

Programming wit th Visual C#

7-25 5

F Forcing Q Query Exec cution

By default, wh B hen you define a LINQ query that return ns a sequence of values, it is s not run until you actually y t to use som try me of the returned data. This feature is known as defer rred query exe ecution and ensures that y can create a query to r you retrieve data in a multiple-u user scenario and know tha at whenever it t is executed y will receiv you ve the latest in nformation. I the followin In ng code exam mple, the quer ry is not actua ally executed u until the start of the foreac ch block. D Deferred Que ery Execution n
IQueryable< <Employee> emps e = from e in DBConte ext.Employee es select e; foreach (va ar emp in em mps) { Console e.WriteLine( ("{0} {1}", emp.FirstNam me, emp.Last tName); }

Conversely, w C when you defin ne a LINQ que ery that return ns a singleton n value, for exa ample, an Av verage, C Count , or Ma ax function, th he query is run n immediately y. This is know wn as immedia ate query exec cution and is n necessary in the singleton result r scenario o because the e query must produce p a seq quence to calc culate the s singleton resu ult. You can overr Y ride the defau ult deferred qu uery execution behavior fo or queries that t do not produce a s singleton resu ult by calling o one of the following metho ods on the query: ToArray ToDiction nary ToList

I the followin In ng code exam mple, the quer ry is executed immediately after it is defi ined.

7-26

Accessing a Database

Forcing Query Execution


IList<Employee> emps = (from e in DBContext.Employees select e;).ToList() foreach (var emp in emps) { Console.WriteLine("{0} {1}", emp.FirstName, emp.LastName); }

Programming wit th Visual C#

7-27 7

D Demonstr ration: Re etrieving and a Modif fying Grad de Data La ab

I this demon In nstration, you will learn abo out the tasks t that you will p perform in the e lab for this module. m

7-28 Accessin ng a Database

Lab: R Retrieving and d Modif fying Grade Da ata

Sc cenario
Yo ou have been asked to upgrade the proto otype applica ation to use an n existing SQL L Server datab base. You ntity Data be egin by workin ng with a data abase that is stored s on your local machin ne and decide e to use the En Mo odel Wizard to generate an n EDM to acce ess the data. Y You will need to update the e data access code for the e Grades secti ion of the app plication, to display grades that are assig gned to a stud dent and to en nable users to assign new grades. You als so decide to incorporate va alidation logic c into the EDM M to ensure th hat stu udents cannot t be assigned to a full class and that the data that use ers enter when n they assign new grades conforms to the e required valu ues.

Ob bjectives
Aft ter completing this lab, you u will be able to: EDM from an e existing datab base. Create an E Update dat ta by using the e .NET Entity Framework. Extend an E EDM to valida ate data.

timated Time: : 75 minutes Est Virtual Mac chine : 20483A A-SEA-DEV11-07, MSL-TMG G1 User Name: Student P Password: Pa$$w0rd

Programming with Visual C# 7-29

Exercise 1: Creating an Entity Data Model from The School of Fine Arts Database
Scenario
In this exercise, you will use the Entity Data Model Wizard to generate an EDM from the SchoolGradesDB SQL Server database and then review the model and the code that the wizard generates. The main tasks for this exercise are as follows: 1. Build and generate an EDM by using a table from the SchoolGradesDB database 2. Review the generated code

X Task 1: Build and generate an EDM by using a table from the SchoolGradesDB database
1. 2. 1. 2. 3. 4. 5. 6. Start the MSL-TMG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-07 virtual machine and log on as Student with the password Pa$$w0rd. Start Visual Studio, and from the E:\Labfiles\Starter\Exercise 1 folder, open the GradesPrototype.sln solution. Add a new class library project named Grades.DataModel to the solution. Add a new ADO.NET Entity Data Model named GradesModel to the Grades.DataModel project. Generate the model from the SchoolGradesDB database on the (localdb)\v11.0 server and include the following tables: Grades Students Subjects Teachers Users If the Security Warning dialog box appears, click Do not show this message again, and then click OK. Build the solution.

X Task 2: Review the generated code


1. 2. 3. 4. 5. 6. In the designer window, review the entities that the wizard generated. Review the properties and navigation properties of the Grade entity. Review the mapping details for the Grade entity. In the GradesModel.Context.tt folder, in GradesModel.Context.cs file, review the code for the SchoolGradesDBEntities DbContext object. In the GradesModel.tt folder, in the Grade.cs file, review the properties of the Grade entity. Save all of the files, and then close the solution.

Results: After completing this exercise, the prototype application should include an EDM that you can use to access The School of Fine Arts database.

7-30

Accessing a Database

Programming with Visual C# 7-31

Exercise 2: Updating Student and Grade Data by Using the Entity Framework
Scenario
In this exercise, you will add functionality to the prototype application to display the grades for a user. The grade information in the database stores the subject ID for a grade, so you will add code to the application to convert this to the subject name for display purposes. You will also add code to display the Add Grade view to the user and then use the information that the user enters to add a grade for the current student. Finally, you will run the application and verify that the grade display and grade-adding functionality works as expected. The main tasks for this exercise are as follows: 1. Display grades for the current student 2. Display the subject name in the UI 3. Display the GradeDialog view and use the input to add a new grade 4. Run the application and test the grade-adding functionality

X Task 1: Display grades for the current student


1. 2. 3. In Visual Studio, from the E:\Labfiles\Starter\Exercise 2 folder, open the GradesPrototype.sln solution. Set the GradesPrototype project to be the startup project. In the Views folder, in StudentProfile.xaml.cs, in the Refresh method, add code to the end of the method to: a. b. 4. 5. 6. 7. 8. Iterate through the grades in the session context object and, if they belong to the current student, add them to a new list of grades. Use data binding to display the list of grades in the studentGrades ItemsControl control.

Build the solution and resolve any compilation errors. Run the application. Log on as vallee with a password of password99. Click Kevin Liu, and then verify that his grades appear in the list. Note that the subject column uses the subject ID rather than the subject name, and then close the application.

X Task 2: Display the subject name in the UI


1. In Visual Studio, in StudentProfile.xaml.cs, in the SubjectConverter class, in the Convert method, add code to the method to: a. 2. Convert the subject ID that is passed into the method into the subject name.

Return the subject name or, if there is no subject name matching the subject ID, the string N/A.

X Task 3: Display the GradeDialog view and use the input to add a new grade
1. In StudentProfile.xaml.cs, in the AddGrade_Click method, add code to: a. b. Create and display a new instance of the GradeDialog view. If the user clicks OK in the GradeDialog view, retrieve the data they have entered and use it to create a new Grade object.

7-32

Accessing a Database

c.

Save the grade and refresh the display so that the new grade appears.

X Task 4: Run the application and test the grade-adding functionality


1. 2. 3. 4. 5. 6. 7. Build the solution, and then resolve any compilation errors. Run the application. Log on as vallee with a password of password99. Click Kevin Liu, and verify that the list of grades now displays the subject name, not the subject ID. Add a new grade for Kevin Liu using the following information: Subject: Geography Assessment: A+ Comments: Well done! Verify that the new grade is added to the list, and then close the application. In Visual Studio, close the solution.

Results: After completing this exercise, users will be see the grades for the current student and add new grades.

Programming with Visual C# 7-33

Exercise 3: Extending the Entity Data Model to Validate Data


Scenario
In this exercise, you will update the application to validate data that the user enters. First, you will add code to check whether a class is full before enrolling a student and throw an exception if it is. Then you will add validation code to check that a user enters a valid date and assessment grade when adding a grade to a student. Finally, you will run the application and verify that the data validation works as expected. The main tasks for this exercise are as follows: 1. Throw the ClassFullException exception 2. Add validation logic for the Assessment and AssessmentDate properties 3. Run the application and test the validation logic

X Task 1: Throw the ClassFullException exception


1. 2. 3. 4. 5. 6. 7. In Visual Studio, open the GradesPrototype.sln solution from the E:\Labfiles\Starter\Exercise 3 folder. Set the GradesPrototype project to be the startup project. Add a new class named customTeacher.cs to the Grades.DataModel project. Modify the class declaration to make it a public partial class named Teacher. Add a private integer constant named MAX_CLASS_SIZE with a value of 8 to the Teacher class. Add an EnrollInClass method that takes a Student object as a parameter and returns void. In the EnrollInClass method, add code to: Use a LINQ query to determine how many students are currently in the class.

Note: You can execute a Count query of the students in a particular class by selecting only those students with a TeacherUserId property equal to the contents of the UserId variable. 8. 9. If the class is full, throw a new ClassFullException exception. If the student who is passed to the method is not already enrolled in a class, set the TeacherID property of the Student object to the UserID of the current teacher.

10. Otherwise, throw a new ArgumentException exception. 11. In the Views folder, in the AssignStudentDialog.xaml.cs, locate the Student_Click method. 12. Towards the end of the method, before the call to the Refresh method, add code to: a. b. Call the EnrollInClass method to assign the student to this teachers class, passing the student as a parameter. Save the updated student/class information back to the database.

X Task 2: Add validation logic for the Assessment and AssessmentDate properties
1. 2. Add a new class named customGrade.cs to the Grades.DataModel project. Modify the class declaration to make it a public partial class named Grade.

7-34

Accessing a Database

3. 4.

Add a ValidateAssessmentDate method that takes a DateTime object as a parameter and returns a boolean. In the ValidateAssessmentDate method, add code to: a. b. c. d. If the DateTime object passed to the method is later than the current date, throw a new ArgumentOutOfRangeException exception. Otherwise, return true. Bring the System.Text.RegularExpressions namespace into scope. Add a ValidateAssessmentGrade method that takes a string as a parameter and returns a boolean.

5.

In the ValidateAssessmentGrade method, add code to: Use a regular expression to check that the string passed to the method is in the range of A+ to E.

Note: The pattern that you will need to use is: @"^[A-E][+-]?$" 6. 7. 8. 9. If the string passed is not in the valid range, throw a new ArgumentOutOfRangeException exception. Otherwise, return true. In the Views folder, in the GradeDialog.xaml.cs class, locate the ok_Click method. In this method, add code to: a. b. c. Create a new Grade object. Call the ValidateAssessmentDate method, passing the selected date in the assessmentDate date picker control. Call the ValidateAssessmentGrade method, passing the text in the assessmentGrade text box control.

X Task 3: Run the application and test the validation logic


1. 2. 3. 4. 5. 6. Build the solution, and then resolve any compilation errors. Run the application. Log on as vallee with a password of password99. Attempt to enroll a new student into the class, and then verify that an error message is displayed explaining that the class is already full. Click Kevin Lui, and then add a new grade for him by using the following information: Date: tomorrows date Subject: Math Assessment: F+ Comments: Well done! Verify that an error message is displayed explaining that the assessment date must be on or before the current date.

Programming with Visual C# 7-35

7. 8. 9.

Modify the new grade date by using the following information: Date: 8/19/2012 Subject: Math Assessment: F+ Comments: Well done! Verify that an error message is displayed explaining that the assessment grade must be in the range A+ to E-. Modify the new grade date by using the following information: Date: 8/19/2012 Subject: Math Assessment: A+ Comments: Well done!

10. Verify that the new grade is added to the list, and then close the application. 11. In Visual Studio, close the solution.

Results: After completing this exercise, the application will raise and handle exceptions when invalid data is entered.

7-36 Accessin ng a Database

Modu ule Revi iew and d Takea aways

M Module Revie ew
In this module, y you learned how h to create and use EDM Ms and how to o query many types of data by using LIN NQ. ying data? W advanta ages does LINQ provide ov ver traditional ways of query Question: What Test Your Know wledge Q Question F Fourth Coffee e wants you to o add custom m functionality y to an existing EDM in its s Coffee S Sales applicati ion. You need d to write a m method for ad dding a new p product to th he a application. In n which of the e following lo ocations shou uld you write your code? S Select the cor rrect answer. In the relevant gene erated class in n the EDM pro oject. In a pa artial class in the t EDM project.

8-1

Module 8
Accessing Remote Data
Contents:
Module Overview Lesson 1: Accessing Data Across the Web Lesson 2: Accessing Data in the Cloud Lab: Retrieving and Modifying Grade Data in the Cloud Module Review and Takeaways 8-2 8-3 8-19 8-34 8-42

8-2

Accessing g Remote Data

Modu ule Ove erview

Sys stems often consist of man ny component ts and services; some might be hosted w within your org ganizations inf frastructure, w whereas others could be ho osted in data c centers anywh here in the wo orld. The abilit ty for ap pplications to b be able to interact with suc ch services is a common req quirement in modern applications. In this module, y you will learn how to use the request an nd response cl lasses in the System.Net S n namespace to directly mani ipulate remote data source es. You will als so learn how t to use Window ws Commun nication Foundation (WC CF) Data Servi ices to expose e and consum me an entity da ata model (ED DM) over the web. w

Ob bjectives
Aft ter completing this module e, you will be able to: to and receive e data from w web services an nd other remo ote data sourc ces. Send data t Access data a by using WC CF Data Servic ces.

Programming g in Visual C#

8-3 3

Lesson 1

Acce essing Data D Ac cross the Web

Data is often e D exposed over r the web thro ough web serv vices or other application p programming interfaces ( (APIs). To be a able to consume such data sources in yo our application, you need a way to send and receive m messages so t that you can e establish a con nnection and ultimately send and receiv ve data. In this lesson, you will learn I n how to cons sume remote data sources such as web s services and F File Transfer P Protocol (FTP) ) sites, which w will include how to create a request, sup pply credentia als for authent tication, p package data into the requ uest, and proc cess data that is returned in n the response e.

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Describe how the Micr rosoft .NET Framework us ses requests and a responses s. Expose ty ypes from web b services by u using data contracts. Create a r request and p process a response. Provide c credentials or a security tok ken to enable the remote data source to perform auth hentication. Send and d receive data. .

8-4

Accessing g Remote Data

Ov verview o of Web Co onnectivity y in the .N NET Frame ework

The .NET Frame ework provide es the infrastru ucture to enab ble you to inte egrate your applications w with remote data sources. Th he remote dat ta source coul ld be anything g from an FTP P site to an AS SP.NET or WC CF Web Service. Wh hen consumin ng a remote d data source in your applicat tion, the .NET T Framework u uses requests and res sponses to pass messages b between the t two (or more) systems. This s involves the following steps: 1. 2. onnection to t the remote da ata source. This might inclu ude passing a security token n or user Initiate a co credentials so that the re emote data so ource can auth henticate you. Send a requ uest message to the remote e data source. This message may also include any dat ta that the remote data source requ uires to satisfy y the request, such as the id dentifier for th he sales record d you want to retrieve. Wait for the e remote data a source to pr rocess your request and issu ue a response e. As a develop per, you have no con ntrol over how w long it migh ht take to rece eive a response from a web b service. Process the e response, and extract any data that is in ncluded in the e response.

3. 4.

Note: Not t all communications have to include bo oth a request a and response message. De epending on t the nature of the applicatio on, it might on nly be applica able to send o one message. For example, if y your applicati ion wants to let a web service know that t it has finishe ed processing a tas sk, you only need to send a request. This s is known as a one-way op peration.

W Connec Web ctivity in the e .NET Fram mework


The .NET Frame ework provide es the System.Net namespace, which co ontains several request and response cla asses that enable you to tar rget different data sources. The following g table describes some of t these req quest and response classes. C Class W WebRequest Descripti ion An abstr ract class that provides the base infrastru ucture for any y request to a Uniform m Resource Id dentifier (URI) ).

Programming in Visual C# 8-5

Class WebResponse HttpWebRequest HttpWebResponse FtpWebRequest FtpWebResponse FileWebRequest FileWebResponse

Description An abstract class that provides the base infrastructure to process any response from a URI. A derivative of the WebRequest class that provides functionality for any HTTP web request. A derivative of the WebResponse class that provides functionality to process any HTTP web response. A derivative of the WebRequest class that provides functionality for any FTP request. A derivative of the WebResponse class that provides functionality to process any FTP response. A derivative of the WebRequest class that provides functionality for requesting files. A derivative of the WebResponse class that provides functionality to process a file response.

Depending on whether you want to send a request to a web service by using HTTP or you want to download a file from an FTP site, the .NET Framework provides the necessary classes for you to consume these remote data sources in your applications. Additional Reading: For more information about the System.Net namespace, see the System.Net Namespace page at http://go.microsoft.com/fwlink/?LinkID=267811.

8-6

Accessing g Remote Data

Defining a Data Cont tract

A remote r data s source can expose any type e of data. For example, a web service can n expose bina ary streams, sca alar values, or r custom objects. The choic ce of the type of data that y you expose is determined b by the req quirements of f your applica ation, but how w you expose it i is controlled d by the data contracts that you de efine in your w web services. If y you want to e expose a custo om object from m a web servi ice, you must provide meta adata that des scribes the str ructure of the object. The se erialization pr rocess uses th his metadata to convert you ur object into a tra ansportable fo ormat, such as s XML or JavaScript Object Notation (JSO ON). This meta adata provide es ins structions to t the serializer t that enable yo ou to control w which types a and members are serialized.

Da ata Contrac cts in the .N NET Framew work


The .NET Frame ework provide es the System.Runtime.Ser rialization na amespace, which includes the Da ataContract a and DataMem mber attribute es. You can us se these attrib butes to define serializable types and me embers. The following co ode example shows how to o define a seri ializable type by using the DataContrac ct and Da ataMember attributes. a De efining a Dat ta Contract
[ [DataContract t()] p public class SalesPerson n { [DataMembe er()] public string FirstNa ame { get; s set; } [DataMembe er()] public string Surname e { get; set t; } [DataMembe er()] public string Area { get; set; } [DataMembe er()] public string EmailAd ddress { get t; set; } }

Additiona al Reading: F For more infor rmation about the DataContract and DataMember att tributes, see th he DataContr ractAttribute C Class page at htt tp://go.micros soft.com/fwlin nk/?LinkID=26 67812.

Programming in Visual C# 8-7

8-8

Accessing g Remote Data

Cr reating a Request a and Proces ssing a Re esponse

The protocol that your remot te data source e uses determ mines the requ uest and respo onse classes yo ou must use e. Irrespective e of the classe es you use, you u can apply th he same patte ern to send a request and r receive a res sponse.

Th he HttpWeb bRequest a and HttpWe ebResponse e Classes


The following st teps describe how to send an HTTP requ uest to a web service and process the res sponse by usi ing the HttpW WebRequest and HttpWe ebResponse c classes: 1. Get a URI to o the web serv vice to which you want to send a reques st. The followi ing code exam mple shows an HTTP UR RI that addres sses the GetSa alesPerson m method in the Fourth Coffee e Sales Service e.
var uri = "http://sa ales.fourthco offee.com/Sa alesService.svc/GetSalesPerson";

2.

Create a req quest object t to configure the request an nd access the response. The e following co ode example shows how to create an Http pWebReques st object.
var reque est = WebReq quest.Create(uri) as Htt tpWebRequest t;

Note: Reg gardless of the e type of requ uest object yo ou require, you u always use t the static Create method that the Web bRequest bas se class exposes and then c cast to the typ pe of request you require. 3. ponse from th he request obj bject. The follo owing code ex xample shows s how to get the Get the resp response fro om an HttpW WebRequest object. o
var respo onse = reque est.GetResponse() as Htt tpWebRespons se;

Note: Sim milar to creatin ng a request object, o you cre eate a response object by invoking the Ge etResponse m method on the e WebRequest object, and d you then cas st to the type of response you require.

Programming in Visual C# 8-9

4.

Access and process the response by using the various members that the WebResponse object provides. The following code example shows how to use and view the status of the response by using the StatusCode property.
var status = response.StatusCode; // Returns OK if a response is received.

If the remote data source uses a different protocol, such as FTP, you can apply the same pattern but use the FtpWebRequest and FtpWebResponse classes instead.

Handling Network Exceptions


When consuming any remote resources, whether an FTP site or an HTTP web service, you cannot guarantee that the resource is online and listening for your request. If you try to send a request to a web service by using the HttpWebRequest class and the web service is not online, the GetResponse method call will throw a WebException exception with the following message: WebException The remote server returned an error: (404) Not Found. Similarly, if you try to access a secure web service with the wrong credentials or security token, the GetResponse method call will throw a WebException exception with the following message: WebException The remote server returned an error: 401 unauthorized If you do not handle these exceptions in your code, they will cause your application to fail, offering a poor user experience. Therefore, as a minimum, you should enclose any logic that communicates with a remote data source in a try/catch statement, with the catch block handling exceptions of type WebException.

8-10 Accessin ng Remote Data

Au uthenticat ting a We eb Reques st

Re emote data so ources are ofte en protected to t prevent unauthorized us sers from usin ng the service and gaining access t to data. Expos sing an unpro otected data so ource over the web can lea ad to unautho orized users sen nding request ts and increas sing the load on o the data so ource. There a are many way ys in which you can sec cure remote d data sources. One O approach h is to authenticate each us ser who attem mpts to conne ect to the rem mote data sou urce.

Ty ype of Auth hentication


The following ta able describes s some of the common authentication te echniques tha at you can use e to secure rem mote data sou urces. A Authentication mechanism m B Basic De escription En nables users to o authenticate e by using a u user name and d password. Ba asic authentica ation does no ot encrypt the credentials w while in tra ansit, which means m that una sers may access the authorized us cre edentials. En nables users to o authenticate e by using a u user name and d password, bu ut unlike basic c authenticatio on, the credentials are encrypted. En nables clients to authenticate by using th heir Windows domain cre edentials. Win ndows authen ntication uses either hashing or a Ke erberos token to securely authenticate users. Window ws au uthentication is typically use e a single sign-on (SSO) ed to provide ex xperience in o organizations. En nables only clients that have e the correct certificate installed to au uthenticate wi ith the service e.

D Digest W Windows

C Certificate

The nature of th he service and d where it is hosted are like ely to influence an organiza ations choice of authentication m mechanism. For example, a service that is i exposed ov ver an organiz zations intranet might use e Windows au uthentication so that users can authentic cate by using their Active D Directory Do omain Services (AD DS S) credentials. Using Window ws authentica ation in this sc cenario will pr rovide the use ers with an SSO experience and not requ uire them to re emember cred dentials for ea ach service th hey consume.

Programming in Visual C# 8-11

The .NET Framework provides a number of classes that you can use to authenticate with a secure remote data source.

Authenticating Users by Using Credentials


When communicating with a remote data source that requires a user name and password, you use the Credentials property that is exposed by any class that is derived from the WebRequest base class to pass the credentials to the data source. You can set the Credentials property to any object that implements the ICredentials interface: The NetworkCredential class implements the ICredentials interface and enables you to encapsulate a user name and password. The following code example shows how to instantiate a NetworkCredential object and pass values for the user name and password to the class constructor.
var uri = "http://Sales.FourthCoffee.com/SalesService.svc/GetSalesPerson"; var username = "jespera"; var password = "Pa$$w0rd"; var request = WebRequest.Create(uri) as HttpWebRequest; request.Credentials = new NetworkCredential(username, password);

The CredentialCache class provides a number of members that enable you to get credentials in the form of an ICredentials object. These members include the DefaultCredentials property, which returns an ICredentials object containing the credentials that the user is currently logged on with. The following code example shows how to use the DefaultCredentials property to get the current users credentials.
var uri = "http://Sales.FourthCoffee.com/SalesService.svc/GetSalesPerson"; var request = WebRequest.Create(uri) as HttpWebRequest; request.Credentials = CredentialCache.DefaultCredentials;

Authenticating users by using basic or Windows authentication is common, but it does require users to remember and provide credentials. Alternatively, you may choose to authenticate clients by using an X509 certificate. Additional Reading: For more information about the NetworkCredential class, see the NetworkCredential Class page at http://go.microsoft.com/fwlink/?LinkID=267813.

Authenticating Users by Using an X509 Certificate


You can use an X509 certificate as a security token to authenticate users. Instead of users having to specify credentials when they access the remote data source, they will automatically gain access as long as the request that is sent includes the correct X509 certificate. To the users, this means they need the correct X509 certificate in their certificate store on the computer where the client application is running. The following code example shows how you can create an HttpWebRequest object and add an X509 certificate to the request object by using the ClientCertificates property. HttpWebRequest and x509 Certificates
var uri = "http://Sales.FourthCoffee.com/SalesService.svc/GetSalesPerson"; var certificate = FourthCoffeeCertificateServices.GetCertificate(); var request = WebRequest.Create(uri) as HttpWebRequest; request.ClientCertificates.Add(certificate);

When the remote data source receives the request, it must extract and process the X509 certificate. If the X509 certificate is invalid, the remote data source can return a suitable response, such as a "The remote server returned an error: 401 unauthorized" message.

8-12

Accessing Remote Data

Note: The GetCertificate method of the web service that is shown in the previous example returns an X509Certficate2 object. This type provides programmatic access to the properties of the X509 certificate.

Programming in i Visual C#

8-13 3

S Sending a and Receiv ving Data

You use reque Y ests and respo onses to send data to or ret trieve data fro om a remote data source. F For example, y may want you t to add a new w record to a web service o or retrieve a fi ile from an FT TP site. Each derivativ E ve of the Web bRequest and d WebRespon nse classes en nables you to s send and rece eive data by u using the spec cific protocol that the class s implements. For example, , the HttpWebRequest cla ass enables y to send re you equests to a web w service by y using the HT TTP protocol. The WebRequest base clas T ss includes the following m members that you can use t to send data to a remote d data source: ContentT Type. This pro operty enable es you to set th he type of dat ta that the req quest will send. For example, if you are sen nding JSON data by using t the HttpWeb bRequest class, you use the e applicati ion/json cont tent type. Method. This property y enables you to set the typ pe of method that the Web bRequest obj ject will use to send th he request. Fo or example, if you are uploa ading a file by y using the Ft tpWebReque est class, you use the STOR method. . ContentL Length. This p property enab bles you to set t the number of bytes that the request w will send. GetRequestStream. This method enables you to o access and w write data to the underlying g data stream in the req quest object.

The WebResp T ponse class provides the GetResponseS Stream metho od, which ena ables you to ac ccess and s stream data fr rom the respo onse.

S Sending Da ata to a Rem mote Data Source


Whether you are sending d W data to a web service or up ploading a file to an FTP site e, the process s for creating t request re the emains the sam me: 1 1. 2 2. 3 3. 4 4. Get the U URI to the rem mote data sour rce and the da ata you want to send. Create the request object. Configure e the request object, which h includes sett ting the reque est method an nd the length of the data that the r request will se end. Stream th he data to the e request obje ect.

8-14

Accessing Remote Data

The following code example shows how to use a POST operation to send a JSON string to a web service by using the HttpWebRequest class. Sending Data to a Web Service
// Get the URI and the data. var uri = "http://sales.fourthcoffee.com/SalesService.svc/GetSalesPerson"; var rawData = Encoding.Default.GetBytes("{\"emailAddress\":\"jesper@fourthcoffee.com\"}"); // Create the request object. var request = WebRequest.Create(uri) as HttpWebRequest; // Configure the type of data the request will send. request.Method = "POST"; request.ContentType = "application/json"; request.ContentLength = rawData.Length; // Stream the data to the request. var dataStream = request.GetRequestStream(); dataStream.Write(rawData, 0, rawData.Length); dataStream.Close();

The following code example shows how to upload a file to an FTP site by using the FtpWebRequest class. Uploading a File to an FTP Site
// Get the URI and the data. var uri = "ftp://sales.fourthcoffee.com/FileRepository/SalesForcast.xls"; var rawData = File.ReadAllBytes("C:\\FourthCoffee\\Documents\\SalesForecast.xls"); // Create the request object. var request = WebRequest.Create(uri) as FtpWebRequest; // Configure the type of data the request will send. request.Method = WebRequestMethods.Ftp.UploadFile; request.ContentLength = rawData.Length; // Stream the data to the request. var dataStream = request.GetRequestStream(); dataStream.Write(rawData, 0, rawData.Length); dataStream.Close();

Receiving Data from a Remote Data Source


To get data that a response might contain, you use the GetResponseStream method of the response object. The GetResponseStream method returns a stream, which you can read to get the data. The following code example shows how to use the GetResponseStream method to access the response data. Reading Data from the Response
var request = WebRequest.Create(uri) as HttpWebRequest; ... var response = request.GetResponse() as HttpWebResponse; var stream = new StreamReader(response.GetResponseStream()); // Code to process the stream. stream.Close();

When you have acquired the response stream, you must then verify that the data is in the correct format. For example, if the response that is returned is in the JSON format, you can use the DataContractJsonSerializer class to serialize the raw JSON data into an object that you can consume in your code. Alternatively, if the data is in the XML format, you can use the SoapFormatter class to deserialize the data or Language-Integrated Query (LINQ) to XML to manually parse the XML. Additional Reading: For more information about LINQ to XML, see the LINQ to XML page at http://go.microsoft.com/fwlink/?LinkID=267814.

Programming in Visual C# 8-15

8-16 Accessin ng Remote Data

Demonstration: Con nsuming a Web Serv vice

In this demonstration, you wi ill use the Htt tpWebReque est and HttpW WebResponse e classes to co onsume a we eb service ove er HTTP. The application will use the S System.Net classes to get s sales people r records from t the Fourth Co offee Sale Service. You will send a reque est that will co ontain the em mail address of f the sale pers son record you want to ge et in the JSON format, process the respon nse, and then display the re ecord details in the UI.

De emonstration Steps
1. 2. Start the 20 0483A-SEA-DE EV11-08 virtual machine. Log on to W Windows 8 as Student with h the password Pa$$w0rd. Note: If necessary, click k Switch User r to display th he list of users s. 3. 4. 5. 6. 7. 8. 9. he Windows 8 Start window w. Switch to th Click Visual Studio 2012. udio, on the F File menu, point to Open, and a then click k Project/Solution. In Visual Stu In the Open n Project dialo og box, brows se to E:\Demo ocode\Starter\ \Fourth Coffee e Contact Find der folder, click Fourth h Coffee Conta act Finder.sln, , and then clic ck Open. In the Solut tion Explorer r window, exp pand the Four rthCoffee.Da ataService pro oject, and the en doubleclick ISalesS Service.cs. In the code e editor, review w the signatur re of the GetS SalesPerson operation, o wh hich accepts an email address in t the form of a JSON string and a returns a SalesPerson object. In the Solut tion Explorer r window, exp pand the Four rthCoffee.Inf frastructure project, p expan nd the Models folder, and then n double-click SalesPerson.cs.

0. In the code e editor, review w the DataCo ontract and D DataMember attributes tha at decorate th he type and 10 type memb bers. ft Visual Studio o, on the Vi iew menu, click Task List. 11. In Microsof

Programming in Visual C# 8-17

12. In the Task List window, in the Categories list, click Comments. 13. Double-click the TODO: 01: Bring the System.Net namespace into scope. task. 14. In the code editor, click in the blank line below the comment, and then type the following code:
using System.Net;

15. In the Task List window, double-click the TODO: 02: Declare a global object to encapsulate an HTTP request. task. 16. In the code editor, click in the blank line below the comment, and then type the following code:
HttpWebRequest _request;

17. In the Task List window, double-click the TODO: 03: Instantiate the _request object. task. 18. In the code editor, click in the blank line below the comment, and then type the following code:
this._request = WebRequest.Create( this._serviceUri.AbsoluteUri) as HttpWebRequest;

19. In the Task List window, double-click the TODO: 04: Configure the request to send JSON data. task. 20. In the code editor, click in the blank line below the comment, and then type the following code:
this._request.Method = "POST"; this._request.ContentType = "application/json"; this._request.ContentLength = rawData.Length;

21. In the Task List window, double-click the TODO: 05: Write data to the request stream. task. 22. In the code editor, click in the blank line below the comment, and then type the following code:
var dataStream = this._request.GetRequestStream(); dataStream.Write(data, 0, data.Length); dataStream.Close();

23. In the Task List window, double-click the TODO: 06: Create an HttpWebResponse object. task. 24. In the code editor, click in the blank line below the comment, and then type the following code:
var response = this._request.GetResponse() as HttpWebResponse;

25. In the Task List window, double-click the TODO: 07: Check to see if the response contains any data. task. 26. In the code editor, click in the blank line below the comment, and then type the following code:
if (response.ContentLength == 0) return null;

27. In the Task List window, double-click the TODO: 08: Read and process the response data. task. 28. In the code editor, click in the blank line below the comment, and then type the following code:
var stream = new StreamReader(response.GetResponseStream()); var result = SalesPerson.FromJson(stream.BaseStream); stream.Close();

29. On the Build menu, click Build Solution.

8-18

Accessing Remote Data

30. In Solution Explorer, right-click Fourth Coffee Contact Finder, and then click Set as StartUp Project. 31. On the Debug menu, click Start Debugging. 32. In the Fourth Coffee Contract Finder application, in the Search box, type jesper@fourthcoffee.com, and then click GO. 33. In the Search Successful dialog box, click OK. 34. Verify that the details for Jesper Herp are displayed. 35. On the Debug menu, click Stop Debugging. 36. Close Visual Studio.

Programming in i Visual C#

8-19 9

Lesson 2

Acce essing Data D in the Clo oud

WCF Data Ser W rvices follows the Representational State e Transfer (RES ST) architectural model and d uses open w standards such as the Open Data Pr web rotocol (ODat ta) to expose and consume e data over the e web. By f following thes se standards, you can build d solutions based on WCF D Data Services that a wide va ariety of c client applicat tions can easily access, rega ardless of the technology that is used to o implement the client a application. a Service and how to define which entiti In this lesson, you will learn I n how to creat te a WCF Data ies and o operations yo ou want to exp pose. You will also learn ho ow to create a client library and how to c consume the e entities and o operations that you have ex xposed.

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Describe the purpose o of a WCF Data a Service. Define a W WCF Data Ser rvice. Expose a data model b by using a WC CF Data Servic ce. Expose w web methods b by using a WC CF Data Servic ce. Create a c client library a and reference e a WCF Data Service. Retrieve a and manipula ate entities tha at a WCF Data a Service expo oses.

8-20 Accessin ng Remote Data

W What Is WC CF Data Se ervices?

WC CF Data Servic ces enables yo ou to create a and access dat ta services ov ver the web. Yo ou expose your data as res sources that a applications ca an access by u using a URI. These resource es are exposed d as sets of en ntities that are e related by associations, th he same concepts as in an EDM. Howeve er, you can ex xpose data fro om many typ pes of storage e, including da atabases and Common Lan nguage Runtim me (CLR) class ses. WC CF Data Servic ces uses URIs to address da ata and simple e, well-known n formats to re epresent that data, such as XML and Ato om. This result ts in data bein ng served as a REST-style re esource collec ction. RE EST has becom me a popular m model for imp plementing web services th hat need to ac ccess data (oth her models, suc ch as those ba ased on the W WebRequest/ /WebResponse model des scribed in the previous lesso on, are mo ore suited to invoking i remo ote methods). REST describ bes a stateless s, hierarchical scheme for re epresenting res sources and b business objec cts over a netw work. Resourc ces are accesse ed through URIs that identify the data to retrieve. For example, e Fourth Coffee mig ght choose to o make the da ata for all of it ts sales people e available thr rough the foll lowing URI: htt tp://FourthCo offee.com/Sale esService.svc/S SalesPersons The data for a specific sales p person could b be fetched by y specifying th he identifier (s such as a sales s person nu umber) for tha at sales person n, like this: htt tp://FourthCo offee.com/Sale esService.svc/S SalesPersons/ /99 Sim milarly, the de etails of produ ucts that it sells might be av vailable throu ugh the follow wing URI: htt tp://FourthCo offee.com/Sale esService.svc/Products The details for a specific prod duct could be retrieved by including the product ID in n the URI: tp://FourthCo offee.com/Sale esService.svc/Products/25 htt Note: The e exact URI scheme that a w web service us ses to expose data is a deci ision of the org ganization tha at implements the web serv vice, but the e examples that t are shown here illustrate a common patter rn. TTP GET queri ies to retrieve data, but the e REST model also supports s insert, The REST model performs HT up pdate, and delete operation ns by using HT TTP PUT, POST, and DELETE requests.

Programming in Visual C# 8-21

The REST model enables a web service to extend URIs to support filtering, sorting, and paging of data. For example, the following URI sends a request that fetches the first 10 sales people only: http://FourthCoffee.com/SalesService.svc/SalesPersons?top=10 The list of filters and other functionality depends on how the web service is implemented, but features such as these are available with WCF Data Services. Additionally, WCF Data Services enables you to extend your web services by writing service operations as methods that perform business logic at the server. These methods are then accessible as URIs in a similar manner to resources. You can also define interceptors, which are called when you query, insert, update, or delete data and can validate or modify the data, enforce security, or reject the change. Additional Reading: For more information about WCF Data Services, see the WCF Data Services page at http://go.microsoft.com/fwlink/?LinkID=267815.

8-22 Accessin ng Remote Data

Defining a WCF Data a Service

By y using WCF D Data Services, you can expo ose data from relational dat ta sources suc ch as Microsof ft SQL Server through an EDM con nceptual sche ema that is cre eated by using g the ADO.NE ET Entity Fram mework, and you can enable a client applic cation to query and mainta ain data by us sing this schem ma. Note: WC CF Data Servic ces can also ex xpose non-relational data, but this requires building customized clas sses. WCF Data Services ope erates most naturally with t the model tha at the ADO.NET Entity Framework presents. A WCF W Data Ser rvice is based on the System m.Data.Servi ices.DataServ vice generic class. c This class expects a typ pe parameter that is a colle ection contain ning at least one property t that implemen nts the IQuery yable int terface, such a as the DbCon ntext class for an entity set that is defined by using the Entity Framework. The Da ataService typ pe implement ts the basic fu unctionality to o expose the entities e in this collection as a series of RE EST resources. ode example shows the definition of a W WCF Data Serv vice based on a DbContex xt class The following co called FourthCo offee that is ge enerated by u using the ADO O.NET Entity Framework. efining a Dat ta Service De
p public class FourthCoffe eeDataServic ce : DataServ vice<FourthC Coffee> { ... }

Yo ou can implem ment methods s in a WCF Data Service tha at specify the e entities to exp pose from the e underlying ED DM and that configure the s size of datase ets that the da ata service pre esents. You can also overrid de methods tha at are inherite ed from the D DataService cl lass to custom mize the way in which the service operate es. By y default, WCF F Data Service es uses a simple addressing scheme that exposes the e entity sets that are de efined within t the specified E EDM. When y you consume a WCF Data S Service, you ad ddress these e entity res sources as an entity set that contains instances of an e entity type. Fo or example, su uppose that th he fol llowing URI (s shown in the p previous topic c) returns all of o the SalesPe erson entities that were defined in the ED DM that was used to construct a WCF Da ata Service: htt tp://FourthCo offee.com/Sale esService.svc/S SalesPersons

Programming in Visual C# 8-23

The "/SalesPersons" element of the URI points to the SalesPersons entity set, which is the container for SalesPerson instances. Additional Reading: For more information about defining a WCF Data Service, see the Exposing Your Data as a Service (WCF Data Services) page at http://go.microsoft.com/fwlink/?LinkID=267816.

8-24 Accessin ng Remote Data

Ex xposing a Data Mod del by Usi ing WCF Data D Servi ices

For security reas sons, WCF Da ata Services do oes not autom matically expo ose any resour rces, such as e entity collections, that t the EDM imp plements. You u specify a policy that enab bles or disables access to resources in the e InitializeService method d of your data a service. This method takes s a DataServi iceConfiguration object, wh hich has a Set tEntitySetAcc cessRule prop perty that you u use to define e the access p policy. The following co ode example shows how to o allow access s to all resourc ces that the WCF W Data Serv vice exposes. Da ata Service Access to all E Entities
p public class FourthCoffe eeDataServic ce : DataServ vice<FourthC Coffee> { public st tatic void I InitializeSe ervice(DataSe erviceConfig guration con nfig) { confi ig.SetEntity ySetAccessRu ule("*", Enti itySetRights s.All); } }

The parameters to the SetEntitySetAccessRule method d are the nam me of a resource and the ac ccess rights to grant over th hat resource. Y You can specif fy a resource explicitly, or y you can use wildcard w characters. The * value that is sho own in the cod de example is s a shorthand way of specif fying all resou urces that the WCF Data Service publishe es. The EntitySetRights.All l value grants s unrestricted access to thes se resources. te Note: Enu umerations an nd partial class ses that are im mplemented in an EDM do not propagat thr rough WCF D Data Services. If I you want to o expose enum merations and d extensions to o partial class ses, you should inclu ude these types in a separa ate assembly t that you can r reference in th he service and d clie ent applicatio on directly. Additiona al Reading: F For more infor rmation about defining acc cess rules in a WCF Data Service, see the Configuring the Data Ser rvice (WCF D Data Services) ) page at htt tp://go.micros soft.com/fwlin nk/?LinkID=26 67817.

Programming in i Visual C#

8-25 5

E Exposing Web Met thods by U Using WCF Data Services

The primary purpose T p of a WCF W Data Serv vice is to prov vide access to data. However, you can also implement t c custom opera ations that ma anipulate data a. A WCF Data a Service oper ration is simply a method o of the data s service that is visible to the e REST infrastr ructure and th hat can be acc cessed by send ding an HTTP P GET, PUT, P POST, or DELE ETE request. WCF Data Ser W rvices operatio ons that are a accessed by us sing a GET req quest should be b annotated with the W WebGet attribute. These o operations typ pically return d data, although h they may ru un some busin ness logic that t d does not return a value. Op perations that t are accessed d by using PUT T, POST, or DE ELETE request ts should be a annotated wit th the WebIn nvoke attribut te. These oper rations typically modify the e data that the e service uses i some way. in Similar to entity sets, you m S must explicitly y enable acces ss to operation ns that a WCF F Data Service e exposes. Y can do th You his by calling t the SetServic ceOperationA AccessRule m method of the D DataServiceC Configuration n object when n you initialize e the service. You specify th he name of th he operation a the appro and opriate access s rights. A data service e operation ca an take param meters and returns one of th he following d data types: IEnumera able<T> or IQ Queryable<T T> (where T represents r an entity type in the service). If an operation n returns an enumerable co ollection based on an entity y type that the service reco ognizes, a client app plication can p perform queri ies by specifyi ing HTTP URIs s in the mann ner shown in t the previous topics in t this lesson. Im mplementing an a operation that returns a an enumerable e collection in n this way gives you u detailed control over the contents of th he collection. It is the respo onsibility of yo our code to generate this collection n, possibly based on inform mation that th he client applic cation provide es. The following g code example shows an o operation that t retrieves sale es people per area.
public class FourthCoffeeDataS Service : Da ataService<FourthCoffee> > { pub blic static void Initial lizeService( ( DataServiceConfigurati ion config) { ... config.SetServiceOpera ationAccessR Rule("SalesPersonByArea" ", ServiceOperationRi ights.ReadMu ultiple); } ... [We ebGet]

8-26

Accessing Remote Data

public IQueryable<SalesPerson> SalesPersonByArea(string area) { if (!String.IsNullOrEmpty(area)) { return from p in this.CurrentDataSource.SalesPerson where String.Equals(p.Area, area) select p; } else { throw new ArgumentException("Area must be specified", "area"); } } }

You can invoke this operation by using the following URI: http://<hostName>/FourthCoffee/FourthCoffeeDataService.svc/SalesPersonByArea?area='snacks' T (where T represents an entity type in the service). An operation can return a single instance of an entity. The following code example shows an operation that retrieves a sales person record that has a specific email address. Notice that you should also annotate an operation that returns a scalar value with the SingleResult attribute.
public class FourthCoffeeDataService : DataService<FourthCoffee> { public static void InitializeService( DataServiceConfiguration config) { ... config.SetServiceOperationAccessRule("SalesPersonByEmail", ServiceOperationRights.ReadMultiple); } ... [WebGet] [SingleResult] public SalesPerson SalesPersonByEmail(string emailAddress) { return (from p in this.CurrentDataSource.SalesPerson where String.Equals(p.Area, area) select p).SingleOrDefault(); } }

A primitive value. The following code example shows an operation that retrieves a count of all of the sales people and returns the count value as an int.
public class FourthCoffeeDataService : DataService<FourthCoffee> { public static void InitializeService( DataServiceConfiguration config) { ... config.SetServiceOperationAccessRule("SalesPersonCount", ServiceOperationRights.ReadSingle); } ... [WebGet] [SingleResult] public int SalesPersonCount() { return (from p in this.CurrentDataSource.SalesPerson select p).Count(); } }

Programming in Visual C# 8-27

void. Not all operations have to return a value.

Additional Reading: For more information about service operations, see the Service Operations (WCF Data Services) page at http://go.microsoft.com/fwlink/?LinkID=267818.

8-28 Accessin ng Remote Data

Re eferencing g a WCF D Data Sourc ce

The client library for a WCF D Data Service consists of a class that is der rived from the e DataService eContext typ pe that exposes one or more DataServic ceQuery obje ects as properties. The name of this class s is usually the e same as the e name of the DbContext o object that is used u by the EDM on which h the WCF Dat ta Service is based. For exam mple, the Four rthCoffeeDat taService WC CF Data Service uses a DbCo ontext object t called Fo ourthCoffeeEntities to con nnect to the underlying EDM, so the nam me of the DataServiceCont text type tha at is generate ed for the clien nt library is als so FourthCof ffeeEntities. The DataServic ceContext class performs a similar role to the DbContext class in t the Entity Fram mework. A clie ent applicatio on connects to o the data sou urce through a DataService eContext obj ject and fetches the data for r the entities t that the data service exposes by using th he DataServic ceQuery prop perties. Each Da ataServiceQu uery property is a generic c collection obje ect that presents data from m one of the underlying entities that pro ovides the dat ta for the WCF F Data Service e. es definitions of the types t that each Dat taServiceQue ery collection contains. A The client library also provide ent applicatio on can perform m LINQ querie es against the e DataService eQuery collection propertie es, and the clie clie ent library con nstructs the appropriate HT TTP request to o fetch the co orresponding data. The WC CF Data Service fetches t the matching data and pop pulates the Da ataServiceQu uery collection. The client a application can then iterate e through this collection and retrieve the e data for each h item. Yo ou can generate the client library for a W WCF Data Serv vice by using t the Add Servi ice Reference e dialog bo ox in Visual Stu udio or by usi ing the WCF D Data Service client c utility, D DataSvcUtil, fro om the comm mand line.

Ad dding a Ser rvice Refere ence


bles you to Yo ou can use the e Add Service e Reference dialog d box in a client applic cation. This dialog box enab spe ecify the URL of the WCF D Data Service to o connect to. The dialog bo ox sends a me etadata query y to the spe ecified URL, and it uses the e response to generate the appropriate D DataServiceC Context class that contains the Da ataServiceQuery properties and the clas sses for each o of the entities s that the WCF F Data Service exposes. The returned d metadata is stored in the client project t as an .edmx file. This is no ot the same as an .edmx file that is genera ated by using g the ADO.NET T Entity Data Model Design ner (it has a different for rmat), but you u can view this metadata file by using th he XML editor or any text editor.

Programming in Visual C# 8-29

To add a data service reference, perform the following steps: 1. 2. 3. 4. 5. If the data service is not part of the solution and is not already running, start the data service and note its URI. In Solution Explorer, right-click the client project, and then select Add Service Reference. If the data service is part of the current solution, click Discover. Alternatively, if the data service is not part of the current solution, in the Address box, type the base URL of the data service, and then click Go. Click OK. After you have referenced the WCF Data Service, you can then consume the entities and service operations that it exposes. Additional Reading: For more information about creating a service reference by using the command line, see the WCF Data Service Client Utility (DataSvcUtil.exe) page at http://go.microsoft.com/fwlink/?LinkID=267819.

8-30 Accessin ng Remote Data

Re etrieving a and Upda ating Data a in a WCF F Data Ser rvice

Aft ter you have referenced r the WCF Data Service S by gen nerating a clie ent library, you u can then co onsume the ED DM and any se ervice operatio ons that the s service expose es.

Re etrieving Data
To o retrieve data a from a WCF Data Service by using the client c library, perform the f following step ps: 1. Create an in nstance of the e type that is derived d from the DataServ viceContext c class in the client library, and then co onnect to the WCF Data Se ervice. The con nstructor for t this class expe ects a Uri obje ect that contains the e address of t the service. Retrieve data by querying the appropriate DataSer rviceQuery co ollection in th he DataServic ceContext object. Whe en you query a DataServic ceQuery colle ection, the clie ent library con nstructs an HT TTP request that specifie es the resourc ce and any criteria that is re equired. The q query is transm mitted to the WCF Data Service, and d the data is returned and used u to populate the DataServiceQuery y object. Iterate through the items s in the DataS ServiceQuery y collection an nd process the e objects that t are returned.

2.

3.

The following co ode example connects to the FourthCoff feeDataServic ce WCF Data S Service by using the Fo ourthCoffeeEntities type in n the client lib brary (this is th he class that is derived from m DataServic ceContext). The parameter to t the constru uctor is the ad ddress of the s service. The co ode then queries the Sales sPersons Da ataServiceQu uery property to fetch all sa ales people an nd reads the e email address for each reco ord. Qu uerying the FourthCoffee F eDataService WCF Data Se ervice
F FourthCoffeeE Entities con ntext = new FourthCoffee eEntities (n new Uri ("http:// /FourthCoffe ee.com/Fourt thCoffeeDataS Service.svc" ")); f foreach (Sale esPerson per rson in cont text.SalesPersons) { var email l = product. .EmailAddres ss; }

Yo ou can also mo odify data by invoking any custom servic ce operations s that you may y have expose ed in the WC CF Data Servic ce. You can in nvoke service operations by y using the Ex xecute metho od of the Da ataServiceContext class. The value that the Execute method retur rns is an enum merable collec ction. If the ser rvice operatio on returns a single, scalar va alue, you shou uld extract tha at value from the collection n by using am method such as First.

Programming in Visual C# 8-31

The following code example shows how to invoke the SalesPersonByArea service operation and iterate the results. Querying the FourthCoffeeDataService WCF Data Service by Using a Service Operation Querying the FourthCoffeeDataService
FourthCoffeeEntities context = new FourthCoffeeEntities (new Uri ("http://FourthCoffee.com/FourthCoffeeDataService.svc")); foreach (SalesPerson person in context.Execute<SalesPerson> (new Uri("/SalesPersonByArea?area='snacks'", UriKind.Relative))) { var email = product.EmailAddress; }

Modifying Data
After you have retrieved data, you can modify the entities as you would when working with an EDM and then save your changes back to the WCF Data Service. The DataServiceContext class provides the following methods that enable you to work with the entities in your EDM. AddToXXXX. These methods enable you to add a new entity to the entity collection. The following code example shows how to use the AddToSalesPersons method to add a new SalesPerson entity.
FourthCoffeeEntities context = new FourthCoffeeEntities (new Uri ("http://FourthCoffee.com/FourthCoffeeDataService.svc")); ... var newSalesPerson = new SalesPerson { Area = "tea", EmailAddress = "roy@fourthcoffee.com", FirstName = "Roy", Surname = "Antebi" }; context.AddToSalesPersons(newSalesPerson); context.SaveChanges();

DeleteObject. This method enables you to remove an existing object from the entity collection. The following code example shows how to use the DeleteObject method to delete a sales person with the email address roya@fourthcoffee.com.
FourthCoffeeEntities context = new FourthCoffeeEntities (new Uri ("http://FourthCoffee.com/FourthCoffeeDataService.svc")); ... var salesPerson = (from p in context.SalesPersons where p.EmailAddress.Equals("roy@fourthcoffee.com") select p).Single(); context.DeleteObject(salesPerson); context.SaveChanges();

UpdateObject. This method enables you to update an existing object in the entity collection. The following code example shows how to use the UpdateObject method to change the area to which a sales person belongs.
FourthCoffeeEntities context = new FourthCoffeeEntities (new Uri ("http://FourthCoffee.com/FourthCoffeeDataService.svc")); ... var salesPerson = (from p in context.SalesPersons where p.EmailAddress.Equals("roy@fourthcoffee.com") select p).Single(); salesperson.Area = "soft drinks";

8-32

Accessing Remote Data

context.UpdateObject(salesPerson); context.SaveChanges();

Implementing Eager Loading of Entities


When retrieving data by using WCF Data Services, by default only the entity you requested is returned in the response. For example, the SalesPerson entity in the FourthCoffeeEntities object is related to the Sales entity. When you request a SalesPerson entity, the response will not include the related Sales entity. However, you can use the Expand or LoadProperty methods to get related entities. Using the eager loading strategy that the Expand method implements causes the data for the specified related entities to be retrieved as part of the same request that fetches the primary data for the query. This approach is useful if you know that you will always need this related data, but it can be wasteful of bandwidth for the cases where you do not actually use these entities. The following code example shows how to use the Expand method to fetch the sales associated with each SalesPerson object. Eager Loading of Entities
FourthCoffeeEntities context = new FourthCoffeeEntities (new Uri ("http://FourthCoffee.com/FourthCoffeeDataService.svc")); var salesPersons = (from s in context.SalesPersons.Expand("Sales") select s).ToList();

As an alternative, you can use explicit loading. This strategy sends an additional query to the WCF Data Service that is requesting the related data for a specific object, but it has the advantage that it does not waste bandwidth by automatically fetching data that is not used. You can implement explicit loading by using the LoadProperty method of the DataServiceContext object. You call the LoadProperty method each time you require data that is related to a particular entity; you specify the entity and the name of the DataServiceQuery collection property that holds the related data. The following code example shows how to use the LoadProperty method to fetch the sales that are associated with each SalesPerson object. Explicit Loading of Entities
FourthCoffeeEntities context = new FourthCoffeeEntities (new Uri ("http://FourthCoffee.com/FourthCoffeeDataService.svc")); foreach (var salesPerson in context.SalesPersons) { ... context.LoadProperty(salesPerson, "Sales"); foreach (var sale in salesPerson.Sales) { ... } }

Additional Reading: For more information about modifying entities, see the How to: Add, Modify, and Delete Entities (WCF Data Services) page at http://go.microsoft.com/fwlink/?LinkID=267820.

Programming in i Visual C#

8-33 3

D Demonstr ration: Re etrieving and a Modif fying Grad de Data in n the Clou ud Lab

I this demon In nstration, you will learn abo out the tasks t that you will p perform in the e lab for this module. m

8-34 Accessin ng Remote Data

Lab: R Retrieving and d Modif fying Grade Da ata in t the Clou ud

Sc cenario
Cu urrently, the application retrieves data fro om a local database. Howe ever, you have e decided to store s the data in the cloud and must configure the application a so o that it can re etrieve data across the web b. ou must create e a WCF Data Service for th he SchoolGrades database e that will be integrated into o the Yo ap pplication to e enable access t to the data. Fin nally, you have e been asked to write code e that displays s student imag ges by retriev ving them from m across the e web.

Ob bjectives
Aft ter completing this lab, you u will be able to: CF Data Service. Create a WC Use a WCF Data Service. Retrieve data over the web.

timated Time: : 60 minutes Est Virtual Mac chine: 20483A A-SEA-DEV11-08, MSL-TMG G1 User Name: Student P Password: Pa$$w0rd

Programming in Visual C# 8-35

Exercise 1: Creating a WCF Data Service for the SchoolGrades Database


Scenario
In this exercise, you will create a WCF Data Service for the SchoolGrades database so that the client application can connect to the database over the web. First, you will add a new ASP.NET Web Application project to the solution and configure it for the client application. You will then expose the entities in the EDM from a data service in the new project. Next, you will specify the data context for the data service and configure access rights to the entities that it exposes. You will then add an operation to the data service that returns all of the students in a specified class. Finally, you will test the WCF Data Service to ensure that it functions correctly. The main tasks for this exercise are as follows: 1. Create the Grades.Web project 2. Add a data service to the Grades.Web project 3. Specify the GradesDBEntities data context for the data service 4. Add an operation to retrieve all of the students in a specified class 5. Build and test the data service

X Task 1: Create the Grades.Web project


1. 2. 3. 4. 5. Start the MSL-TMG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-08 virtual machine and log on as Student with the password Pa$$w0rd. Start Visual Studio, and then open the GradesPrototype.sln solution from the E:\Labfiles\Starter\Exercise 1 folder. Add a Visual C# ASP.NET Empty Web Application project called Grades.Web to the solution. Configure the new project as follows: a. b. c. d. e. Start Action: Dont open a page. Servers: Use Local IIS Web server Project Url: http://localhost:1650/ Add the Grades.Web project to the list of startup projects for the solution. Save all of the files.

X Task 2: Add a data service to the Grades.Web project


1. 2. 3. 4. 5. Add a new folder named Services to the Grades.Web project. Add a new WCF Data Service named GradesWebDataService to the Services folder. Add a reference to the Grades.DataModel project in the Grades.Web project. Add a reference to the EntityFramework assembly. This assembly is located in the E:\Labfiles\Starter\Exercise 1\packages\EntityFramework.5.0.0\lib\net45 folder. Copy the <connectionStrings> element from the App.config file in the GradesPrototype project and paste it into the Web.config file in the Grades.Web project.

8-36

Accessing Remote Data

Note: The data service in the Grades.Web project needs to connect to the same data source that the data model uses.

X Task 3: Specify the GradesDBEntities data context for the data service
1. 2. In the code in the Grades.WebDataService.svc file, add a using directive to bring the Grades.DataModel namespace into scope. Modify the class declaration of the GradesWebDataService to use the SchoolGradesDBEntities class as the data source.

Note: The GradesDBEntities class provides the object context for the EDM. The GradesWebDataService data service will retrieve data by using this object context and expose the various entities by using REST URIs. 3. In the InitializeService method, set the access rules for each of the following entities to EntitySetRights.All: Grades Teachers Students Subjects Users

X Task 4: Add an operation to retrieve all of the students in a specified class


1. In the GradesWebDataService class, add an operation named StudentsInClass that takes a class name as a string and returns an IEnumerable<Student> collection. This operation should be annotated with the WebGet attribute. In this operation, use a LINQ query against the CurrentDataSource object to retrieve and return all of the students in the class. In the InitializeService method, set the access rule for the StudentsInClass operation to ServiceOperationRights.AllRead.

2. 3.

X Task 5: Build and test the data service


1. 2. 3. 4. 5. Build the solution, and then resolve any compilation errors. View GradesWebDataService.svc in Windows Internet Explorer. Verify that Internet Explorer displays an XML description of the entities that the data service exposes. Close Internet Explorer. In Visual Studio, close the solution.

Results: After completing this exercise, you should have added a WCF Data Service to the application to provide remote access to the SchoolGrades database.

Programming in Visual C# 8-37

Exercise 2: Integrating the Data Service into the Application


Scenario
In this exercise, you will integrate the WCF Data Service into the Grades Prototype application. First, you will add a service reference in the GradesPrototype project that references the running WCF Data Service. You will then modify the code that accesses the local EDM to use the WCF Data Service instead. Next, you will modify the code that saves changes back to the database to do so through the data service. Finally, you will test the application to verify that it runs the same as if the data was being called locally. The main tasks for this exercise are as follows: 1. Add a service reference for the WCF Data Service to the GradesPrototype application 2. Modify the code that accesses the EDM to use the WCF Data Service 3. Modify the code that saves changes back to the database to use the WCF Data Service 4. Build and test the application to verify that the application still functions correctly

X Task 1: Add a service reference for the WCF Data Service to the GradesPrototype application
1. 2. 3. 4. In Visual Studio, open the GradesPrototype.sln solution from the E:\Labfiles\Starter\Exercise 2 folder. In the GradesPrototype project, remove the reference to the Grades.DataModel project. Add a service reference to http://localhost:1650, using the namespace of Grades.DataModel. Update the namespace declaration in the Reference.cs file for the service reference to Grades.DataModel. The Reference.cs file is generated in the Service References\Grades.DataModel\Reference.datasvcmap folder in Solution Explorer. You need to enable Solution Explorer to show all files to see this folder.

Note: The Add Service Reference Wizard prepends the namespace that you specify with the namespace of the project, so the result in this case is GradesPrototype.Grades.DataModel. The existing code in the GradesPrototype project expects the various entity classes to be located in the Grades.DataModel namespace. You can either update every reference throughout the project, or you can change the namespace of the data service; this lab opts for the latter approach. There is one drawback with this approach; if you regenerate the data service reference (this will be necessary if, for example, you modify the WCF data service and add a new entity class), you will have to edit the Reference.cs file and update the namespace again because any manual changes you make to this file will be lost. 5. 6. Add a new folder named DataModel to the GradesPrototype project. Copy the following code files from the Grades.DataModel project to the GradesPrototype\DataModel folder: a. b. c. Classes.cs customGrade.cs customTeacher.cs

8-38

Accessing Remote Data

Note: The Classes.cs, Grade.cs, and Teacher.cs files contain custom functionality for the Grade and Teacher classes that you implemented in an earlier lab. WCF Data Services does not propagate any custom functionality that is defined for a data model, so you must manually copy these files to the Grades.DataModel project. You will also have to make some small changes to this code to access data through the WCF Data Service rather than by referencing the entities themselves. You will do this in the next task.

X Task 2: Modify the code that accesses the EDM to use the WCF Data Service
1. In the Grades.Web project, in the Services folder, in SessionContext.cs, modify the DBContext declaration to pass a new Uri object pointing to http://localhost:1650/Services/GradesWebDataService.svc to the SchoolGradesDBEntities constructor.

Note: The DBContext object provides the object context for accessing the data source. Previously this object context retrieved data directly from a local EDM. Now the data service provides this object context, and the constructor requires the URL of the data service. 2. Add the following static constructor to the SessionContext class.
static SessionContext() { DBContext.MergeOption = System.Data.Services.Client.MergeOption.PreserveChanges; }

This constructor ensures that any changes made by the user are not lost if multiple users try and make simultaneous changes 3. 4. In the Views folder, in StudentsPage.xaml.cs, locate the Refresh method. Modify the code in the foreach loop that populates the list ItemsControl with the details of the students for the current teacher.

The user and grades data for a student are held in separate entities and they are not fetched automatically by WCF Data Services (this is to save network resources by not retrieving data unnecessarily). The code that populates the list of students should retrieve that the related data in the User and Grades properties for each student by using the LoadProperty method of the data context (available in SessionContext.DBContext). 5. In LogonPage.xaml.cs, in the Logon_Click method, modify the statement that loads teacher data to also load the user and student data for that teacher. As an alternative to using the LoadProperty method of the data context, use the Expand method when the data is fetched by using the LINQ query. In LogonPage.xaml.cs, in the Logon_Click method, modify the statement that loads student data to also load the user and grades data. In the GradesPrototype solution, in the customTeacher.cs file, add a using directive to bring the GradesPrototype.Services namespace into scope. In the EnrollInClass method, modify the from statement to reference the Students collection in the SessionContext.DBContext object. In the AssignStudentDialog dialog, in the Refresh method, modify the code that finds unassigned students to reference the SessionContext.DBContext.Students collection rather than SessionContext.DBContext.Students.Local. This change is necessary because the data model

6. 7. 8. 9.

Programming in Visual C# 8-39

implemented by the data service does not provide the Local property. You should also use the Expand method to retrieve the User and Grades information for the students. 10. In the StudentProfile view, in the AddGrade_Click method, find the code that uses the Add method of the Grades collection to add a grade to a student. Modify this code to use the AddToGrades method of the DBContext class. This change is necessary because the Grades collection implemented by WCF Data Services does not provide the Add method. 11. In the SaveReport_Click method, modify the LINQ query that retrieves the grades for the report to also fetch the Subject details. Use the Expand method. 12. In the StudentsPage view, in the NewStudent_Click method, find the code that uses the Add method of the Students collection to add a new student. Modify this code to use the AddToStudents method of the DBContext class.

X Task 3: Modify the code that saves changes back to the database to use the WCF Data Service
1. In the code for the AssignStudentDialog view, in the Student_Click method, add code to specify that the selected student has been changed before the call to the SessionContext.Save method.

Note: WCF Data Services requires that you explicitly mark an entity as updated, otherwise any changes will not be saved. 2. 3. In the StudentProfile view, in the Remove_Click method, add code to specify that the current student has been changed before the call to the SessionContext.Save method. In the Controls folder, in ChangePasswordDialog.xaml.cs, in the ok_Click method, add code to specify that the current user has been changed before the call to the SessionContext.Save method.

X Task 4: Build and test the application to verify that the application still functions correctly
1. 2. 3. Build the solution, and then resolve any compilation errors. Log on as vallee with a password of password99. Perform the following tasks to verify that the application still updates the data correctly: a. b. c. d. e. 4. 5. Remove Eric Gruber from the class. Enroll Jon Orton into the class. Change the password to password88, and then verify that you can log on with the new password. Log on as grubere with a password of password. Verify that his student profile appears, and then log off.

Close the application. In Visual Studio, close the solution.

Results: After completing this exercise, you should have updated the Grades Prototype application to use the WCF Data Service.

8-40

Accessing Remote Data

Exercise 3: Retrieving Student Photographs Over the Web


Scenario
In this exercise, you will write code that displays student images by retrieving the image from across the web. You will modify the StudentsPage window (that displays the list of students in a class), the StudentProfile window (that displays the details for an individual student), and the AssignStudentDialog window (that displays a list of unassigned students) to include the student photographs. The data for each student contains an ImageName property that specifies the filename of the photograph for the student on the web server. These files are located in the Images\Portraits folder on the same web server that hosts the data service (in the Web.Grades project.) You will build a value converter class that generates the URL of an image from the ImageName property and then use an Image control to use the URL to fetch and render the image in each of the specified windows. Finally, you will run the application to verify that the images appear. The main tasks for this exercise are as follows: 1. Create the ImageNameConverter value converter class 2. Add an Image control to the StudentsPage view and bind it to the ImageName property 3. Add an Image control to the StudentProfile view and bind it to the ImageName property 4. Add an Image control to the AssignStudentDialog control and bind it to the ImageName property 5. Build and test the application, verifying that students photographs appear in the list of students for the teacher

X Task 1: Create the ImageNameConverter value converter class


1. 2. 3. 4. 5. In Visual Studio, open the GradesPrototype.sln solution from the E:\Labfiles\Starter\Exercise 3 folder. In the GradesPrototype project, in StudentsPage.xaml.cs, create a new public class named ImageNameConverter that implements the IValueConverter interface. In the ImageNameConverter class, define a string constant named webFolder that contains the string http://localhost:1650/Images/Portraits/. Implement the IValueConverter interface. In the Convert method, add code to check whether the value that is passed to the method contains a string, and if so, append it to the webFolder string and return the result. If the value passed to the method is null, return string.Empty. There is no need to add any code to the ConvertBack method. Build the solution and resolve any compilation errors.

6.

X Task 2: Add an Image control to the StudentsPage view and bind it to the ImageName property
1. In the XAML markup for the StudentsPage view, add a reference to the clrnamespace:GradesPrototype.Views namespace. Assign this to xmlns:local. This is the namespace that contains the ImageNameConverter class. Add an instance of the ImageNameConverter class as a resource to the view. At the top of the StackPanel control, add an Image control. The contents of the image should use a data binding that references the ImageNameConverter class to convert the value in the ImageName property into a URL, and then display the data retrieved from this URL. Set the height of the control to 100. The markup for the control should look like this:

2. 3.

Programming in Visual C# 8-41

<Image Height="100" Source="{Binding ImageName, Converter={StaticResource ImageNameConverter}}" />

X Task 3: Add an Image control to the StudentProfile view and bind it to the ImageName property
1. In the XAML markup for the StudentProfile view, add an instance of the ImageNameConverter class as a resource to the view. Use the app namespace (this namespace has already been defined at the top of the XAML markup). At the top of the StackPanel control, add an Image control. Use the ImageNameConverter to convert the value in the ImageName property into a URL and display the image retrieved from this URL. Set the height of the Image control to 150.

2.

X Task 4: Add an Image control to the AssignStudentDialog control and bind it to the ImageName property
1. 2. 3. In the XAML markup for the AssignStudentDialog control, add a reference to the clrnamespace:GradesPrototype.Views namespace. Assign this to xmlns:local. Add an instance of the ImageNameConverter class as a resource to the view. At the top of the StackPanel control. As before, use the ImageNameConverter to convert the value in the ImageName property into a URL and display the image retrieved from this URL. Set the height of the Image control to 100.

X Task 5: Build and test the application, verifying that students photographs appear in the list of students for the teacher
1. 2. 3. 4. 5. 6. 7. 8. Build the solution, and then resolve any compilation errors. Log on as vallee with a password of password88. Verify that the students list now includes images. View George Lis profile and verify that his image appears. Remove George Li from the class. Enroll George Li in the class, and then verify that the Assign Student dialog box now includes images, and new student icons in the main application window include images. Close the application. In Visual Studio, close the solution.

Results: After completing this exercise, the students list, student profile, and unassigned student dialog box will display the images of students that were retrieved across the web.

8-42 Accessin ng Remote Data

Modu ule Revi iew and d Takea aways

M Module Revie ew
In this module, y you have lear rned how to u use the reques st and response classes in the System.Net namespace to m manipulate rem mote data sou urces directly and how to u use WCF Data Services to expose and consume an ent tity data model over the we eb. Test Your Know wledge Q Question W Which of the f following cor rrectly describ bes how to ac ccess data tha at is provided d in an H HTTP response? S Select the cor rrect answer. Invoke e the GetResp ponseStream s static method on the HttpW WebResponse class. Read t the ContentLe ength instance e property on n the HttpWeb bResponse ob bject. Invoke e the GetRequ uestStream ins stance metho od on the Http pWebRespons se object. Invoke e the GetResp ponseStream instance meth hod on the Htt tpWebRespon nse object. Invoke e the GetResp ponseStream instance meth hod on the Htt tpWebReques st object. Test Your Know wledge Q Question W When you cre eate a WCF Da ata Service to o provide rem mote access to o an EDM, ho ow do you specify which entity sets th he data servic ce should mak ke available to t client appli ications? S Select the cor rrect answer. Do no othing. All enti ity sets in the EDM are auto omatically ava ailable to clien nt

Programming in Visual C# 8-43

Question applications. In the InitializeService method of the data service, use the SetEntityAccessRule method of the DataServiceConfiguration object to specify which entity sets should be made available to client applications. Create a certificate for each client that can connect to the service. Configure the service to only allow authenticated clients to connect and retrieve data. Define a data contract for each entity set. Configure the service to enable HTTP GET requests for each entity set.

9-1

Module 9
Designing the User Interface for a Graphical Application
Contents:
Module Overview Lesson 1: Using XAML to Design a User Interface Lesson 2: Binding Controls to Data Lesson 3: Styling a UI Lab: Customizing Student Photographs and Styling the Application Module Review and Takeaways 9-2 9-3 9-19 9-30 9-39 9-52

9-2

Designing g the User Interface e for a Graphical App plication

Modu ule Ove erview

An n effective and d easy-to-use user interface e (UI) is essential for graphical applicatio ons. In this mo odule, you will learn how to o use Extensib ble Application Markup Lan nguage (XAML) and Windo ows Presentati ion Foundation (WP PF) to create e engaging UIs.

Ob bjectives
Aft ter completing this module e, you will be able to: to design a UI. Use XAML t Bind a XAM ML control to d data. Apply styles s to a XAML UI. U

Programming g in Visual C#

9-3 3

Lesson 1

Using g XAML to De esign a User In nterface e

XAML is a dec X clarative, XML L-based marku up language that t you can u use to create UIs for .NET F Framework a applications. D Defining a UI in declarative e markup, rath her than impe erative code, m makes your UI more f flexible and portable. Using g XAML also h helps to separ rate your appl lication UI fro om its runtime e logic. I this lesson, you will learn In n how to use XAML X to create simple graphical UIs.

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Explain ho ow to use XAML to define the layout of a UI. Describe some of the c common cont trols used by WPF W applicati ions. Create co ontrols and set properties in n XAML. Handle ev vents for XAM ML controls. Use layou ut controls in X XAML. Create us ser controls in XAML.

9-4

Designing g the User Interface e for a Graphical App plication

In ntroducing g XAML

XA AML enables y you to define UI elements b by using a dec clarative, XML L-based syntax x. When you u use XAML in a WPF applica ation, you use e XML elemen nts and attribu utes to represent controls a and their prop perties. You can use a variety y of tools to c create XAML f files, such as Visual V Studio, the Microsoft t Expression suite, and tex xt editors. Wh hen you build a WPF applic cation, the bui ild engine con nverts the dec clarative mark kup in your XA AML file into classes c and ob bjects. The following ex xample shows s the basic str ructure of a XA AML UI: De efining a Button in XAML L
< <Window x:Cla ass="MyNames space.MainWindow" xmlns="h http://schem mas.microsoft t.com/winfx/ /2006/xaml/p presentation" xmlns:x= ="http://sch hemas.microso oft.com/winf fx/2006/xaml" Title="O Order Your C Coffee Here" Height="350 0" Width="52 25"> <Grid> <Button n Content="G Get Me a Cof ffee!" /> </Grid> < </Window>

XA AML uses a hie erarchical app proach to define a UI. The m most common n top-level ele ement in a WP PF XAML file e is the Windo ow element. The T Window element can include sever ral attributes. In the previou us example, the e Window ele ement identif fies various XM ML namespace es that make built-in contr rols available f for use. It de efines a title, w which is displa ayed in the titl le bar of the a application, an nd defines the e initial height and width of the window. A Window W elem ment can cont tain a single c child element that defines t the content of f the UI. In mo ost ap pplications, a U UI requires mo ore than a single control, so o WPF defines container co ontrols that yo ou can use to combine other lower-level l controls toge ether and lay them out. The most comm monly used co ontainer control is the Gr rid control, an nd when you add a new W Window to a W WPF project in n Visual Studio o, the Window templa ate automatic cally adds a G Grid control to o the Window w. The Grid contro ol can contain n multiple child controls tha at it lays out in n a grid style. In the examp ple shown ab bove, the Grid d control conta ains a single B Button contro ol. The Grid control defines s a default lay yout that consists of a single row and a single colum mn, but you ca an customize t this layout by y defining add ditional row ws and colum mns as attribut tes of the Grid d. This mechanism enables you to define e cells in the G Grid, and you can then place controls in specific cells. You can als so nest a grid control inside e a cell if you need to pro ovide finer co ontrol over the e layout of certain parts of a window.

Programming in Visual C# 9-5

Additional Reading: For more information about XAML, see the XAML Overview (WPF) page at http://go.microsoft.com/fwlink/?LinkID=267821.

9-6

Designing g the User Interface e for a Graphical App plication

Co ommon C Controls

The .NET Frame ework provide es a comprehe ensive collection of controls s that you can n use to imple ement a UI. Yo ou can find the e complete se et in the Toolb box that is ava ailable when y you design a w window. You can also de efine your own n custom user r controls, as d described in this lesson. The following ta able summariz zes some of the e most comm monly used con ntrols: C Control B Button C CheckBox C ComboBox L Label L ListBox R RadioButton T TabControl T TextBlock T TextBox De escription Displays a button that a user r can click to perform an ac ction. En nables a user to indicate wh hether an item m should be selected s (chec cked) or not (b blank). Displays a drop p-down list of f items from w which the user r can make a selection. s Displays a piece e of static tex xt. Displays a scrollable list of items from which the user can make a selection. En nables the use er to select fro om a range of f mutually exc clusive option ns. O Organizes the controls c in a U UI into a set o of tabbed pages. Displays a read d-only block o of text. En nables the use er to enter and edit text.

Programming g in Visual C#

9-7 7

S Setting Co ontrol Pro operties

When you add controls to a XAML window, you can d W define control properties in n various ways s. Most c controls enab ble you to set simple property values by using attribut tes. T following example sho The ows how to set t the properties of a button n control by using u attribute es: U Using Attribu utes to Set Control Prope erties
<Button Con ntent="Get Me M a Coffee!" Margin=" "150, 130, 150, 130" Backgrou und="Yellow" Foregrou und="Blue" />

This attribute syntax is easy T y to use and in ntuitive for de evelopers with h XML experie ence. Howeve er, this syntax d does not prov vide the flexib bility that you need to defin ne more comp plex property values. Suppo ose that i instead of sett ting the butto on backgroun nd to a simple text value such as Yellow, you want to apply a more e c complex grad dient effect to the button. Y You cannot de efine all the nu uances of a gradient effect t within an a attribute value. Instead, XA AML supports an alternative e way of settin ng control pro operties called d property e element synta ax. Rather than n specifying the Background property a as an inline at ttribute of the e Button e element, you can add an element named d Button.Bac ckground as a child element of the Butt ton element, a then in th and he Button.Background ele ement, you ca an add further r child elemen nts to define y your gradient e effect. The following example sho T ows how to set t the properties of a button n control by using u property y element s syntax: U Using Proper rty Element S Syntax to Set t Control Pro operties
<Button Con ntent="Get Me M a Coffee!" Margin=" "150, 130, 150, 130"> <Button. .Background> > <Line earGradientB Brush StartPoint="0.5, 0 0.5" EndPoin nt="1.5, 1.5" > <G GradientStop p Color="AliceBlue" Offs set="0" /> <G GradientStop p Color="Aqua" Offset="0 0.5" /> </Lin nearGradient tBrush> </Button n.Background d> <Button. .Foreground> > <Soli idColorBrush h Color="Black" /> </Button n.Foreground d>

9-8

Designing the User Interface for a Graphical Application

</Button>

Many WPF controls include a Content property. The previous examples used an attribute to set the Content property of a button to a simple text value. However, the content of a control is rarely limited to text. Instead of specifying the Content property as an attribute, you can add the desired content between the opening and closing tags of the control. For example, you might want to replace the contents of the Button element with a picture of a cup of coffee. The following example shows how to add content to a WPF control: Adding Content to a WPF Control
<Button Margin="150, 130, 150, 130"> <Image Source="Images/coffee.jpg" Stretch="Fill" /> </Button>

Programming g in Visual C#

9-9 9

H Handling Events

When you cre W eate a WPF ap pplication in V Visual Studio, e each XAML page has a cor rresponding code-behind f For example, the MainWindow.xaml file. l file that Visual Studio crea ates by default has a code-behind file n named MainW Window.xaml.cs. You subscribe to event handlers in yo our XAML ma arkup and then define your r e event handler r logic in the c code-behind f file. Note: V Visual Studio includes many y features that t make it easy y to create handlers for eve ents. For example, if you double F e-click a Butto on control at design d time, V Visual Studio w will automatic cally c create an event handler stu ub method in the code-beh hind file. It als so automatically binds the Click C e event of the button b to the event handler method. Suppose you create a simp S ple application n that consists s of a button a and a label. W When you click k the button, y want an e you event handler r to add some e text to the la abel. To do thi is, you need to do three things: 1 1. 2 2. Make sur re the button and the label include a Name property, so that you c can reference the controls in your co ode. Set the Click attribute of the button n to the name e of an event h handler metho od. This meth hod runs when the e Click event o occurs.

Note: T The name of a control should be unique within the window that ho olds the contro ol; n two contro no ols in the same window sho ould have the same name. The following code example shows how to set the eve T ent handler method m for the e Click event of a Button c control: H Handling Eve ents in XAML L
<Button x:N Name="btnMak keCoffee" Margin=" "150, 130, 150, 130" Content= ="Make Me a Coffee!" Click="b btnMakeCoffee_Click" /> <Label x:Na ame="lblResu ult" Content="" "

9-10

Designing the User Interface for a Graphical Application

Margin="150, 186, 150, 75" />

In the code-behind file, you can add logic to the btnMakeCoffee_Click method to define what should happen when a user clicks the button. The following example shows how to create an event handler method for a WPF control: Creating Event Handler Methods
private void btnMakeCoffee_Click(object sender, RoutedEventArgs e) { lblResult.Content = "Your coffee is on its way."; }

Note: WPF uses the concept of routed events. When an event is raised, WPF will attempt to run the corresponding event handler for the control that has the focus. If there is no event handler available, then WPF will examine the parent of the control that has the focus, and if it has a handler for the event it will run. If the parent has no suitable event handler, WPF examines the parent of the parent, and so on right up to the top-level window. This process is known as bubbling, and it enables a container control to implement default event-handling logic for any events that are not handled by its children. When a control handles an event, the event is still bubbled to the parent in case the parent needs to perform any additional processing. An event handler is passed information about the event in the RoutedEventArgs parameter. An event handler can use the properties in this parameter to determine the source of the event (the control that had the focus when the event was raised). The RoutedEventArgs parameter also includes a Boolean property called Handled. An event handler can set this property to true to indicate that the event has been processed. When the event bubbles, the value of this property can be used to prevent the event from being handled by a parent control. Additional Reading: For more information about how routed events work in WPF, see the Routed Events Overview page at http://go.microsoft.com/fwlink/?LinkID=267821.

Programming in i Visual C#

9-11 1

U Using Lay yout Contr rols

Support for re S elative positio oning is one of f the core prin nciples of WPF. The idea is that your app plication s should render r correctly reg gardless of how the user po ositions or resizes the applic cation window w. WPF i includes sever ral layout, or container, c con ntrols that ena able you to po osition and siz ze your child controls in d different ways s. The followin ng table show ws the most co ommon layout controls: Control Canvas DockPanel Grid StackPanel VirtualizingStackPanel Description Child cont trols define th heir own layou ut by specifying g canvas coord dinates. Child cont trols are attac ched to the ed dges of the DockPane el. Child cont trols are adde ed to rows and d columns within the e grid. Child cont trols are stack ked either vert tically or horizontal lly. Child cont trols are stack ked either vert tically or horizontal lly. At any one e time, only ch hild items that are vi isible on the s screen are created. Child cont trols are adde ed from left to o right. If there are too t many con ntrols to fit on n a single line, the contro ols wrap to the e next line.

WrapPanel

T following example sho The ows how to de efine a grid wi ith two rows a and two colum mns: U Using a Grid Layout
<Grid> <Grid.Ro owDefinition ns> <RowD Definition M MinHeight="100" MaxHeigh ht="200" /> <RowD Definition H Height="Auto" /> </Grid.R RowDefinitio ons> <Grid.Co olumnDefinit tions> <Colu umnDefinitio on Width="3*" />

9-12

Designing the User Interface for a Graphical Application

<ColumnDefinition Width="7*" /> </Grid.ColumnDefinitions> <Label Content="This is Row 0, Column <Label Content="This is Row 0, Column <Label Content="This is Row 1, Column <Label Content="This is Row 1, Column </Grid>

0" 1" 0" 1"

Grid.Row="0" Grid.Row="0" Grid.Row="1" Grid.Row="1"

Grid.Column="0" Grid.Column="1" Grid.Column="0" Grid.Column="1"

/> /> /> />

In the previous example, notice that you use RowDefinition and ColumnDefinition elements to define rows and columns respectively. For each row or column, you can specify a minimum and maximum height or width, or a fixed height or width. You can specify heights and widths in three ways: As numerical units. For example, Width="200" represents 200 units (where 1 unit equals 1/96th of an inch). As Auto. For example, Width="Auto" will set the column to the minimum width required to render all the child controls in the column. As a star value. For example, Width="*" will make the column use up any available space after fixedwidth columns and auto-width columns are allocated. If you create two columns with widths of 3* and 7*, the available space will be divided between the columns in the ratio 3:7.

To put a child control in a particular row or column, you add the Grid.Row and Grid.Column attributes to the child control element. Note that these properties are defined by the parent Grid element, rather than the child Label element. Properties such as Grid.Row and Grid.Column are known as attached propertiesthey are defined by a parent element to be specified by its child elements. Attached properties enable child elements to tell a parent element how they should be rendered. Additional Reading: For more information about layout controls, see: The Canvas Class page at http://go.microsoft.com/fwlink/?LinkID=267823. The DockPanel Class page at http://go.microsoft.com/fwlink/?LinkID=267824. The Grid Class page at http://go.microsoft.com/fwlink/?LinkID=267825. The StackPanel Class page at http://go.microsoft.com/fwlink/?LinkID=267826. The VirtualizingStackPanel Class page at http://go.microsoft.com/fwlink/?LinkID=267827. The WrapPanel Class page at http://go.microsoft.com/fwlink/?LinkID=267828.

Programming in i Visual C#

9-13 3

D Demonstr ration: Us sing Desig gn View to o Create a XAML UI I

In this demon I nstration, you will create a s simple WPF ap pplication tha at contains a b button and a label. When y click the button, you b an eve ent handler w will update the e text on the label. The demonstr T ration illustrat tes various wa ays in which you can create e and configur re XAML files in Visual S Studio. It illustrates how yo ou can add controls to the design d surface e by double-c clicking a cont trol in the t toolbox. It sho ows how you can configure e controls thro ough a combi ination of usin ng designer to ools and e editing XAML L markup direc ctly. It also illu ustrates how V Visual Studio can automatically connect event h handlers to yo our controls.

D Demonstra ation Steps


1 1. 2 2. 3 3. Start the MSL-TMG1 vi irtual machine e if it is not already running g. Start the 20483A-SEA A-DEV11-09 v virtual machine. ord Pa$$w0r Log on to o Windows 8 as a Student with the passwo rd. Note: If f necessary, click Switch Us ser to display the list of use ers. 4 4. 5 5. 6 6. 7 7. 8 8. 9 9. Switch to the Windows s 8 Start wind dow. Click Visu ual Studio 20 012. In Visual Studio, on the e File menu, p point to New, and then clic ck Project. In the Ne ew Project dia alog box, in th he Templates s list, click Vis sual C#, and t then in the Pr roject Type list, click WPF W Applica ation. In the Na ame box, type e DesignView w. In the Loc cation text bo ox, set the loc cation to E:\D Democode, an nd then click O OK.

1 In the XA 10. AML pane, in the t Window e element, chan nge the value of the Title a attribute to Or rder Your Coffee H Here. 1 Add the f 11. following mar rkup between the opening and closing Grid G tags:
<Grid.R RowDefinitions>

9-14

Designing the User Interface for a Graphical Application

<RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions>

12. Open the Toolbox pane, expand Common WPF Controls, and then double-click Button. 13. On the design surface, drag the button towards the top of the screen until a message displays Press Tab to place inside row 0. Press Tab, and then release the button. 14. In the XAML pane, in the Button element, change the value of the Content attribute to Make Me a Coffee! 15. Change the value of the HorizontalAlignment attribute to Center. 16. Change the value of the Width attribute to Auto. 17. In the Properties window, ensure the button is selected, and then in the Name box, type btnGetCoffee. 18. In the Toolbox pane, double-click Label. 19. On the design surface, drag the label to anywhere in the lower row of the Grid. 20. In the XAML pane, in the Label element, change the value of the Content attribute to an empty string. 21. Change the value of the HorizontalAlignment attribute to Center. 22. In the Properties window, ensure the label is selected, and then in the Name text box, type lblResult. 23. On the design surface, double-click Make Me a Coffee! 24. Notice that Visual Studio automatically creates an event handler method and switches to the codebehind page. 25. In the btnGetCoffee_Click method, add the following code:
lblResult.Content = "Your coffee is on its way.";

26. On the Debug menu, click Start Without Debugging. 27. In the Order Your Coffee Here window, click Make Me a Coffee! 28. Notice that the label displays a message. 29. Close the Order Your Coffee Here window, and then close Visual Studio.

Programming in i Visual C#

9-15 5

C Creating U User Cont trols

When you wo W ork with WPF, you can creat te your own s self-contained d, reusable use er controls in XAML. User c controls are so ometimes called composite e controls, because they are a composite e of other con ntrols. For e example, if yo ou use the sam me combinatio on of a text box and a butt ton multiple times in a UI, i it might be m more conveni ient to create and use a use er control that consists of t the text box and the button n. A Alternatively, you might cre eate a user co ontrol to enab ble multiple de evelopers to s share the sam me custom c control across s multiple asse emblies. Like a regular L r XAML windo ow, user contro ols consist of a XAML file a and a correspo onding code-behind file. In n t XAML file, the principal difference is that the topthe -level element t is a UserCon ntrol element t rather than a Window ele ement. T following example sho The ows a user con ntrol that enab bles people to o select and o order beverage es: C Creating a Us ser Control in n XAML
<UserContro ol x:Class=" "DesignView.CoffeeSelect tor" xmlns="ht ttp://schemas.microsoft. .com/winfx/2 2006/xaml/presentation" xmlns:x=" "http://schemas.microsof ft.com/winfx x/2006/xaml" xmlns:mc= ="http://schemas.openxml lformats.org g/markup-compatibility/2 2006" xmlns:d=" "http://schemas.microsof ft.com/expre ession/blend/2008" mc:Ignora able="d" d:DesignH Height="300" d:DesignWid dth="200"> <Grid> <Gr rid.RowDefin nitions> <RowDefinition Height="2*"/> <RowDefinition Height="2*"/> <RowDefinition Height="2*"/> <RowDefinition Height="1*"/> </G Grid.RowDefinitions> <St tackPanel Gr rid.Row="0"> <Label Con ntent="Do you want coffe ee or tea?"/ /> <RadioButt ton x:Name="radCoffee" C Content="Cof ffee" HorizontalAlignmen nt="Left" Ver rticalAlignment="Top" Ma argin="5,5,5 5,5" GroupName="Beverage e" IsC Checked="True" Checked=" "radCoffee_C Checked" /> <RadioButt ton x:Name="radTea" Cont tent="Tea" HorizontalAl H ignment="Lef ft" Ve erticalAlignment="Top" M Margin="5,5,5,5" GroupName="Beverag ge" Ch hecked="radTea_Checked"/ /> </S StackPanel> <St tackPanel Gr rid.Row="1"> <Label Con ntent="Do you want milk? ?"/>

9-16

Designing the User Interface for a Graphical Application

<RadioButton x:Name="radMilk" Content="Milk" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="5,5,5,5" GroupName="Milk" IsChecked="True" Checked="radMilk_Checked" /> <RadioButton x:Name="radNoMilk" Content="No Milk" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="5,5,5,5" GroupName="Milk" Checked="radNoMilk_Checked"/> </StackPanel> <StackPanel Grid.Row="2"> <Label Content="Do you want sugar?"/> <RadioButton x:Name="radSugar" Content="Sugar" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="5,5,5,5" GroupName="Sugar" IsChecked="True" Checked="radSugar_Checked" /> <RadioButton x:Name="radNoSugar" Content="No Sugar" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="5,5,5,5" GroupName="Sugar" Checked="radNoSugar_Checked"/> </StackPanel> <Button x:Name="btnOrder" Content="Place Order" Margin="5,5,5,5" Grid.Row="3" Click="btnOrder_Click"/> </Grid> </UserControl>

As the previous example shows, creating the XAML for a user control is very similar to creating the XAML for a window. In the code-behind file for the user control, you can create event handler methods in the same way that you would for regular XAML windows. When you edit the code-behind file, you should also: Define any required public properties. Creating public properties enables the consumers of your user control to get or set property values, either in XAML or in code. Define any required public events. Raising events enables consumers of your user control to respond in the same way that they would respond to other control events, such as the Click event of a button.

The following example shows the code-behind class for a user control: Creating the Code-Behind Class for a User Control
public partial class CoffeeSelector : UserControl { public CoffeeSelector() { InitializeComponent(); } private string beverage; private string milk; private string sugar; public string Order { get { return String.Format("{0}, {1}, {2}", beverage, milk, sugar); } } public event EventHandler<EventArgs> OrderPlaced; private void btnOrder_Click(object sender, RoutedEventArgs e) { if(OrderPlaced!=null) OrderPlaced(this, EventArgs.Empty); } private void radCoffee_Checked(object sender, RoutedEventArgs e) { beverage = "Coffee"; } private void radTea_Checked(object sender, RoutedEventArgs e) { beverage = "Tea"; } private void radMilk_Checked(object sender, RoutedEventArgs e) { milk = "Milk"; } private void radNoMilk_Checked(object sender, RoutedEventArgs e) { milk = "No Milk"; } private void radSugar_Checked(object sender, RoutedEventArgs e) { sugar = "Sugar"; }

Programming in Visual C# 9-17

private void radNoSugar_Checked(object sender, RoutedEventArgs e) { sugar = "No Sugar"; } }

In the previous code example, the user control raises an OrderPlaced event when the user clicks the Place Order button. Applications that include the user control can subscribe to this event and take appropriate action. To use your user control in a WPF application, you need to do two things: 1. Add a namespace prefix for your user control namespace and assembly to the Window element. This should take the following form:

xmlns:[your prefix]="clr-namespace:[your namespace],[your assembly name]" Note: If your application and your user control are in the same assembly, you can omit the assembly name from the namespace prefix declaration. 2. Add the control to your application in the same way that you would add a built-in control, with the namespace prefix you defined.

The following example shows how to add a user control in XAML: Adding a User Control to a WPF Application
<Window x:Class="DesignView.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:coffee="clr-namespace:DesignView" Title="Order Your Coffee Here" Height="350" Width="525"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="8*" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <coffee:CoffeeSelector x:Name="coffeeSelector1" Grid.Row="0" OrderPlaced="coffeeSelector1_OrderPlaced" /> <Label x:Name="lblResult" Margin="5,5,5,5" Grid.Row="1" /> </Grid> </Window>

When you have added the user control, you can handle events and get or set property values in the same way that you would for a built-in control. In the previous example, the OrderPlaced event of the CoffeeSelector control is wired up to the coffeeSelector1_OrderPlaced method. The following example shows how to interact with a user control in a code-behind class: Programming with User Controls
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void coffeeSelector1_OrderPlaced(object sender, EventArgs e) { lblResult.Content = coffeeSelector1.Order; } }

9-18

Designing the User Interface for a Graphical Application

In the previous code example, the coffeeSelector1_OrderPlaced method handles the OrderPlaced event of the CoffeeSelector control. The method then retrieves the order details from the control and writes them to a label.

Programming in i Visual C#

9-19 9

Lesson 2

Binding Con ntrols t to Data

Most applicat M tions work wit th data in one e form or anot ther. The data a that drives y your applicatio on can come f from a wide v variety of sour rces, such as files, databases, or web serv vices. Almost e every graphical application n n needs to conn nect UI contro ols to an unde erlying data so ource so that users can retr rieve, enter, or edit i information. I this lesson, you will learn In n how to bind d controls to d data in WPF ap pplications.

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Describe how data binding works in n WPF. Use XAML to bind controls to data. Use code to bind controls to data. Bind cont trols to collect tions of data. Create da ata templates to specify how data is rend dered.

9-20 Designing the User Interfac ce for a Graphical Application

In ntroductio on to Data a Binding

Da ata binding is the act of con nnecting a data source to a UI element in such a way that if one ch hanges, the oth her must also change. Conceptually, dat ta binding con nsists of three e components: The binding g source. This is the source of your data, and is typically a property of a custom .NET object. For example, you might bind a contro ol to the Coun ntryOfOrigin property of a Coffee objec ct. g target. This is the XAML e element you w want to bind to o your data so ource, and is t typically a The binding UI control. Y You must bind your data so ource to a pro operty of your target objec ct, and that pr roperty must be a d dependency pr roperty. For ex xample, you m might bind da ata to the Con ntent property of a TextBox element. g object. This is the object that connects the source to the target. Th he Binding object can The binding also specify y a converter, if the source property and the target pro operty are of different data a types.

Note: A d dependency property is a sp pecial type of wrapper arou und a regular property. De ependency pro operties are re egistered with h the .NET Fra amework runt time, which en nables the run ntime to notif fy any interest ted parties wh hen the value of the underlying property y changes. This ab bility to notify changes is wh hat makes dat ta binding wo ork. Most built t-in UI elemen nts implemen nt de ependency pro operties and w will support data binding. F For more information abou ut dependency y pro operties, see t the Dependen ncy Properties s Overview pa age at htt tp://go.micros soft.com/fwlin nk/?LinkID=26 67829. The following ex xample shows s a simple dat ta binding exp pression: mple Data Bi inding Sim
< <TextBlock Te ext="{Bindin ng Source={S StaticResourc ce coffee1}, , Path=Bean}" />

In this example, the Text pro operty of a Tex xtBlock is set t to a data bin nding expression. Note that t: n braces. This e enables you to t set properties on the Bin nding The Binding expression is enclosed in object befo ore it is evaluated by the Te extBlock. The Source e property of the t Binding o object is set to o {StaticReso ource coffee1 1}. This is an o object instance de efined elsewhe ere in the solu ution.

Programming in Visual C# 9-21

The Path property of the Binding object is set to Bean. This indicates that you want to bind to the Bean property of the coffee1 object.

As a result of this expression, the TextBlock will always display the value of the Bean property of the coffee1 object. If the value of the Bean property changes, the TextBlock will update automatically. In terms of the concepts described at the start of this topic: The binding source is the Bean property of the coffee1 object. The binding target is the Text property of the TextBlock element. The binding object is defined by the expression in braces.

You can also configure the direction of the data binding. For example, you might want to update the UI when the source data is changed or you might want to update the source data when the user edits a value in the UI. To specify the direction of the binding, you set the Mode property of the Binding object. The Mode property can take the following values: Mode Value TwoWay OneWay OneTime OneWayToSource Default Details Updates the target property when the source property changes, and updates the source property when the target property changes. Updates the target property when the source property changes. Updates the target property only when the application starts or when the DataContext property of the target is changed. Updates the source property when the target property changes. Uses the default Mode value of the target property.

The following example shows how to configure a text box to use two-way data binding: Specifying the Binding Direction
<TextBox Text="{Binding Source={StaticResource coffee1}, Path=Bean, Mode=TwoWay}" />

Additional Reading: For more information about the concepts of data binding, see the Data Binding Overview page at http://go.microsoft.com/fwlink/?LinkID=267830.

9-22 Designing the User Interfac ce for a Graphical Application

Bi inding Co ontrols to Data in XA AML

Yo ou can bind co ontrols to data a in various w ways. If your so ource data wil ll not change during the ex xecution of your application n, you can cre eate a static re esource to rep present your data in XAML. A static resou urce enables you to create c instanc ces of classes. For example, if your assem mbly contains a class named d Coffee, you can define a static resour rce to create an a instance of f Coffee and set properties s on it. To create a static res source, you m must: Add an elem ment to the R Resources pro operty of a container contro ol, such as the e top-level Window. Set the nam me of the elem ment to the na ame of the cla ass you want to t instantiate. . For example, , if you want to create an instanc ce of the Coff fee class, crea ate an elemen nt named Coff fee. Use a nam mespace prefix decla aration to iden ntify the name espace and as ssembly that c contains your class. Add an x:K Key attribute to the element. This is the id dentifier by w which you will specify the st tatic resource in data binding expressions. You can creat te multiple ins stances of a re esource in a window, w but each instance should hav ve a unique x:Key value.

The following ex xample shows s how to creat ource for data a binding: te a static reso Creating a Stat tic Resource
< <Window x:Cla ass="DataBin nding.MainWindow" xmlns="h http://schem mas.microsoft t.com/winfx/ /2006/xaml/p presentation" xmlns:x= ="http://sch hemas.microso oft.com/winf fx/2006/xaml" xmlns:lo oc="clr-name espace:DataBi inding" Title="D Data Binding g Example" He eight="350" Width="525"> <Window.Re esources> <loc:Co offee x:Key= ="coffee1" Name="Four rth Coffee Qu uencher" Bean="Arab bica" CountryOfO Origin="Brazi il" Strength="3" /> </Window.R Resources> < </Window>

If y you want to b bind an individ dual UI eleme ent to this stat tic resource, you can use a binding statement that spe ecifies both a source and a path. You set t the Source property to th he static resou urce, and set the t Path pro operty to the specific property in the source object to o which you w want to bind.

Programming in Visual C# 9-23

The following example shows how to bind an individual item to a static resource: Binding an Individual Item to a Static Resource
<TextBlock Text="{Binding Source={StaticResource coffee1}, Path=Name}" />

More commonly, you will want to bind multiple UI elements to different properties of a data source. In this case, you can set the DataContext property on a container object, such as a Grid or a StackPanel. Setting a DataContext property is similar to providing a partial data binding expression. It specifies the source object, but does not identify specific properties. Any child controls within the container object will inherit this data context, unless you override it. This means that when you create data binding expressions for child controls, you can omit the source and simply specify the path to the property of interest. The following example shows how to set a data context for a set of child controls: Specifying a Data Context
<StackPanel> <StackPanel.DataContext> <Binding Source="{StaticResource coffee1}" /> </StackPanel.DataContext> <TextBlock Text="{Binding Path=Name}" /> <TextBlock Text="{Binding Path=Bean}" /> <TextBlock Text="{Binding Path=CountryOfOrigin}" /> <TextBlock Text="{Binding Path=Strength}" /> </StackPanel>

While you could specify a full data binding expression for each individual UI element, specifying a DataContext property typically makes your XAML easier to write, easier to read, and easier to maintain.

9-24 Designing the User Interfac ce for a Graphical Application

Bi inding Co ontrols to Data in Co ode

In real-world ap pplications, it is i unlikely tha at your source e data will be static. s It is far more likely th hat you will ret trieve data at runtime from m a database or o a web service. In these sc cenarios, you cannot use a static res source to repr resent your da ata. Instead, y you must use c code to specify the data so ource for any UI bindings at runtime. The following ex xample shows s how to creat te data bindin ng programm matically for a T TextBlock ele ement named textbloc ck1: Creating a Data a Binding in Code
p private void mainWindow_ _Loaded(obje ect sender, RoutedEventA R Args e) { // Create a Coffee in nstance to u use as a data a source. Coffee cof ffee1 = new Coffee(); coffee1.Na ame = "Fourt th Coffee Qu uencher"; coffee1.Be ean = "Arabi ica"; coffee1.Co ountryOfOrig gin = "Venez zuela"; coffee1.St trength = 3; ; // Create a Binding o object that references t the Coffee i instance. Binding co offeeBinding g = new Bind ding(); coffeeBind ding.Source = coffee1; coffeeBind ding.Path = new Propert tyPath("Name"); // Add the e binding to o the Text p property of t the TextBloc ck. textblock1 1.SetBinding g(TextBlock.TextProperty y, coffeeBin nding); }

In many cases y you can use a mixture of XA AML binding a and code bind ding. For exam mple, you mig ght know tha at your UI elements will be bound to a Coffee C instanc ce at design time. In this case, you can sp pecify the bin nding paths in n XAML, and then t set a Dat taContext pr roperty in cod de. The following ex xample shows s how to spec cify binding pa aths in XAML: : Sp pecifying Bind ding Paths in n XAML
< <StackPanel x x:Name="stac ckCoffee"> <TextBlock k Text="{Bin nding Path=N Name}" /> <TextBlock k Text="{Bin nding Path=B Bean}" /> <TextBlock k Text="{Bin nding Path=C CountryOfOrig gin}" /> <TextBlock k Text="{Bin nding Path=S Strength}" /> >

Programming in Visual C# 9-25

</StackPanel>

In this example, you have set the binding path for each individual text block in XAML. To complete the binding, all you need to do is to set the DataContext property of the parent StackPanel object to the Coffee instance that you want to display. The following example shows how to specify a DataContext property in code: Specifying the Data Context Programmatically
// Create a Coffee instance. Coffee coffee1 = new Coffee(); coffee1.Name = "Fourth Coffee Quencher"; coffee1.Bean = "Arabica"; coffee1.CountryOfOrigin = "Venezuela"; coffee1.Strength = 3; // Set the DataContext property of the StackPanel. stackCoffee.DataContext = coffee1;

9-26 Designing the User Interfac ce for a Graphical Application

Bi inding Co ontrols to C Collection ns

In many scenarios, you will w want to data bind a control to a collection of objects. W WPF includes controls tha at are designe ed to render c collections, such as the List tBox control, the ListView control, the C ComboBox control, and the e TreeView co ontrol. These c controls all inherit from the e ItemsContr rol class and, as such, sup pport a comm mon approach h to data bind ding. To o bind a collec ction to an Ite emsControl in nstance, you n need to: Specify the source data c collection in the ItemsSour rce property of o the ItemsC Control instan nce. Specify the source prope erty you want to display in the DisplayM MemberPath property of th he ItemsControl instance.

ou can bind an n ItemsContr rol instance to o any collectio on that implem ments the IEn numerable int terface. Yo Yo ou can set the ItemsSource e and Display yMemberPath h properties in XAML or in code. One co ommon ap pproach is to d define the Dis splayMember rPath propert ty (or a data t template) in X XAML, and the en to set the e ItemsSourc ce programma atically at runtime. The following co ode example shows how to o set the Disp playMemberP Path property y in XAML: Se etting the Dis splayMember rPath Proper rty
< <ListBox x:Na ame="lstCoff fees" Displa ayMemberPath= ="Name" />

Ha aving set the D DisplayMemb berPath prop perty in XAML L, you can now w set the Item msSource property in code to comple ete the data bi inding. The following ex xample shows s how to set the ItemsSource property in code: Se etting the Item msSource Property
/ // Create som me Coffee in nstances. v var coffee1 = new Coffee e("Fourth Co offee Quenche er"); v var coffee2 = new Coffee e("Espresso Number Four"); v var coffee3 = new Coffee e("Fourth Re efresher"); v var coffee3 = new Coffee e("Fourth Fr renetic"); / // Add the it tems to an o observable c collection. v var coffees = new Observ vableCollect tion<Coffee>(); c coffees.Add(c coffee1); c coffees.Add(c coffee2);

Programming in Visual C# 9-27

coffees.Add(coffee3); coffees.Add(coffee4); // Set the ItemsSource property of the ListBox to the coffees collection. lstCoffees.ItemsSource = coffees;

Note: If you want a control displaying data in a collection to be updated automatically when items are added or removed, the collection must implement the INotifyPropertyChanged interface. This interface defines an event called PropertyChanged that the collection can raise after making a change. The .NET Framework includes a class named ObservableCollection<T> that provides a generic implementation of INotifyPropertyChanged. The control that binds to the collection receives the event, and can use it to refresh the data that it is displaying. Many of the WPF container controls catch and handle this event automatically. Additional Reading: For more information about the ObservableCollection<T> class, see the ObservableCollection(T) class at http://go.microsoft.com/fwlink/?LinkID=267831. For more information about the INotifyPropertyChanged interface, see the INotifyPropertyChanged Interface page at http://go.microsoft.com/fwlink/?LinkID=267832.

9-28 Designing the User Interfac ce for a Graphical Application

Cr reating Da ata Templ lates

Wh hen you use c controls that d derive from th he ItemsCont trol or Conten ntControl control, you can n create a suppose you w da ata template to o specify how w your items are rendered. F For example, s want to use a ListBox control to displa ay a collection n of Coffee in nstances. Each h Coffee instance includes several prope erties to rep present the na ame of the co offee, the type e of coffee bea an, the country of origin, and the streng gth of the coffee. The data a template spe ecifies how ea ach Coffee instance should d be rendered, by mapping properties of the Coffee in nstance to child controls wi ithin the data template. Cre eating a data template give es you pre ecise control o over how you ur items are re endered and s styled. The following ex xample shows s how to defin ne a data tem mplate for a Lis stBox control: Creating a Data a Template
< <ListBox x:Na ame="lstCoff fees" Width= ="200"> <ListBox.I ItemTemplate e> <DataTe emplate> <Gri id> < <Grid.RowDef finitions> <RowDefin nition Heigh ht="2*" /> <RowDefin nition Heigh ht="*" /> <RowDefin nition Heigh ht="*" /> <RowDefin nition Heigh ht="*" /> < </Grid.RowDe efinitions> < <TextBlock T Text="{Binding Path=Name e}" Grid.Row w="0" Font tSize="22" B Background="B Black" Foreg ground="Whit te" /> < <TextBlock T Text="{Binding Path=Bean n}" Grid.Row w="1" /> < <TextBlock T Text="{Binding Path=Coun ntryOfOrigin n}" Grid.Row w="2" /> < <TextBlock T Text="{Binding Path=Stre ength}" Grid d.Row="3" /> > </Grid> </DataT Template> </ListBox.ItemTemplat te> < </ListBox>

Wh hen you set th he ItemsSour rce property o of this ListBox x to a collection of Coffee objects, the d data tem mplate specifi ies how the Li istBox should d render each Coffee objec ct. In this exam mple, the data a template ng use es a simple gr rid layout and d displays the name of the c coffee with a larger font an nd a contrastin background. Ho owever, you ca an make your r data templat tes as comple ex and sophist ticated as you u want.

Programming in Visual C# 9-29

Additional Reading: For more information about data templates in WPF, see the Data Templating Overview page at http://go.microsoft.com/fwlink/?LinkID=267833.

9-30 Designing the User Interfac ce for a Graphical Application

Lesson 3

Styling g a UI

If y you had to sty yle a graphica al application by setting pro operties on on ne control at a time, the de evelopment pro ocess would q quickly becom me laborious. It I would also be difficult to o maintain you ur application, as you wo ould often nee ed to make th he same chang ge in multiple e locations. XA AML enables y you to define styles as reu usable resourc ces that you c can apply to m multiple contr rols. In this lesson, yo ou will learn h how to use sty yles and anima ations.

Le esson Obje ectives


Aft ter completing this lesson, you will be ab ble to: sable resource es in XAML. Create reus Define style es that apply t to multiple co ontrols. Use propert ty triggers to apply styles when w conditio ons are met. Use animations to create e dynamic effe ects and trans sformations.

Programming in i Visual C#

9-31 1

C Creating R Reusable Resources s in XAML L

XAML enables X s you to creat te certain elem ments, such as s data templates, styles, and d brushes, as reusable r resources. This has various advantages w when you are developing a graphical app plication: You can d define a resou urce once and d use it in multiple places. You can e edit a resource without editing every ele ement that use es the resourc ce. Your XAM ML files are shorter and easier to read.

Every WPF control has a Re E esources prop perty to which h you can add d resources. This is because e the R Resources pr roperty is defined by the Fr rameworkEle ement class from which all WPF element ts ultimately d derive. In mos st cases, you d define resourc ces on the roo ot element in a file, such as the Window w element or descendants. t UserCont the trol element. The resources s are then ava ailable to the r root element and all of its d Y can also create You c resourc ces for use across the entire e application by defining th hem in the Ap pp.xaml file. Note: Every WPF app plication has a an App.xaml f file. It is a XAM ML file that can contain glo obal resources used by all windo r ows and contr rols in a WPF application. It t is also the en ntry point for the a application, and defines wh hich window s should appear when an app plication start ts. Resources are R e stored in a d dictionary colle ection of type e ResourceDictionary. Wh hen you create e a reusable r resource, you must give it a unique key by providing a value for th he x:Key attrib bute. T following example sho The ows how to cre eate a brush a as a window-level resource: C Creating and d Using Resou urces
<Window x:C Class="DataB Binding.MainW Window" xmlns= ="http://schemas.microso oft.com/winf fx/2006/xaml/presentatio on" xmlns:x="http://schemas.micro osoft.com/winfx/2006/xaml" Title= ="Reusable Resources" He eight="350" Width="525"> <Window. .Resources> <Sol lidColorBrus sh x:Key="MyBrush" Color r="Coral" /> > </Window w.Resources> > </Window>

9-32

Designing the User Interface for a Graphical Application

To reference a resource, you use the format {StaticResource [resource key]}. You can use the resource in any property that accepts values of the same type as the resource, provided that the resource is in scope. For example, if you create a brush as a resource, you can reference the brush in any property that accepts brush types, such as Foreground, Background, or Fill. The following example shows how to reference a reusable resource in multiple places: Referencing a Reusable Resource
<StackPanel> <Button Content="Click Me" Background="{StaticResource MyBrush}" /> <TextBlock Text="Foreground" Foreground="{StaticResource MyBrush}" /> <TextBlock Text="Background" Background="{StaticResource MyBrush}" /> <Ellipse Height="50" Fill="{StaticResource MyBrush}" /> </StackPanel>

If you need to create several reusable resources, it can be useful to create your resources in a separate resource dictionary file. A resource dictionary is a XAML file with a top-level element of ResourceDictionary. You can add reusable resources within the ResourceDictionary element in the same way that you would add them to a Window.Resources element. Note: You can create a WPF Resource Dictionary from the Add New Item menu in Visual Studio. In most cases, you make a resource dictionary available for use in your application by referencing it in the application-scoped App.xaml file. The following example shows how to reference a resource dictionary in the App.xaml file: Referencing a Resource Dictionary
<Application x:Class="ReusableResources.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="MainWindow.xaml"> <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="FourthCoffeeResources.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources> </Application>

Programming in i Visual C#

9-33 3

D Defining S Styles as Resources R

In many cases I s, you will wan nt to apply the same prope erty values to multiple cont trols of the sam me type w within an app plication. For e example, if a p page contains s five textboxe es, you will pro obably want e each textbox t have the sa to ame foreground color, back kground color, font size, an nd so on. To m make this consistency e easier to manage, you can create Style e elements as re esources in XA AML. Style ele ements enable you to a apply a collec ction of prope erty values to s some or all co ontrols of a pa articular type. . To create a s style, perform t following steps: the 1 1. 2 2. 3 3. 4 4. Add a Sty yle element to o a resource c collection with hin your appli ication (for ex xample, the Window. .Resources co ollection or a resource dictionary). Use the T TargetType at ttribute of the e Style eleme ent to specify t the type of co ontrol you want the style to target (for example, , TextBox or Button). Use the x x:Key attribute e of the Style e element to enable e controls to specify th rnatively, you his style. Alter can omit the x:Key att tribute and yo our style will a apply to all controls of the s specified type e. Within th he Style eleme ent, use Sette er elements to o apply specifi ic values to sp pecific propert ties.

T following example sho The ows how to cre eate a style th hat targets Tex xtBlock controls: C Creating Styl les
<Window.Res sources> <Style TargetType= ="TextBlock" x:Key="Bloc ckStyle1"> <Se etter Proper rty="FontSize" Value="20 0" /> <Se etter Proper rty="Background" Value=" "Black" /> <Se etter Proper rty="Foreground"> <Setter.Va alue> <Linea arGradientBrush StartPoi int="0.5,0" EndPoint="0.5,1"> <L LinearGradientBrush.Grad dientStops> <GradientStop Offset= ="0.0" Color r="Orange" /> <GradientStop Offset= ="1.0" Color r="Red" /> </ /LinearGradientBrush.Gra adientStops> > </Line earGradientBrush> </Setter.V Value> </S Setter> </Style e> </Window.Re esources>

9-34

Designing the User Interface for a Graphical Application

To apply this style to a TextBlock control, you need to set the Style attribute of the TextBlock to the x:Key value of the style resource. The following example shows how to apply a style to a control: Applying a Style
<TextBlock Text="Drink More Coffee" Style="{StaticResource BlockStyle1}" />

Additional Reading: For more information about defining styles, see the Styling and Templating page at http://go.microsoft.com/fwlink/?LinkID=267834.

Programming in i Visual C#

9-35 5

U Using Pro operty Trig ggers

When you cre W eate a style in XAML, you ca an specify pro operty values that are only applied when n certain c conditions are e true. For exa ample, you might want to c change the fo ont style of a b button when the t user h hovers over it t, or you migh ht want to app ply a highlight ting effect to selected item ms in a list box x. To apply style T e properties based on cond ditions, you ad dd Trigger ele ements to you ur styles. The Trigger T e element ident tifies the prop perty of intere est and the value that should trigger the change. With hin the T Trigger element, you use S Setter elemen nts to apply ch hanges to pro operty values. The following example sho T ows how to ma ake the text o on a button bo old while the user is hovering over the b button: U Using a Prop perty Trigger
<Window.Res sources> <Style TargetType= ="Button"> <St tyle.Trigger rs> <Trigger P Property="IsMouseOver" V Value="True" "> <Sette er Property="FontWeight" " Value="Bold" /> </Trigger> > </S Style.Trigge ers> </Style e> </Window.Re esources>

9-36 Designing the User Interfac ce for a Graphical Application

Cr reating Dy ynamic Tr ransforma ations

Sophisticated gr raphical applications often use animatio ons to make th he user experi ience more en ngaging. An nimations are sometimes us sed to make t transitions bet tween states less abrupt. Fo or example, if you want to enlarge or ro otate a picture e, increasing th he size or cha anging the orientation prog gressively over a short tim me period can n look better t than simply sw witching from one size or o orientation to another. To o create and apply an anima ation effect in n XAML, you n need to do three things: 1. animation. Create an a

PF includes va arious classes that you can use to create animations in n XAML. The m most common nly used WP animation element is Double eAnimation. T The DoubleA Animation ele ement specifie es how a value e should change over tim me, by specifyi ing the initial value, the final value, and the duration over which th he value sho ould change. 2. Create a sto oryboard.

o apply an anim your animatio on in a Storyb board element. The To mation to an object, you need to wrap y Sto oryboard element enables s you to specif fy the object a and the prope erty you want t to animate. It does this by y providing the e TargetNam me and TargetProperty att tached properties, which yo ou can set on child animation elements. 3. gger. Create a trig

o trigger your animation in response to a property cha ange, you nee ed to wrap your storyboard d in an To Ev ventTrigger e element. The E EventTrigger r element spec cifies the cont trol event that t will trigger t the animation. In th he EventTrigg ger element, y you can use a BeginStoryb board elemen nt to launch th he animation. Yo ou can add an EventTrigge er element containing your r storyboards and animations to the Trig ggers collection of a Style S element, or you can add a it directly to the Trigge ers collection of an individual control. xample shows s how to use an a animation to rotate and d expand an im mage when th he user The following ex clic cks on it:

Programming in Visual C# 9-37

Creating an Animation Effect


<Window.Resources> <Style TargetType="Image" x:Key="CoffeeImageStyle"> <Setter Property="Height" Value="200" /> <Setter Property="RenderTransformOrigin" Value="0.5,0.5" /> <Setter Property="RenderTransform"> <Setter.Value> <RotateTransform Angle="0" /> </Setter.Value> </Setter> <Style.Triggers> <EventTrigger RoutedEvent="Image.MouseDown"> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetProperty="Height" From="200" To="300" Duration="0:0:2" /> <DoubleAnimation Storyboard.TargetProperty="RenderTransform.Angle" From="0" To="30" Duration="0:0:2" /> </Storyboard> </BeginStoryboard> </EventTrigger> </Style.Triggers> </Style> </Window.Resources>

Additional Reading: For more information about animations, see the Animation Overview page at http://go.microsoft.com/fwlink/?LinkID=267835.

9-38 Designing the User Interfac ce for a Graphical Application

Demonstration: Customizing Student Photograp P phs and St tyling the e pplication n Lab Ap

In this demonstration, you wi ill learn about t the tasks tha at you will per rform in the la ab for this mo odule.

Programming in i Visual C#

9-39 9

Lab: Custom mizing S Student Photo ographs and S Styling t the lication n Appl

S Scenario
Now that you N u and The Scho ool of Fine Ar rts are happy with the basic c functionality y of the applic cation, you n need to impro ove the appea arance of the interface to g give the user a nicer experie ence through the use of a animations an nd a consisten nt look and feel. You decide to Y o create a StudentPhoto co ontrol that wi ill enable you to display ph hotographs of f students in t student lis the st and other views. v You also o decide to cr reate a fluid m method for a t teacher to rem move a s student from their class. Finally, you w F want to update e the look of t the various vie ews, keeping their look con nsistent across s the a application.

O Objectives
A After complet ting this lab, you y will be able to: Create an nd use user co ontrols. Use styles s and animatio ons.

E Estimated Tim me: 60 minutes Virtual Machine: 20483 3A-SEA-DEV11-09, MSL-TM MG1 User Nam me: Student Password d: Pa$$w0rd

9-40

Designing the User Interface for a Graphical Application

Exercise 1: Customizing the Appearance of Student Photographs


Scenario
In this exercise, you will customize the appearance of student photographs in the production application. You will begin by creating a StudentPhoto user control that will host the photographs on the various pages in the UI. Then you will lay out the user controls and write code to raise the Student_Click method when a user clicks a student photograph. Next, you will add a remove button with a red X to the user control that users can click to remove a student from a class. When a user hovers over the button, the opacity of the button and the photograph will change. Finally, you will run the application to verify that the students image is displayed correctly on the StudentsPage view. The main tasks for this exercise are as follows: 1. Create the StudentPhoto user control 2. Display the students photographs in the StudentsPage view 3. Enable the user to display the details for a student 4. Add a Remove button to the StudentsPage view 5. Display all students for the current teacher 6. Build and test the application

X Task 1: Create the StudentPhoto user control


1. 2. 3. 4. Start the MSL-TMG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-09 virtual machine and log on as Student with the password Pa$$w0rd. Start Visual Studio, and then open the Grades.sln solution from the E:\Labfiles\Starter\Exercise 1 folder. Set the following projects to start without debugging at startup: a. b. 5. 6. Grades.Web Grades.WPF

Add a new WPF user control named StudentPhoto.xaml to the Controls folder in the Grades.WPF project. Modify the XAML markup for the user control as follows: a. Add an Image control to the Grid. This Image control will use data binding to display the photograph, and the source of the Image should be the File property of the data source. The Image should fill the user control except for a margin of 8 points all the way around to allow for a frame. Add a second Image control to the Grid. This Image control will display the frame around the student photograph, and it should completely fill the Grid, so specify a margin of 0 points. Use the Image_Frame.png file in the Images folder as the source for the Image; this image has a transparent center that enables the student photograph to show through. Add a TextBlock control to display the name of the student underneath the photo frame. This control will also use data binding, and the name will be provided by the Name property of the data source. Use the static resource LabelCenter to style the text and set the FontSize to 16. Set

b.

c.

Programming in Visual C# 9-41

the VerticalAlignment to Bottom to ensure that the name appears underneath the photograph, and specify a margin of 8, 0, 14.583, 8 to add a bit of space around the name. d. Change the Class name of the control to Grades.WPF.StudentPhoto. The completed markup should look like the following:
<UserControl x:Class="Grades.WPF.StudentPhoto" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markupcompatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> <Grid> <Image Stretch="UniformToFill" Source="{Binding File}" Margin="8" /> <Image Margin="0" Source="../Images/Image_Frame.png" Stretch="Fill" /> <TextBlock Text="{Binding Name}" Style="{StaticResource LabelCenter}" FontSize="16" VerticalAlignment="Bottom" Margin="8,0,14.583,8" /> </Grid> </UserControl>

7. 8.

In StudentPhoto.xaml.cs, remove the existing using directives and add using directives to bring the following namespaces into scope: System.Windows.Controls System.Windows.Media.Animation Change the namespace of the control to Grades.WPF.

X Task 2: Display the students photographs in the StudentsPage view


1. In the Views folder, in StudentsPage.xaml, in the ScrollViewer element, create an ItemsControl control named list. You will use this control to display the list of photographs for students in a class. In a later step, you will use data binding to associate the list of students with this control. In the ItemsControl element, add an ItemsPanel control that will be used to define the layout for the list of photographs. The ItemsPanel control should contain an ItemsPanelTemplate element with the following property values: o o o Margin: 0: Orientation: Horizontal HorizontalAlignment: Center

2.

The completed markup should look like the following:


<ItemsControl x:Name="list"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <WrapPanel Margin="0" Orientation="Horizontal" HorizontalAlignment="Center" /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl>

3. 4.

Add an ItemTemplate element to the ItemsControl. This element will specify how each photograph is displayed and formatted. In the ItemTemplate element, define a DataTemplate that displays the StudentPhoto control in a grid with a Margin property of 8 points.

9-42

Designing the User Interface for a Graphical Application

Use the following information to set the properties of the StudentPhoto control. Height: 150 Width: 127.5 Cursor: Hand

Note: Remember that the StudentPhoto control is defined in the Grades.WPF namespace. The XAML markup for the StudentsPage control contains the following namespace definition to bring the types in the Grades.WPF namespace into scope with the alias local: xmlns:local="clr-namespace:Grades.WPF" You should refer to the StudentPhoto control as local:StudentPhoto. The completed markup should look like the following:
<ItemsControl x:Name="list"> <ItemsControl.ItemsPanel> ... </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate> <Grid Margin="8"> <local:StudentPhoto Height="150" Width="127.5" Cursor="Hand" /> </Grid> </DataTemplate> </ItemsControl.ItemTemplate> <ItemsControl>

X Task 3: Enable the user to display the details for a student


1. The user will be able to click on a photograph to display the details of a student. In StudentsPage.xaml.cs, in the Events region, add a private method named Student_Click that takes an object and a MouseButtonEventArgs as parameter and returns void. In the Student_Click method, raise the StudentSelected event.

2.

The StudentProfile view subscribes to this event and uses it to display the details of the selected student. The Student_Click method should verify that the StudentSelected event has at least one subscriber before raising the event. The StudentSelected event expects a LocalStudent object containing the data for the student to be provided as an event parameter (this is so that the StudentProfile view knows which student to display). This is actually the same object that will be used as the data source for the StudentPhoto control that the user clicked. You can retrieve this object form the DataContext property of the sender parameter to the Student_Click method (you must cast the sender property to the StudentPhoto type first). The completed method should look like this:
private void Student_Click(object sender, MouseButtonEventArgs e) { if (StudentSelected != null) StudentSelected(sender, new StudentEventArgs((sender as StudentPhoto).DataContext as LocalStudent)); }

Note: The LocalStudent type is a wrapper around the Student class retrieved from the database by using the WCF data service. It provides additional helper methods that the WPF

Programming in Visual C# 9-43

application can use to format the details of a student for display purposes. This type is defined in the Data.cs file. 3. In StudentPage.xaml, modify the instance of the StudentPhoto control in the DataTemplate element to invoke the Student_Click event handler when a user clicks a photo. The XAML markup for the StudentPhoto control should look like this:
<local:StudentPhoto Height="150" Width="127.5" Cursor="Hand" MouseLeftButtonUp="Student_Click"/>

X Task 4: Add a Remove button to the StudentsPage view


1. In StudentsPage.xaml, add another Grid control to the existing Grid control in the DataTemplate element. You will add controls to this grid to display a customized "remove" icon in the top right corner of each photograph. If the user clicks this icon, the student will be removed. Use the following information to set properties of the Grid control. VerticalAlignment: Top HorizontalAlignment: Right Background: #00000000 Opacity: 0.3 Width: 20 Height: 20 ToolTipService.Tooltip: Remove from class Tag: {Binding}

2.

Note: The Tag property will contain a reference to the student, so that the "remove" functionality knows which student to remove. This property will use the data binding of the ItemsControl that contains the DataTemplate to reference the student. 3. Add an Image control as a child of the Grid control and use it to display the delete.png picture in the Images folder. Set the Stretch property to Uniform. This image contains a cross symbol that will be displayed by the remove icon. The XAML markup for the Grid control should look like this:
<Grid VerticalAlignment="Top" HorizontalAlignment="Right" Background="#00000000" Opacity="0.3" Width="20" Height="20" ToolTipService.ToolTip="Remove from class" Tag="{Binding}" > <Image Source="../Images/delete.png" Stretch="Uniform" /> </Grid>

4.

In StudentsPage.xaml.cs, in the Events region, add a private method named RemoveStudent_MouseEnter that takes an object and a MouseEventArgs parameter and returns void.

This method is an event handler that will run when the mouse moves over the remove icon for a student photograph. 5. In the RemoveStudent_MouseEnter method, add code to change the Opacity property of the Grid control holding the delete icon to 1.0 and the Opacity property of the StudentPhoto control to 0.6.

9-44

Designing the User Interface for a Graphical Application

Note: The Grid control that holds the delete icon is available in the sender parameter; cast it to a Grid control first before setting the Opacity property. The StudentPhoto control can be located by accessing the Parent property of the Grid control holding the delete icon, and then accessing the first child element; use the expression Children[0] and cast the result to the StudentPhoto type. This code highlights the remove icon and slightly dims the student photograph. The completed code for this method should look like this:
private void RemoveStudent_MouseEnter(object sender, MouseEventArgs e) { Grid grid = (Grid)sender; grid.Opacity = 1.0; StudentPhoto photo = ((Grid)grid.Parent).Children[0] as StudentPhoto; photo.Opacity = 0.6; }

6. 7.

Add a private method named RemoveStudent_MouseLeave that takes an object and a MouseEventArgs parameter and returns void. In this method, add code to change the Opacity property of the Grid control to 0.3 and the Opacity property of the StudentPhoto control to 1.0. This code restores the photograph to its original brightness and dims the remove icon as the mouse moves away. The completed code for this method should look like this:
private void RemoveStudent_MouseLeave(object sender, MouseEventArgs e) { Grid grid = (Grid)sender; grid.Opacity = 0.3; StudentPhoto photo = ((Grid)grid.Parent).Children[0] as StudentPhoto; photo.Opacity = 1.0; }

8.

In StudentsPage.xaml, in the Grid control for the remove icon, specify the event handlers to use when the mouse traverses the control; when the mouse enters the control raise the RemoveStudent_MouseEnter event, and when the mouse leaves the control, raise the RemoveStudent_MouseLeave event. If the user clicks the remove icon, invoke the RemoveStudent_Click event. The code for this event has already been written; it displays a dialog box that prompts the user to confirm that they really want to remove the student, and then removes the student if the user clicks Yes. The completed XAML markup for ItemsControl element, including the student photograph and the remove icon, should look like this:
<ItemsControl x:Name="list"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <WrapPanel Margin="0" Orientation="Horizontal" HorizontalAlignment="Center" /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate> <Grid Margin="8"> <local:StudentPhoto Height="150" Width="127.5" Cursor="Hand" MouseLeftButtonUp="Student_Click" />

9.

Programming in Visual C# 9-45

<Grid VerticalAlignment="Top" HorizontalAlignment="Right" Background="#00000000" Opacity="0.3" Width="20" Height="20" ToolTipService.ToolTip="Remove from class" Tag="{Binding}" MouseEnter="RemoveStudent_MouseEnter" MouseLeave="RemoveStudent_MouseLeave" MouseLeftButtonUp="RemoveStudent_Click"> <Image Source="../Images/delete.png" Stretch="Uniform" /> </Grid> </Grid> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>

X Task 5: Display all students for the current teacher


1. In the StudentsPage.xaml.cs file, locate the Refresh method. This method runs each time the StudentsPage view is displayed. The purpose of this method is to ensure that the view displays a correct and up-to-date list of students for the teacher. 2. In this method, add code to find all students for the current teacher.

To do this, perform the following tasks: Create a new ServiceUtils object. Call the GetStudentsByTeacher method of the ServiceUtils object, to retrieve the list of students for the currently logged-in teacher. Pass in the name of the current teacher as the parameter to this method. The name is available in the UserName property of the SessionContext object.

Note: The ServiceUtils object is a wrapper around the WCF Data Service that provides the data for the application. It provides a number of helper methods, such as GetStudentsByTeacher that abstract the details of the WCF Data Service from the application. The SessionContext object contains static properties that hold information about the user currently running the application. These properties are populated when the user logs in. The UserName property is the login name of the user. 3. In the Refresh method, add code to iterate through the set of students returned by the GetStudentsByTeacher method and construct a list containing LocalStudent objects for each student.

Note: Remember that a LocalStudent object is a wrapper around a Student object that is retrieved by using the WCF Data Service. The LocalStudent type provides helper methods and properties such as Name (which returns the full name of a student), and File (which returns a formatted URL that references the photographic image file of a student). The StudentPhoto control uses data binding bind to these properties. 4. Add code to bind the list of students to the list ItemsControl control. Note: Set the ItemsSource property of the list object to the list of students. The completed code for the Refresh method should look like this:
public void Refresh() { ServiceUtils utils = new ServiceUtils();

9-46

Designing the User Interface for a Graphical Application

var students = utils.GetStudentsByTeacher(SessionContext.UserName); // Iterate through the returned set of students, construct a local student object list // and then data bind this to the list item template List<LocalStudent> resultData = new List<LocalStudent>(); foreach (Student s in students) { LocalStudent student = new LocalStudent() { Record = s }; resultData.Add(student); } list.ItemsSource = resultData; txtClass.Text = String.Format("Class {0}", SessionContext.CurrentTeacher.Class); }

X Task 6: Build and test the application


1. 2. 3. 4. 5. 6. 7. 8. 9. Build the solution and resolve any compilation errors. Run the application. Log on as vallee with a password of password99. Verify that the students list appears with photographs. In the student list, hover over the red x for the student Martin Weber. Verify that the student photograph for Martin Weber becomes transparent and that the red x becomes opaque. Move the cursor away from the red x and verify that the student photograph becomes opaque and that the red x becomes transparent. Click the red x for Martin Weber, verify that the Student message box appears, and then click Yes. Verify that Martin Weber is removed from the student list.

10. Close the application.

Results: After completing this exercise, the application will display the photographs of each student on the Student List page.

Programming in Visual C# 9-47

Exercise 2: Styling the Logon View and the StudentPhoto Control


Scenario
In this exercise, you will update the LogonPage and StudentPhoto control to have the same look and feel as the rest of the application. First, you will define styles for the username and password text boxes on the LogonPage of the application. You will use the Style property of each control to apply the styles that you have defined. Then you will define some global styles for use across the entire application. You will define a style for labels and a style for text. Next, you will define an animation for the StudentPhoto control, which will cause a students photograph to pulse when a user hovers over it. You will then add event handlers for this animation and apply the animation to the control. Finally, you will run the application to verify that the styling of the text elements has changed throughout the application and that the animations execute correctly. The main tasks for this exercise are as follows: 1. Define and apply styles for the LogonPage view 2. Define global styles for the application 3. Define animations for the StudentPhoto control 4. Add event handlers to trigger the animations 5. Build and test the application

X Task 1: Define and apply styles for the LogonPage view


1. 2. In Visual Studio, open the Grades.sln solution from the E:\Labfiles\Starter\Exercise 2 folder. Set the following projects to start without debugging at startup: a. b. 3. 4. 5. Grades.Web Grades.WPF

In the Grades.WPF project, in the Views folder, open LogonPage.xaml. In the LogonPage user control, define a style named LoginTextBoxStyle, based on the TextBoxStyle style, and targeting text boxes. Use the following information to set properties of the style: Margin: 5 FontSize: 24 MaxLength: 16 The XAML markup for the style should look like this:
<Style x:Key="LoginTextBoxStyle" BasedOn="{StaticResource TextBoxStyle}" TargetType="{x:Type TextBox}"> <Setter Property="Margin" Value="5" /> <Setter Property="FontSize" Value="24"/> <Setter Property="MaxLength" Value="16" /> </Style>

6.

Locate the definition of the username text box, delete the FontSize property of the control, and then apply the LoginTextBoxStyle to the control.

9-48

Designing the User Interface for a Graphical Application

7. 8. 9.

Add another style named PasswordBoxStyle targeting password boxes. Use the following information to set properties of the style: Margin: 5 FontSize: 24 MaxLength: 16 Locate the definition of the password text box, delete the FontSize property of the control, and then apply the PasswordBoxStyle to the control.

X Task 2: Define global styles for the application


1. 2. 3. 4. 5. In the Themes folder, open the Generic.xaml file. Locate the <!-- TODO: Exercise 2: Task 2a: Define the label styling used throughout the application -> comment near the end of the file. Below this comment, set the properties of the LabelStyle style by using the following information: TextWrapping: NoWrap FontFamily: ../Assets/#Buxton Sketch FontSize: 19 Foreground: #FF303030 Locate the <!-- TODO: Exercise 2: Task 2b: Define the text styling used throughout the application --> comment. Below this comment, set the properties of the TextBoxStyle style by using the following information: TextWrapping: NoWrap FontFamily: ../Assets/#Buxton Sketch FontSize: 12 TextAlignment: Left Foreground: #FF303030

X Task 3: Define animations for the StudentPhoto control


1. 2. In the Controls folder, open the StudentPhoto.xaml file. Add a ScaleTransform named scale to the StudentPhoto user control. You will use this transform to change the size of the StudentPhoto user control when the mouse moves over it.

Note: Create a RenderTransform section in the user control, and add the ScaleTransform to this section. 3. Add a Storyboard to the StudentPhoto user control that will contain animations that are performed when the mouse enters the control; set the x:Key property to sbMouseEnter. The animations in this storyboard will use the ScaleTransform that you have just defined. Note: Create a Resources section in the user control, and add the storyboard to this section.

Programming in Visual C# 9-49

4. 5. 6. 7. 8.

Add a DoubleAnimation element for the x axis to the storyboard. Use the following information to define the properties of the animation: To: 1.1 BeginTime: 00:00:00 Duration: 00:00:00.05 Storyboard.TargetName: scale Storyboard.TargetProperty: ScaleX Add another DoubleAnimation element to the same storyboard for the y axis, using the following information: To: 1.1 BeginTime: 00:00:00 Duration: 00:00:00.15 Storyboard.TargetName: scale Storyboard.TargetProperty: ScaleY Add another Storyboard that will contain animations that are performed when the mouse leaves the control; set the x:Key property to sbMouseLeave. Add a DoubleAnimation element for the x axis to this storyboard, using the following information: To: 1 BeginTime: 00:00:00 Duration: 00:00:00.05 Storyboard.TargetName: scale Storyboard.TargetProperty: ScaleX Add another DoubleAnimation element to the storyboard for the y axis, using the following information: To: 1 BeginTime: 00:00:00 Duration: 00:00:00.15 Storyboard.TargetName: scale Storyboard.TargetProperty: ScaleY

X Task 4: Add event handlers to trigger the animations


1. 2. In the StudentPhoto.xaml.cs file, locate the Storyboard region. Add code to define the OnMouseEnter event handler that triggers the mouse enter animation (sbMouseEnter), as follows:
public void OnMouseEnter() { // Trigger the mouse enter animation to grow the size of the photograph currently under the mouse pointer (this.Resources["sbMouseEnter"] as Storyboard).Begin(); }

9-50

Designing the User Interface for a Graphical Application

3. 4. 5.

Add code to define the OnMouseLeave event handler that triggers the mouse leave animation (sbMouseLeave). In the Views folder, open the StudentsPage.xaml.cs file. In the Events region, add an event handler called Student_MouseEnter to forward the MouseEnter event to the StudentPhoto control, as follows:
private void Student_MouseEnter(object sender, MouseEventArgs e) { // Call the OnMouseEnter event handler on the specific photograph currently under the mouse pointer ((StudentPhoto)sender).OnMouseEnter(); }

6. 7.

Add another event handler called Student_MouseLeave that forwards the MouseLeave event to the StudentPhoto control. In the XAML markup for the StudentsPage.view, specify that the MouseEnter event for the StudentPhoto control in the DataTemplate should trigger the Student_MouseEnter event handler method, and the MouseLeave event should trigger the Student_MouseLeave event handler.

X Task 5: Build and test the application


1. 2. 3. 4. Build the solution and resolve any compilation errors. Run the application. Log on as vallee with a password of password99. In The School of Fine Arts window, verify that the styling of the text elements of the application has changed.

Programming in Visual C# 9-51

Comparison of the Logon views

FIGURE 9.1: UPPER: OLD STYLE LOGON VIEW. LOWER: NEW STYLE LOGON VIEW 5. 6. Hover over one of the students in the student list and verify that the photograph animatesit should expand and contract as the mouse passes over it Close the application, and then in Visual Studio, close the solution.

Results: After completing this exercise, the Logon view and the Photograph control will be styled with a consistent look and feel.

9-52 Designing the User Interfac ce for a Graphical Application

Modu ule Revi iew and d Takea aways

M Module Revie ew
In this module, y you learned how h to create engaging UIs s for graphical applications s. You learned how to use e XAML to cre eate windows s and user con ntrols and how w you bind co ontrols to data a items and co ollections. Yo ou also learned d how to prov vide a consiste ent user experience by crea ating styles as s reusable reso ources. Test Your Know wledge Q Question Y You want to u use rows and columns to la ay out a UI. W Which contain ner control sh hould you u use? S Select the cor rrect answer. The Ca anvas control. The Do ockPanel control. The Grid control. The St tackPanel control. The W WrapPanel con ntrol. Test Your Know wledge Q Question Y You are creating an applica ation that ena ables users to o place orders s for coffees. The a application sh hould allow us sers to select the drink the ey want from m a list. Each li ist item should display y the name of f the coffee, the t descriptio on, the price, and an image of the c coffee. How sh hould you pr roceed?

Programming in Visual C# 9-53

Question Select the correct answer. Create a ListBox control. Add child controls to the ListBox control to represent each field. Create a ListBox control. Use a DataTemplate to specify how each field is displayed within a list item. Create a ListBox control. Create a custom control that inherits from ListBoxItem, and use this custom control to specify how each field is displayed. Create a ListBox control. Use the DisplayMemberPath property to specify the fields you want to display in each list item. Create a ListBox control. Use a Style to specify how each field is displayed within a list item. Test Your Knowledge Question You want to apply a highlighting effect to selected items in a ListBox. How should you proceed? Select the correct answer. Create a Style element and set the TargetType attribute to ListBox. Use a Setter element to apply the highlighting effect. Create a Style element and set the TargetType attribute to ListBox. Use a Trigger element to apply the highlighting effect when a list box item is selected. Create a Style element and set the TargetType attribute to ListBox. Use an EventTrigger element to apply the highlighting effect when a list box item is selected. Create a Style element and set the TargetType attribute to ListBox. Use a Storyboard element to apply the highlighting effect when a list box item is selected. Create a Style element and set the TargetType attribute to ListBox. Use a DoubleAnimation element to apply the highlighting effect when a list box item is selected.

10-1

Module 10
Improving Application Performance and Responsiveness
Contents:
Module Overview Lesson 1: Implementing Multitasking Lesson 2: Performing Operations Asynchronously Lesson 3: Synchronizing Concurrent Access to Data Lab: Improving the Responsiveness and Performance of the Application Module Review and Takeaways 10-2 10-3 10-20 10-36 10-46 10-53

10-2 Improviing Application Perf formance and Respo onsiveness

Modu ule Ove erview

Mo odern process sors use threa ads to concurr rently run multiple operatio ons. If your ap pplication perf forms all of , which can its logic on a sin ngle thread, yo ou do not ma ake the best use of the avai ilable processing resources, res sult in a poor experience fo or your users. In this module, you will lea arn how to im mprove the per rformance of your applicat tions by distrib buting your o operations acr ross multiple t threads.

Ob bjectives
Aft ter completing this module e, you will be able to: sk Parallel Libr rary to implem ment multitasking. Use the Tas Perform lon ng-running op perations with hout blocking threads. Control how w multiple thr reads can acce ess resources concurrently. .

Programming in i Visual C#

10-3 3

Lesson 1

Implementi ing Multitasking

A typical grap phical applicat tion consists o of blocks of co ode that run w when an even nt occurs; thes se events fire i response to in o actions such h as the user c clicking a butt ton, moving th he mouse, or opening a window. By d default, this co ode runs by u using the UI th hread. Howev ver, you should d avoid execu uting long-run nning o operations on n this thread because b they can c cause the e UI to become unresponsiv ve. Also, runni ing all of your r c code on a sing gle thread do oes not make g good use of a available processing power in the compu uter; most m modern mach hines contain multiple proc cessor cores, a and running all operations o on a single th hread will only y u a single p use processor core e. The Microsoft T t .NET Framework now in ncludes the Ta ask Parallel Lib brary. This is a set of classes s that makes i easy to distr it ribute your co ode execution n across multip ple threads. Y You can run th hese threads on o different p processor cores and take advantage of t the parallelism m that this mo odel provides. You can assig gn longr running tasks to a separate e thread, leaving the UI thre ead free to respond to user r actions. In this lesson, you will learn I n how to use the t Task Paral llel Library to create multithreaded and responsive a applications.

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Create tasks. Control h how tasks are executed. Return va alues from tasks. Cancel long-running ta asks. Run multiple tasks in p parallel. Link tasks s together. Handle ex xceptions that tasks throw.

10-4 Improviing Application Perf formance and Respo onsiveness

Cr reating Ta asks

The Task class lies at the heart of the Task k Parallel Libra ary in the .NET T Framework. As the name suggests, you use the Tas sk class to rep present a task, or in other words, w a unit o of work. The T Task class enables you to pe erform multipl le tasks concu urrently, each on a different t thread. Behind the scenes s, the Task Parallel Lib brary manages the thread p pool and assig gns tasks to th hreads. You ca an implement t sophisticated d mu ultitasking fun nctionality by using the Tas sk Parallel Libr rary to chain t tasks, pause ta asks, wait for tasks to complete before e continuing, and perform many other o operations.

Cr reating a Ta ask
Yo ou create a new Task object by using the e Task class. A Task object runs a block of code, and you specify thi is code as a parameter to the constructo or. You can provide this cod de in a metho od and create an Action de elegate that w wraps this meth hod. Note: A d delegate provi ides a mechan nism for refere encing a bloc ck of code or a method. The e Ac ction class is a type in the .NET Framewo ork Class Libra ary that enables you to con nvert a method int to a delegate. The method cannot return n a value, but it can take pa arameters. The .NET Fra amework Clas ss Library also provides the Func class, which w enables you to define e a delegate th hat can return a result. The following co ode example shows how to o create a task k by using an Action deleg gate: Creating a Task k by Using an n Action Dele egate
T Task task1 = new Task(ne ew Action(Ge etTheTime)); p private stati ic void GetT TheTime() { Console.WriteLine("Th he time now is {0}", Dat teTime.Now); ; }

Us sing an Action n delegate req quires that yo ou have define ed a method that t contains the code that t you want to run in a task. However, if the t sole purpo ose of this me ethod is to pro ovide the logic c for a task an nd it is not reu used anywher re else, you ca an find yourse elf creating (an nd having to remember the e names of) a substantial nu umber of meth hods. This makes maintenance more diff ficult. A more common app proach is to use an anonymous met thod. An anon nymous meth hod is a metho od without a name, n and yo ou provide the e code for

Programming in Visual C# 10-5

an anonymous method inline, at the point you need to use it. You can use the delegate keyword to convert an anonymous method into a delegate. The following code example shows how to create a task by using an anonymous delegate. Creating a Task by Using an Anonymous Delegate
Task task2 = new Task( delegate { Console.WriteLine("The time now is {0}", DateTime.Now); });

Using Lambda Expressions to Create Tasks


A lambda expression is a shorthand syntax that provides a simple and concise way to define anonymous delegates. When you create a Task instance, you can use a lambda expression to define the delegate that you want to associate with your task. If you want your delegate to invoke a named method or a single line of code, you use can use a lambda expression. A lambda expression provides a shorthand notation for defining a delegate that can take parameters and return a result. It has the following form: (input parameters) => expression In this case: The lambda operator, =>, is read as goes to. The left side of the lambda operator includes any variables that you want to pass to the expression. If you do not require any inputsfor example, if you are invoking a method that takes no parameters you include empty parentheses () on the left side of the lambda operator.

The right side of the lambda operator includes the expression you want to evaluate. This could be a comparison of the input parametersfor example, the expression (x, y) => x == y will return true if x is equal to y; otherwise, it will return false. Alternatively, you can call a method on the right side of the lambda operator. The following code example shows how to use lambda expressions to represent a delegate that invokes a named method. Using a Lambda Expression to Invoke a Named Method
Task task1 = new Task ( () => MyMethod() ); // This is equivalent to: Task task1 = new Task( delegate(MyMethod) );

A lambda expression can be a simple expression or function call, as the previous example shows, or it can reference a more substantial block of code. To do this, specify the code in curly braces (like the body of a method) on the right side of the lambda operator: (input parameters) => { Visual C# statements; } The following code example shows how to use lambda expressions to represent a delegate that invokes an anonymous method. Using a Lambda Expression to Invoke an Anonymous Method
Task task2 = new Task( () => { Console.WriteLine("Test") } ); // This is equivalent to: Task task2 = new Task( delegate { Console.WriteLine("Test") } );

As your delegates become more complex, lambda expressions offer a far more concise and easily understood way to express anonymous delegates and anonymous methods. As such, lambda expressions are the recommended approach when you work with tasks.

10-6

Improving Application Performance and Responsiveness

Reference Links: For more information about lambda expressions, see Lambda Expressions (C# Programming Guide) at http://go.microsoft.com/fwlink/?LinkID=267836.

Programming in i Visual C#

10-7 7

C Controllin ng Task Ex xecution

The Task Para T allel Library of ffers several different appro oaches that yo ou can use to start tasks. Th here are also v various differe ent ways in which you can pause the exe ecution of you ur code until one o or more t tasks have c completed.

S Starting Ta asks
When your co W ode starts a ta ask, the Task P Parallel Library y assigns a thr read to your t task and starts s running that t t task. The task runs on a sep parate thread, , so your code e does not need to wait for r the task to complete. I Instead, the ta ask and the co ode that invok ked the task c continue to ru un in parallel. I you want to If o queue the ta ask immediate ely, you use th he Start meth hod. U Using the Task.Start Method to Queu ue a Task
var task1 = new Task( () => Console.WriteLine e("Task 1 ha as completed.") ); task1.Start t();

Alternatively, you can use t A the static Task kFactory class to create an nd queue a tas sk with a single line of c code. The Tas skFactory class is exposed through the s static Factory y property of the t Task class s. U Using the TaskFactory.Sta artNew Meth hod to Queue e a Task
var task3 = Task.Facto ory.StartNew( () => Cons sole.WriteLine("Task 3 has complete ed.") );

The Task.Fact T tory.StartNew w method is highly configu urable and ac ccepts a wide range of para ameters. If y simply wa you ant to queue some code with the default scheduling o options, you c can use the st tatic T Task.Run method as a sho ortcut for the Task.Factory T .StartNew method. U Using the Task.Run Meth hod to Queue e a Task
var task4 = Task.Run( () => Console.WriteLine e("Task 4 ha as completed. ") );

W Waiting for r Tasks


In some cases I s, you may nee ed to pause the execution of your code until a particu ular task has c completed. T Typically you do this if your code depen nds on the result from one or o more tasks s, or if you nee ed to handle e exceptions tha at a task may throw. The Task class offers various me echanisms to d do this:

10-8

Improving Application Performance and Responsiveness

If you want to wait for a single task to finish executing, use the Task.Wait method. If you want to wait for multiple tasks to finish executing, use the static Task.WaitAll method. If you want to wait for any one of a collection of tasks to finish executing, use the static Task.WaitAny method.

The following code example shows how to wait for a single task to complete. Waiting for a Single Task to Complete
var task1 = Task.Run( () => LongRunningMethod() ); // Do some other work. // Wait for task 1 to complete. task1.Wait(); // Continue with execution.

If you want to wait for multiple tasks to finish executing, or for one of a collection of tasks to finish executing, you must add your tasks to an array. You can then pass the array of tasks to the static Task.WaitAll or Task.WaitAny methods. The following code example shows how to wait for multiple tasks to complete. Waiting for Multiple Tasks to Complete
Task[] tasks = new Task[3] { Task.Run( () => LongRunningMethodA()), Task.Run( () => LongRunningMethodB()), Task.Run( () => LongRunningMethodC()) }; // Wait for any of the tasks to complete. Task.WaitAny(tasks); // Alternatively, wait for all of the tasks to complete. Task.WaitAll(tasks); // Continue with execution.

Programming in i Visual C#

10-9 9

R Returning g a Value f from a Task

For tasks to be effective in real-world sce F enarios, you n need to be ab ble to create ta asks that can return values, , o results, to t or the code that initiated the t task. The regu ular Task class s does not enable you to do this. H However, the Task Parallel Library also in ncludes the ge eneric Task<T TResult> clas ss that you can use when y need to return you r a value. When you cre W eate an instance of Task<T TResult>, you u use the type parameter to o specify the t type of the r result that the e task will retu urn. The Task<TResult> class exposes a read-only pr roperty named d Result. A After the task has finished e executing, you can use the e Result prope erty to retriev ve the return v value of the t task. The Resu ult property is s the same type as the task ks type param meter. T following example sho The ows how to use the Task<T TResult> class s. R Retrieving a Value from a Task
// Create a and queue a task that returns the d day of the week w as a string. Task<string g> task1 = Task.Run<str T ing>( () => DateTime.No ow.DayOfWeek.ToString() ); // Retrieve e and displa ay the task result. Console.Wri iteLine(task k1.Result);

If you access the I t Result pro operty before e the task has finished runn ning, your cod de will wait un ntil a result is a available befo ore proceeding.

10-10

Impro oving Application Performance and Resp ponsiveness

Ca ancelling Long-Run nning Task ks

Tasks are often used to perfo orm long-runn ning operation ns without blo ocking the UI thread, becau use of their asy ynchronous nature. In some cases, you w will want to gi ive your users s the opportun nity to cancel a task if the ey are tired of f waiting. How wever, it would be dangero ous to simply a abort the task k on demand, because thi is could leave your applicat tion data in an unknown st tate. Instead, t the Task Paral llel Library use es can ncellation tok kens to suppor rt a cooperativ ve cancellatio on model. At a high level, th he cancellatio on process wo orks as follows s: 1. 2. 3. 4. When you create c a task, you also create a cancellat tion token. You pass th he cancellation n token as an argument to your delegate method. On the thre ead that created the task, you request cancellation by calling the Ca ancel method d on the e. cancellation n token source In your task k method, you u can check th he status of th he cancellation n token at any y point. If the instigator has request ted that the ta ask be cancelled, you can te erminate your task logic gr racefully, poss sibly rolling back any ch hanges resulting from the w work that the task has perfo ormed.

Typically, you w would check w whether the ca ancellation tok ken has been set to cancele ed at one or m more convenient poin nts in your tas sk logic. For ex xample, if you ur task logic it terates over a collection, yo ou might check for cancellation after e each iteration. The following co ode example shows how to o cancel a task k. Ca ancelling a Ta ask
/ // Create a c cancellation n token sour rce and obtai in a cancell lation token n. C CancellationT TokenSource cts = new C CancellationT TokenSource( (); C CancellationT Token ct = c cts.Token; / // Create and d start a ta ask. T Task.Run( () => doWork(c ct) ); / // Method run n by the tas sk. p private void doWork(Canc cellationTok ken token); { // Check f for cancella ation. if(token.I IsCancellati ionRequested d) { // Tidy y up and fin nish.

Programming in Visual C# 10-11

return; } // If the task has not been cancelled, continue running as normal. }

This approach works well if you do not need to check whether the task ran to completion. Each task exposes a Status property that enables you to monitor the current status of the task in the task life cycle. If you cancel a task by returning the task method, as shown in the previous example, the task status is set to RanToCompletion. In other words, the task has no way of knowing why the method returnedit may have returned in response to a cancellation request, or it may simply have completed its logic. If you want to cancel a task and be able to confirm that it was cancelled, you need to pass the cancellation token as an argument to the task constructor in addition to the delegate method. In your task method, you check the status of the cancellation token. If the instigator has requested the cancellation of the task, you throw an OperationCanceledException exception. When an OperationCanceledException exception occurs, the Task Parallel Library checks the cancellation token to verify whether a cancellation was requested. If it was, the Task Parallel Library handles the OperationCanceledException exception, sets the task status to Canceled, and throws a TaskCanceledException exception. In the code that created the cancellation request, you can catch this TaskCanceledException exception and deal with the cancellation accordingly. To check whether a cancellation was requested and throw an OperationCanceledException exception if it was, you call the ThrowIfCancellationRequested method on the cancellation token. The following code example shows how to cancel a task by throwing an OperationCanceledException exception. Canceling a Task by Throwing an Exception
// Create a cancellation token source and obtain a cancellation token. CancellationTokenSource cts = new CancellationTokenSource(); CancellationToken ct = cts.Token; // Create and start a task. Task.Run( () => doWork(ct) ); // Method run by the task. private void doWork(CancellationToken token); { // Throw an OperationCanceledException if cancellation was requested. token.ThrowIfCancellationRequested(); // If the task has not been cancelled, continue running as normal. }

Reference Links: For more information about cancelling tasks, see Task Cancellation at http://go.microsoft.com/fwlink/?LinkID=267837 and How to: Cancel a Task and Its Children at http://go.microsoft.com/fwlink/?LinkID=267838.

10-12

Impro oving Application Performance and Resp ponsiveness

Ru unning Ta asks in Par rallel

The Task Paralle el Library inclu udes a static class c named Parallel P . The P Parallel class p provides a ran nge of me ethods that yo ou can use to execute tasks s simultaneou usly.

Ex xecuting a S Set of Task ks Simultane eously


If y you want to ru un a fixed set of tasks in pa arallel, you can use the Par rallel.Invoke m method. Whe en you call thi is method, you use lambda a expressions t to specify the tasks that you want to run n simultaneou usly. You do no ot need to exp plicitly create each e taskth he tasks are created implicit tly from the d delegates that you supply to the Parallel.I Invoke metho od. The following co ode example shows how to o use the Para allel.Invoke m method to run n several tasks s in parallel. Us sing the Para allel.Invoke Method M
P Parallel.Invo oke( () => M MethodForFir rstTask(), () => Me ethodForSecon ndTask(), () => Me ethodForThird dTask() );

Ru unning Loo op Iteration ns in Paralle el


The Parallel class also provid des methods t that you can use u to run for r and foreach loop iteration ns in parallel. Clearly it will not alw ways be appro opriate to run loop iteration ns in parallel. For example, if you want to compare sequential values s, you must ru un your loop iterations sequ uentially. How wever, if each loop ite eration represe ents an independent opera ation, running loop iterations in parallel enables you t to maximize your use of the available proc cessing power. o run for loop iterations in parallel, you c can use the Pa arallel.For me ethod. This m method has sev veral To ov verloads to cat ter to many different scena arios. In its sim mplest form, th he Parallel.Fo or method tak kes three parameters: arameter that t represents th he start index for the opera ation, inclusive e. An Int32 pa An Int32 pa arameter that t represents th he end index f for the operat tion, exclusive e. An Action< <Int32> deleg gate that is ex xecuted once per iteration. .

ode example shows how to o use a Parallel.For loop. In n this example e, each eleme ent of an The following co ray is set to th he square root t of the index x value. This is a simple exam mple of a loop in which the e order of arr the e iterations do oes not matte er.

Programming in Visual C# 10-13

Using a Parallel.For Loop


int from = 0; int to = 500000; double[] array = new double[capacity]; // This is a sequential implementation: for(int index = 0; index < 500000; index++) { array[index] = Math.Sqrt(index); } // This is the equivalent parallel implementation: Parallel.For(from, to, index => { array[index] = Math.Sqrt(index); });

To run foreach loop iterations in parallel, you can use the Parallel.ForEach method. Like the Parallel.For method, the Parallel.ForEach method includes many different overloads. In its simplest form, the Parallel.ForEach method takes two parameters: An IEnumerable<TSource> collection that you want to iterate over. An Action<TSource> delegate that is executed once per iteration.

The following code example shows how to use a Parallel.ForEach loop. In this example, you iterate over a generic list of Coffee objects. For each item, you call a method named CheckAvailability that accepts a Coffee object as an argument. Using a Parallel.ForEach Loop
var coffeeList = new List<Coffee>(); // Populate the coffee list // This is a sequential implementation: foreach(Coffee coffee in coffeeList) { CheckAvailability(coffee); } // This is the equivalent parallel implementation: Parallel.ForEach(coffeeList, coffee => CheckAvailability(coffee));

Additional Reading: For more information and examples about running data operations in parallel, see Data Parallelism (Task Parallel Library) at http://go.microsoft.com/fwlink/?LinkID=267839.

Using Parallel LINQ


Parallel LINQ (PLINQ) is an implementation of Language-Integrated Query (LINQ) that supports parallel operations. In most cases, PLINQ syntax is identical to regular LINQ syntax. When you write a LINQ expression, you can opt in to PLINQ by calling the AsParallel extension method on your IEnumerable data source. The following code example shows how to write a PLINQ query.

10-14

Improving Application Performance and Responsiveness

Using PLINQ
var coffeeList = new List<Coffee>(); // Populate the coffee list var strongCoffees = from coffee in coffeeList.AsParallel() where coffee.Strength > 3 select coffee;

Additional Reading: For more information about PLINQ, see Parallel LINQ (PLINQ) at http://go.microsoft.com/fwlink/?LinkID=267840.

Programming in Visual C#

10-15 5

L Linking Ta asks

Sometimes it is useful to se S equence tasks. For example e, you might require that if a task comple etes s successfully, a another task is s run, or if the e task fails, a different d task i is run that possibly needs t to perform s some kind of recovery proc cess. A task th hat runs only w when a previo ous task finishes is called a continuation. T approach This h enables you to construct a pipeline of background o operations. Additionally, a task may spawn other tas A sks if the work k that it needs s to perform is also multith hreaded in asks) can wait n nature. The pa arent task (the e task that spa awned the ne ew or nested ta t for the neste ed tasks to c complete befo ore it finishes itself, or it can return and let the child tasks continue e running asyn nchronously. T Tasks that cau use the parent t task to wait are called chi ild tasks.

C Continuatio on Tasks
Continuation tasks enable y C you to chain multiple m tasks s together so t that they exec cute one after r another. T task that invokes anoth The her task on co ompletion is k known as the antecedent a , an nd the task th hat it invokes i known as th is he continuatio on. You can pa ass data from the antecede ent to the con ntinuation, and d you can c control the ex xecution of the task chain in various way ys. To create a basic continu uation, you us se the T Task.Continu ueWith metho od. T following code example shows how to create a ta The ask continuati ion. C Creating a Ta ask Continua ation
// Create a task that returns a string. Task<string g> firstTask k = new Task<string>( () ) => return "Hello" ); // Create t the continua ation task. // The dele egate takes the result of the antec cedent task as an argument. Task<string g> secondTas sk = firstTask.ContinueW With( (antec cedent) => { retur rn String.Fo ormat("{0}, W World!", ant tecedent.Res sult)); } // Start th he anteceden nt task. firstTask.S Start(); // Use the continuatio on task's result. Console.Wri iteLine(seco ondTask.Result); // Displays s "Hello, Wo orld!"

Notice that w N when you creat te the continu uation task, yo ou are providi ing the result of the first task as an a argument to the t delegate of o the second d task. For example, you mig ght use the first task to collect some

10-16

Improving Application Performance and Responsiveness

data and then invoke a continuation task to process the data. Continuation tasks do not have to return the same result type as their antecedent tasks. Note: Continuations enable you to implement the Promise pattern. This is a common idiom that many asynchronous environments use to ensure that operations perform in a guaranteed sequence. Additional Reading: For more information about continuation tasks, see Continuation Tasks at http://go.microsoft.com/fwlink/?LinkID=267841.

Nested Tasks and Child Tasks


A nested task is simply a task that you create within the delegate of another task. When you create tasks in this way, the nested task and the outer task are essentially independent. The outer task does not need to wait for the nested task to complete before it finishes. A child task is a type of nested task, except that you specify the AttachedToParent option when you create the child task. In this case, the child task and the parent task become far more closely connected. The status of the parent task depends on the status of any child tasksin other words, a parent task cannot complete until all of its child tasks have completed. The parent task will also propagate any exceptions that its child tasks throw. To illustrate the difference between nested tasks and child tasks, consider these two simple examples. The following code example shows how to create a nested task. Creating Nested Tasks
var outer = Task.Run( () => { Console.WriteLine("Outer task starting"); var inner = Task.Run( () => { Console.WriteLine("Nested task starting"); Thread.SpinWait(500000); Console.WriteLine("Nested task completing"); }); }); outer.Wait(); Console.WriteLine("Outer task completed."); /* Output: Outer task starting Nested task starting Outer task completed. Nested task completing */

In this case, due to the delay in the nested task, the outer task completes before the nested task. The following code example shows how to create a child task. Creating Child Tasks
var parent = Task.Run( () => { Console.WriteLine("Parent task starting"); var child = Task.Run( () => { Console.WriteLine("Child task starting"); Thread.SpinWait(500000); Console.WriteLine("Child task completing"); }, TaskCreationOptions.AttachedToParent);

Programming in Visual C# 10-17

}); parent.Wait(); Console.WriteLine("Parent task completed."); /* Output: Parent task starting Child task starting Child task completing Parent task completed. */

Note that the preceding example is essentially identical to the nested task example, except that in this case, the child task is created by using the AttachedToParent option. As a result, in this case, the parent task waits for the child task to complete before completing itself. Nested tasks are useful because they enable you to break down asynchronous operations into smaller units that can themselves be distributed across available threads. By contrast, it is more useful to use parent and child tasks when you need to control synchronization by ensuring that certain child tasks are complete before the parent task returns. Additional Reading: For more information about nested tasks and child tasks, see Nested Tasks and Child Tasks at http://go.microsoft.com/fwlink/?LinkID=267842.

10-18

Impro oving Application Performance and Resp ponsiveness

Handling T Task Excep ptions

Wh hen a task thr rows an excep ption, the exce eption is prop pagated back to the thread that initiated d the task (th he joining thre ead). The task might be link ked to other ta asks through continuations s or child task ks, so mu ultiple exceptions may be t thrown. To en nsure that all e exceptions are e propagated back to the jo oining thr read, the Task k Parallel Libra ary bundles an ny exceptions s together in a an Aggregate eException o object. This ob bject exposes a all of the exce eptions that o occurred throu ugh an InnerE Exceptions co ollection. To o catch except tions on the jo oining thread, , you must wa ait for the task k to complete e. You do this by calling the e Task.Wait m method in a try block and then catching g an Aggrega ateException exception in n the corresponding c catch block. A common ex xception-hand dling scenario is to catch the Ta askCanceledE Exception exc ception that is i thrown whe en you cancel a task. The following co ode example shows how to o handle task exceptions. Ca atching Task Exceptions
s static void M Main(string[ [] args) { // Create a cancellat tion token s source and ob btain a canc cellation to oken. Cancellati ionTokenSour rce cts = ne ew Cancellati ionTokenSour rce(); Cancellati ionToken ct = cts.Token n; // Create and start a long-running task. var task1 = Task.Run( (() => doWor rk(ct),ct); // Cancel the task. cts.Cancel l(); // Handle the TaskCan nceledExcept tion. try { task1.W Wait(); } catch(AggregateExcept tion ae) { foreach h(var inner in ae.Inner rExceptions) { if(i inner is Tas skCanceledEx xception) { C Console.Writ teLine("The task was can ncelled."); C Console.Read dLine(); } else e {

Programming in Visual C# 10-19

// If it's any other kind of exception, re-throw it. throw; } } } } // Method run by the task. private void doWork(CancellationToken token); { for (int i = 0; i < 100; i++) { Thread.SpinWait(500000); // Throw an OperationCanceledException if cancellation was requested. token.ThrowIfCancellationRequested(): } }

Additional Reading: For more information about handling task exceptions, see Exception Handling (Task Parallel Library) at http://go.microsoft.com/fwlink/?LinkID=267843.

10-20

Impro oving Application Performance and Resp ponsiveness

Lesson 2

Perfor rming Operati O ions As synchro onously y

An n asynchronou us operation is an operation that runs on n a separate thread; the thr read that initia ates an s not need to wait for that operation to complete bef asy ynchronous o operation does fore it can con ntinue. Asynchronous o operations are e closely relate ed to tasks. Th he .NET Frame ework 4.5 incl ludes some ne ew features tha at make it eas sier to perform m asynchrono ous operations s. These opera ations transpa arently create new tasks and coordinate their actions, enabling you u to concentra ate on the bus siness logic of f your application. In particular, the a async and awa ait keywords enable you to o invoke an as synchronous operation o and d wait for the e result within n a single met thod, without blocking the thread. In this lesson, yo ou will learn v various techniq ques for invok king and man naging asynch hronous opera ations.

Le esson Obje ectives


Aft ter completing this lesson, you will be ab ble to: spatcher obje ect to run code on a specific thread. Use the Dis Use the asy ync and await t keywords to o run asynchro onous operations. Create methods that are compatible with w the await t operator. ack methods. Create and invoke callba Use the Tas sk Parallel Libr rary with traditional Asynch hronous Programming Mod del (APM) implementa ations. Handle exce eptions that a asynchronous operations th hrow.

Programming in Visual C#

10-21 1

U Using the e Dispatcher

In the .NET Fr I ramework, eac ch thread is as ssociated with h a Dispatche er object. The dispatcher is responsible f maintainin for ng a queue of f work items fo or the thread. . When you work w across mu ultiple threads, for e example, by running asynchronous tasks s, you can use e the Dispatch her object to invoke logic on o a specific t thread. You ty ypically need to do this when you use as synchronous o operations in graphical app plications. For e example, if a user u clicks a b button in a Wi indows Pres sentation Foundation (WPF F) application, , the click e event handler r runs on the UI thread. If the event hand dler starts an asynchronous s task, that tas sk runs on t background thread. As a result, the task the t logic no longer has access to contro ols on the UI, because t these are all o owned by the UI thread. To o update the UI, U the task log gic must use the t D Dispatcher.B BeginInvoke m method to qu ueue the upda ate logic on th he UI thread. Consider a sim C mple WPF app plication that consists of a b button named d btnGetTime e and a label named l lblTime . Whe en the user clicks the button, you use a task to get the e current time e. In this exam mple, the task s simply queries the DateTim me.Now prop perty, but in m many scenarios, your applications might retrieve data f from web serv vices or datab bases in response to activity y on the UI. logic. T following code example shows how you might at The ttempt to upd date the UI fro om your task l T Wrong Way The W to Update a UI Objec ct
public void d btnGetTime e_Click(object sender, R RoutedEventA Args e) { Task.Run n(() => { st tring curren ntTime = DateTime.Now.To oLongTimeStr ring(); Se etTime(curre entTime); } } private voi id SetTime(s string time) { lblTime. .Content = t time; }

If you were to I o run the prec ceding code, y you would get t an InvalidO OperationExce eption except tion with the m message The e calling thread cannot acce ess this object t because a di ifferent thread d owns it. This is because t SetTime method the m is run nning on a background thread, but the lblTime label was created by b the UI t thread. To update the cont tents of the lb blTime label, you y must run the SetTime method on the UI thread.

10-22

Improving Application Performance and Responsiveness

To do this, you can retrieve the Dispatcher object that is associated with the lblTime object and then call the Dispatcher.BeginInvoke method to invoke the SetTime method on the UI thread. The following code example shows how to use the Dispatcher.BeginInvoke method to update a control on the UI thread. The Correct Way to Update a UI Object
public void buttonGetTime_Click(object sender, RoutedEventArgs e) { Task.Run(() => { string currentTime = DateTime.Now.ToLongTimeString(); lblTime.Dispatcher.BeginInvoke(new Action(() => SetTime(currentTime))); } } private void SetTime(string time) { lblTime.Content = time; }

Note that the BeginInvoke method will not accept an anonymous delegate. The previous example uses the Action delegate to invoke the SetTime method. However, you can use any delegate that matches the signature of the method you want to call.

Programming in Visual C#

10-23 3

U Using async and aw wait

The async and T d await keyw words were int troduced in th he .NET Frame ework 4.5 to make m it easier to perform a asynchronous s operations. Y You use the async modifier r to indicate t that a method d is asynchron nous. Within he method t async me the ethod, you use e the await op perator to ind dicate points a at which the execution e of th c be suspen can nded while yo ou wait for a lo ong-running o operation to return. While the method is suspended a an await point, the threa at ad that invoke ed the metho od can do othe er work. Unlike other a U asynchronous programming techniques, , the async an nd await keyw words enable you to run l logic asynchro onously on a s single thread. . This is particularly useful w when you wan nt to run logic c on the UI t thread, becau use it enables y you to run log gic asynchron nously on the same thread without block king the UI. Consider a sim C mple WPF app plication that consists of a b button named d btnLongOp peration and a label long-running operation. In n named lblRes sult. When the user clicks t the button, the event handler invokes a l n t example, it simply sleeps for 10 seco this onds and then n returns the r result Operat tion complete e. In practice, , h however, you might make a call to a web service or re etrieve inform mation from a database. Wh hen the task is s c complete, the e event handle er updates the e lblResult label with the r result of the o operation. The following code example shows an application tha T at performs a synchronous long-running g operation o the UI thre on ead. R Running a Sy ynchronous O Operation on n the UI Thread
private voi id btnLongOp peration_Click(object se ender, Route edEventArgs e) { lblResul lt.Content = "Commencing long-runni ing operatio on"; Task<str ring> task1 = Task.Run<string>(() = => { // / This repre esents a long-running op peration. Th hread.Sleep( (10000); re eturn "Opera ation Complete"; } // This statement b blocks the UI thread unt til the task k result is available. lblResul lt.Content = task1.Result; }

In this example, the final st I tatement in th he event hand dler blocks the e UI thread un ntil the result o of the task is a available. This s means that t the UI will effe ectively freeze e, and the use er will be unab ble to resize th he window, m minimize the window, and so on. To ena able the UI to remain respo onsive, you can convert the e event h handler into a an asynchrono ous method.

10-24

Improving Application Performance and Responsiveness

The following code example shows an application that performs an asynchronous long-running operation on the UI thread. Running an Asynchronous Operation on the UI Thread
private async void btnLongOperation_Click(object sender, RoutedEventArgs e) { lblResult.Content = "Commencing long-running operation"; Task<string> task1 = Task.Run<string>(() => { // This represents a long-running operation. Thread.Sleep(10000); return "Operation Complete"; } // This statement is invoked when the result of task1 is available. // In the meantime, the method completes and the thread is free to do other work. lblResult.Content = await task1; }

This example includes two key changes from the previous example: The method declaration now includes the async keyword. The blocking statement has been replaced by an await operator.

Notice that when you use the await operator, you do not await the result of the taskyou await the task itself. When the .NET runtime executes an async method, it effectively bypasses the await statement until the result of the task is available. The method returns and the thread is free to do other work. When the result of the task becomes available, the runtime returns to the method and executes the await statement. Additional Reading: For more information about using async and await, see Asynchronous Programming with Async and Await (C# and Visual Basic) at http://go.microsoft.com/fwlink/?LinkID=267844.

Programming in Visual C#

10-25 5

C Creating A Awaitable e Methods s

The await operator is always used to aw T wait the completion of a Task instance in n a non-block king manner. I you want to If o create an asy ynchronous m method that y you can wait fo or with the aw wait operator r, your m method must return a Task k object. Whe en you convert a synchrono ous method to an asynchro onous m method, use t the following guidelines: If your synchronous method returns s void (in othe er words, it do oes not return n a value), the e asynchron nous method should return n a Task object. If your synchronous method has a return type of TResult, your asynchronous method sh hould return a Task<TR Result> object t.

An asynchron A nous method c can return void; however, this t is typically y only used fo or event hand dlers. W Wherever pos ssible, you sho ould return a T Task object to o enable calle ers to use the await operat tor with your m method. The following code example shows a syn T nchronous me ethod that wa aits ten second ds and then re eturns a s string. A Long-Runn ning Synchro onous Method
private str ring GetData a() { var task k1 = Task.Ru un<string>(() => { // / Simulate a long-running task. Th hread.Sleep( (10000); re eturn "Opera ation Complete."; }); return t task1.Result t; }

T convert this into an awa To aitable asynch hronous metho od, you must: : Add the a async modifie er to the meth hod declaratio on. Change the return type from string g to Task<stri ing>. Modify th he method log gic to use the e await operat tor with any lo ong-running operations.

10-26

Improving Application Performance and Responsiveness

The following code example shows how to convert the previous synchronous method into an asynchronous method. Creating an Awaitable Asynchronous Method
private async Task<string> GetData() { var result = await Task.Run<string>(() => { // Simulate a long-running task. Thread.Sleep(10000); return "Operation Complete."; }); return result; }

The GetData method returns a task, so you can use the method with the await operator. For example, you might call the method in the event handler for the click event of a button and use the result to set the value of a label named lblResult. The following code example shows how to call an awaitable asynchronous method. Calling an Awaitable Asynchronous Method
private async void btnGetData_Click(object sender, RoutedEventArgs e) { lblResult.Content = await GetData(); }

Note that you can only use the await keyword in an asynchronous method. Additional Reading: For more information about return types for asynchronous methods, see Async Return Types (C# and Visual Basic) at http://go.microsoft.com/fwlink/?LinkID=267845.

Programming in Visual C#

10-27 7

C Creating a and Invok king Callba ack Metho ods

If you must ru I un complex lo ogic when an asynchronous a s method com mpletes, you can configure your a asynchronous s method to in nvoke a callba ack method. The T asynchron nous method passes data to o the callback k m method, and the callback m method proce esses the data. You might a also use the ca allback metho od to update t UI with th the he processed r results. To configure a T an asynchronous method t to invoke a ca allback method, you must include a delegate for the c callback meth hod as a param meter to the a asynchronous method. A ca allback metho od typically ac ccepts one or m more argume ents and does not return a value. v This ma akes the Actio on<T> delegate a good ch hoice to r represent a ca allback metho od, where T is the type of your argument t. If your callb back method requires r m multiple arguments, there a are versions o of the Action delegate that t accept up to o 16 type para ameters. Consider a WPF application C n that consists s of a button named btnGe etCoffees and d a list named d lstCoffees. W When the use er clicks the bu utton, the eve ent handler invokes an asyn nchronous me ethod that ret trieves a list of f c coffees. When n the asynchro onous data re etrieval is com mplete, the me ethod invokes a callback me ethod. The c callback meth hod removes a any duplicates s from the res sults and then n displays the updated resu ults in the l listCoffees lis st. T following code example shows an asynchronous method that invokes a callback method. The I Invoking a Callback Meth hod
// This is the click event e handler for the bu utton. private asy ync void btn nGetCoffees_Click(object t sender, Ro outedEventArgs e) { await Ge etCoffees(Re emoveDuplicates); } // This is the asynchr ronous method. public asyn nc Task GetC Coffees(Action<IEnumerab ble<string>> > callback) { // Simul late a call to a database or a web service. var coff fees = await t Task.Run(() => { va ar coffeeLis st = new List<string>(); ; co offeeList.Ad dd("Caffe Americano"); co offeeList.Ad dd("Caf au Lait"); co offeeList.Ad dd("Caf au Lait"); co offeeList.Ad dd("Espresso Romano"); co offeeList.Ad dd("Latte"); co offeeList.Ad dd("Macchiato");

10-28

Improving Application Performance and Responsiveness

return coffeeList; } // Invoke the callback method asynchronously. await Task.Run(() => callback(coffees)); } // This is the callback method. private void RemoveDuplicates(IEnumerable<string> coffees) { IEnumerable<string> uniqueCoffees = coffees.Distinct(); Dispatcher.BeginInvoke(new Action(() => { lstCoffees.ItemsSource = uniqueCoffees; } }

In the previous example, the RemoveDuplicates callback method accepts a single argument of type IEnumerable<string> and does not return a value. To support this callback method, you add a parameter of type Action<IEnumerable<string>> to your asynchronous method. When you invoke the asynchronous method, you supply the name of the callback method as an argument. Reference Links: For more information, see Action<T> Delegate at http://go.microsoft.com/fwlink/?LinkID=267846.

Programming in Visual C#

10-29 9

W Working w APM with M Operatio ons

Many .NET Fra M amework clas sses that supp port asynchron nous operatio ons do so by im mplementing a design p pattern known as APM. The e APM pattern is typically implemented as two metho ods: a ndOperationN B Begin Operati ionName met thod that start ts the asynchr ronous operat tion and an En Name m method that p provides the r results of the asynchronous s operation. Y You typically call the EndOp perationName e m method from within a callb back method. For example, the HttpWeb bRequest class includes methods n named Begin nGetResponse e and EndGet tResponse. The BeginGetResponse me ethod submits s an a asynchronous s request to an n Internet or intranet i resou urce, and the EndGetRespo onse method returns the a actual response that the Int ternet resourc ce provides. Classes that im C mplement the e APM pattern n use an IAsyn ncResult insta ance to represent the statu us of the a asynchronous s operation. The BeginOperationName m method return ns an IAsyncR Result object t, and the E Operation End nName metho od includes an n IAsyncResu ult parameter. The Task Para T allel Library makes it easier to work with classes that im mplement the e APM pattern n. Rather than n i implementing g a callback m method to call the EndOper rationName m method, you ca an use the T TaskFactory. FromAsync m method to inv voke the oper ration asynchr ronously and return the res sult in a single e s statement. Th he TaskFactor ry.FromAsync c method includes several overloads to accommodate APM m methods that take varying numbers of arguments. a Consider a WPF application C n that verifies URLs that a u user provides. The applicati ion consists of f a box n named txtUrl l, a button named btnSubm mitUrl, and a label named lblResults. T The user types a URL in the b and then clicks the but box tton. The click k event handle er for the butt ton submits a an asynchrono ous web r request to the e URL and the en displays the e status code of the respon nse in the labe el. Rather than n i implementing g a callback m method to han ndle the respo onse, you can use the TaskF Factory.From mAsync m method to pe erform the ent tire operation n. The following code example shows how to use the Ta T askFactory.Fr romAsync me ethod to subm mit an a asynchronous s web request and handle t the response.

10-30

Improving Application Performance and Responsiveness

Using the TaskFactory.FromAsync Method


private async void btnCheckUrl_Click(object sender, RoutedEventArgs e) { // Get the URL provided by the user. string url = txtUrl.Text; // Create an HTTP request. HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); // Submit the request and await a response. HttpWebResponse response = await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, request) as HttpWebResponse; // Display the status code of the response. lblResult.Content = String.Format("The URL returned the following status code: {0}", response.StatusCode); }

Additional Reading: For more information about using the Task Parallel Library with APM patterns, see TPL and Traditional .NET Asynchronous Programming at http://go.microsoft.com/fwlink/?LinkID=267847.

Programming in Visual C#

10-31 1

D Demonstr ration: Us sing the T Task Parallel Library y to Invoke e APM Op perations

This demonstration explain T ns how to convert an applic cation that use es a traditiona al APM implementation to u the Task P use Parallel Library y instead. The e demonstration illustrates how the Task k Parallel Libra ary approach r results in shor rter and simpl ler code.

D Demonstra ation Steps


1 1. 2 2. 3 3. Start the MSL-TMG1 vi irtual machine e if it is not already running g. Start the 20483A-SEA A-DEV11-10 v virtual machine. Log on to o Windows 8 as a Student with the passwo rd. ord Pa$$w0r Note: If f necessary, click Switch Us ser to display the list of use ers. 4 4. 5 5. 6 6. 7 7. 8 8. 9 9. Switch to the Windows s 8 Start wind dow. Click Visu ual Studio 20 012. In Micros soft Visual Studio, on the File menu, po oint to Open, and then clic ck Project/So olution. In the Op pen Project dialog box, bro owse to the E: :\Democode\ \Starter folde er, click APMT Tasks.sln, and then click Open. On the Build menu, click Build Solu ution. On the D Debug menu, c click Start Wi ithout Debug gging.

1 In the tex 10. xt box, type ht ttp://www.co ontoso.com, and then click Check URL. 1 Notice th 11. hat the label d displays the message The URL U returned the followin ng status code: OK. 1 Close the 12. e MainWindo ow window. ainWindow.x 1 In Solutio 13. on Explorer, ex xpand MainW Window.xaml l, and then do ouble-click Ma xaml.cs. 1 Review th 14. he code in the e MainWindo ow class: a. Notic ce that the bt tnCheckUrl_C Click method creates an Ht ttpWebReque est object and d then calls the B BeginGetResp ponse method.

10-32

Improving Application Performance and Responsiveness

b. c.

Notice that the BeginGetResponse method specifies the ResponseCallback method as an asynchronous callback method. Notice that the ResponseCallback method calls the HttpWebResponse.EndGetResponse method to get the result of the web request and then updates the UI.

15. Delete the ResponseCallback method. 16. Modify the btnCheckUrl_Click method declaration to include the async modifier as follows:
private async void btnCheckUrl_Click(object sender, RoutedEventArgs e)

17. In the btnCheckUrl_Click method, delete the following line of code:


request.BeginGetResponse(new AsyncCallback(ResponseCallback), request);

18. Add the following code in place of the line you just deleted:
HttpWebResponse response = await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, request) as HttpWebResponse; lblResult.Content = String.Format("The URL returned the following status code: {0}", response.StatusCode);

19. Notice that the MainWindow class is now far more simple and concise. 20. On the Debug menu, click Start Without Debugging. 21. In the text box, type http://www.contoso.com, and then click Check URL. 22. Notice that the label displays the message The URL returned the following status code: OK. 23. Notice that the application works in exactly the same way as before. 24. Close the MainWindow window, and then close Visual Studio.

Programming in Visual C#

10-33 3

H Handling Exception ns from Aw waitable M Methods

When you perform asynchronous operations with the W e async and a await keyword ds, you can ha andle e exceptions in the same way y that you han ndle exceptions in synchronous code, wh hich is by usin ng try/catch b blocks. T following code example shows how to catch an exception The e that t an awaitable e method has thrown. C Catching an A Awaitable M Method Excep ption
private asy ync void btn nThrowError_Click(object t sender, Ro outedEventArgs e) { using (W WebClient client = new W WebClient()) ) { try { st tring data = await client.DownloadS StringTaskAs sync("http://contoso/bog gus"); } catch h (WebExcept tion ex) { lb blResult.Con ntent = ex.Message; } } }

In the previou I us example, th he click event handler for a button calls the t W WebClient.D ownloadStringTaskAsync c method asynchronously b by using the a await operato or. The URL t that is provide ed is invalid, s so the method d throws a We ebException exception. Ev ven though th he operation i asynchrono is ous, control returns to the b btnThrowErro or_Click meth hod when the asynchronou us operation is s c complete and d the exceptio on is handled correctly. c This s works becau use behind the e scenes, the T Task Parallel L Library is catc ching the asyn nchronous exc ception and re e-throwing it on the UI thre ead.

U Unobserved d Exception ns
When a task r W raises an exception, you can n only handle e the exception when the jo oining thread accesses the t task, for exam mple, by using the await op perator or by calling c the Ta ask.Wait meth hod. If the join ning thread n never accesse es the task, the e exception w will remain uno observed. Whe en the .NET Fr ramework gar rbage c collector (GC) ) detects that a task is no lo onger required d, the task sch heduler will th hrow an excep ption if any t task exception ns remain uno observed. By d default, this ex xception is ignored. Howev ver, you can im mplement an e exception han ndler of last re esort by subsc cribing to the TaskSchedul ler.Unobserv vedTaskExcep ption event.

10-34

Improving Application Performance and Responsiveness

Within the exception handler, you can set the status of the exception to Observed to prevent any further propagation. The following code example shows how to subscribe to the TaskScheduler.UnobservedTaskException event. Implementing a Last-Resort Exception Handler
static void Main(string[] args) { // Subscribe to the TaskScheduler.UnobservedTaskException event and define an event handler. TaskScheduler.UnobservedTaskException += (object sender, UnobservedTaskExceptionEventArgs e) => { foreach (Exception ex in ((AggregateException)e.Exception).InnerExceptions) { Console.WriteLine(String.Format("An exception occurred: {0}", ex.Message)); } // Set the exception status to Observed. e.SetObserved(); } // Launch a task that will throw an unobserved exception // by attempting to download an item from an invalid URL. Task.Run(() => { using(WebClient client = new WebClient()) { client.DownloadStringTaskAsync("http://contoso/bogus"); } }); // Give the task time to complete and then trigger garbage collection (for example purposes only). Thread.Sleep(5000); GC.WaitForPendingFinalizers(); GC.Collect(); Console.WriteLine("Execution complete."); Console.ReadLine(); }

If you use a debugger to step through this code, you will see that the UnobservedTaskException event is fired when the GC runs. In the .NET Framework 4.5, the .NET runtime ignores unobserved task exceptions by default and allows your application to continue executing. This contrasts with the default behavior in the .NET Framework 4.0, where the .NET runtime would terminate any processes that throw unobserved task exceptions. You can revert to the process termination approach by adding a ThrowUnobservedTaskExceptions element to your application configuration file. The following code example shows how to add a ThrowUnobservedTaskExceptions element to an application configuration file. Configuring the ThrowUnobservedTaskExceptions Element
<configuration> <runtime> <ThrowUnobservedTaskExceptions enabled="true" /> </runtime> </configuration>

If you set ThrowUnobservedTaskExceptions to true, the .NET runtime will terminate any processes that contain unobserved task exceptions. A recommended best practice is to set this flag to true during application development and to remove the flag before you release your code.

Programming in Visual C# 10-35

10-36

Impro oving Application Performance and Resp ponsiveness

Lesson 3

Synch hronizin ng Conc current t Access s to Data

Int troducing multithreading in nto your applications has m many advantages in terms of o performanc ce and ate a res sponsiveness. However, it also a introduce es new challen nges. When yo ou can simulta aneously upda res source from m multiple threads, the resour rce can becom me corrupted or can be left t in an unpred dictable sta ate. In this lesson, yo ou will learn h how to use various synchronization techn niques to ensu ure that you a access res sources in a th hread-safe ma annerin oth her words, in a way that pre events concurrent access fro om having un npredictable e effects.

Le esson Obje ectives


Aft ter completing this lesson, you will be ab ble to: atements to prevent p concu urrent access t to code. Use lock sta Use synchro onization prim mitives to restrict and contr rol access to re esources. Use concurrent collection ns to store da ata in a thread d-safe way.

Programming in Visual C#

10-37 7

U Using Loc cks

When you int W troduce multit threading into o your applica ations, you can often encou unter situation ns in which a r resource is sim multaneously accessed from m multiple thr reads. If each of these threa ads can alter t the resource, t resource c the can end up in an unpredict table state. Fo or example, su uppose you cr reate a class th hat manages s stock levels of f coffee. When you place an order for a number of co offees, a method in the clas ss will: 1 1. 2 2. 3 3. Check the e current stoc ck level. If sufficien nt stock exists s, make the co offees. Subtract t the number o of coffees from m the current stock level.

If only one thread can call t I this method a at any one tim me, everything g will work fine. However, suppose two t threads call th his method at the same tim me. The curren nt stock level m might change e between step ps 1 and 2, or r b between steps 2 and 3, making it impossible to keep track of the current stock level and establish whether r y have sufficient stock to you o make a coffe ee. To solve this p T problem, you can use the lo ock keyword to apply a mu utual-exclusio on lock to criti ical sections o code. A mu of utual-exclusion lock means that if one th hread is access sing the critical section, all other threads s a locked out. To apply a lock, you use the following are g syntax: l lock (object) { statement bl lock } The first thing T g to notice is t that you apply y the lock to a an object. This is because the lock works s by ensuring t that only one thread can ac ccess that obj ject at any one time. This o object should be private and d should s serve no othe er role in your logic; its purp pose is to provide somethin ng for the loc ck keyword to o make m mutually exclu usive. Next, yo ou put your critical section of code insid de the lock blo ock. While the e lock s statement is in n scope, only one thread ca an enter the c critical section n at any one time. The following code example shows how to use the lo T ock keyword to ncurrent acces ss to a block o prevent con o code. of

10-38

Improving Application Performance and Responsiveness

Using the Lock Keyword


class Coffee { private object coffeeLock = new object(); int stock; public Coffee(int initialStock) { stock = initialStock; } public bool MakeCoffees(int coffeesRequired) { lock (coffeeLock) { if (stock >= coffeesRequired) { Console.WriteLine(String.Format("Stock level before making coffees: {0}", stock)); stock = stock coffeesRequired; Console.WriteLine(String.Format("{0} coffees made", coffeesRequired)); Console.WriteLine(String.Format("Stock level after making coffees: {0}", stock)); return true; } else { Console.WriteLine("Insufficient stock to make coffees"); return false; } } } }

In the previous example, the lock statement ensures that only one thread can enter the critical section of code within the MakeCoffee method at any one time. Note: Internally, the lock statement actually uses another Microsoft Visual C# locking mechanism, the Monitor.Enter and Monitor.Exit methods, to apply a mutual exclusion lock to a critical section of code. For more information, see lock Statement (C# Reference) at http://go.microsoft.com/fwlink/?LinkID=267848 and Thread Synchronization (C# and Visual Basic) at http://go.microsoft.com/fwlink/?LinkID=267849.

Programming in Visual C#

10-39 9

D Demonstr ration: Us sing Lock Statemen nts

This demonstration illustrat T tes how the lo ock statement prevents concurrent acce ess to critical s sections of c code. The dem monstration solution contains a class nam med Coffee t that includes a method nam med M MakeCoffees s. The MakeC Coffees metho od does the fo ollowing: 1 1. 2 2. 3 3. Checks th he current cof ffee stock leve el. Fulfills the e order, if the e current stock k level is suffic cient. Subtracts s the number of coffees ord dered from the current stoc ck level.

In the Progra I am class, a Parallel.For loop creates 100 0 parallel oper rations. Each p parallel operation places a order for b an between one a and 100 coffe ees at random m. When you use W e a lock statement to apply y a mutual-ex xclusion lock t to the critical section of cod de in the M MakeCoffees s method, the e method will always functio on correctly. However, H if yo ou remove the e lock s statement, the e logic can fai il, the stock le evel becomes negative, and d the applicati ion throws an n exception.

D Demonstra ation Steps


1 1. 2 2. 3 3. Start the MSL-TMG1 vi irtual machine e if it is not already running g. Start the 20483A-SEA A-DEV11-10 v virtual machine. Log on to o Windows 8 as a Student with the passwo rd. ord Pa$$w0r Note: If f necessary, click Switch Us ser to display the list of use ers. 4 4. 5 5. 6 6. 7 7. 8 8. 9 9. Switch to the Windows s 8 Start wind dow. Click Visu ual Studio 20 012. In Visual Studio, on the e File menu, p point to Open n, and then click Project/Solution. In the Op pen Project dialog box, bro owse to the E: :\Democode\ \Starter folde er, click Locking.sln, and then click k Open. In Solutio on Explorer, do ouble-click Co offee.cs. Review th he Coffee clas ss, paying par rticular attenti ion to the Ma akeCoffees m method.

10-40

Improving Application Performance and Responsiveness

10. Notice how the MakeCoffees method uses a lock statement to prevent concurrent access to the critical code. 11. In Solution Explorer, double-click Program.cs. 12. In the Program class, review the Main method. 13. Notice how the Main method uses a Parallel.For loop to simultaneously place 100 orders for between one and 100 coffees. 14. On the Build menu, click Build Solution. 15. On the Debug menu, click Start Debugging. 16. Review the console window output, and notice that the application keeps track of stock levels effectively. 17. Press Enter to close the console window. 18. In the Coffee class, comment out the following line of code:
lock (coffeeLock)

19. On the Debug menu, click Start Debugging. 20. Notice that the application throws an exception with the message Stock cannot be negative! 21. Explain that this is due to concurrent access to the critical code section in the MakeCoffees method. 22. On the Debug menu, click Stop Debugging. 23. Close Visual Studio.

Programming in Visual C#

10-41 1

U Using Syn nchronizat tion Primi itives with h the Task k Parallel L Library

A synchroniza ation primitive e is a mechanism by which a an operating system enables its users, in n this case the e . .NET runtime, to control the synchroniza ation of thread ds. The Task P Parallel Library y supports a w wide range of f s synchronizatio on primitives that enable y you to control access to reso ources in a va ariety of ways. . These are t most com the mmonly used s synchronizatio on primitives: The ManualResetEven ntSlim class enables e one or more thread ds to wait for an event. A ManualR ResetEventSli im object can be in one of two states: sig gnaled and un nsignaled. If a thread calls the Wait method and the ManualR ResetEventSli im object is unsignaled, the e thread is blo ocked until the Manu ualResetEven ntSlim object state changes to signaled. In your task logic, you can n call the Set or Reset methods on t the ManualRe esetEventSlim m object to ch hange the sta ate to signaled d or unsignale ed respectively y. You typically use the Ma anualResetEv ventSlim class s to ensure tha at only one thread ca an access a res source at any one time.

Referen nce Links: For r more inform mation about t the ManualRe esetEventSlim m class, see th he ManualResetE M EventSlim Clas ss page at http://go.micros soft.com/fwlin nk/?LinkID=26 67850. The Sema aphoreSlim c class enables y you to restrict t access to a resource, r or a pool of resou urces, to a limited nu umber of concurrent threads. The Sema aphoreSlim cl lass uses an in nteger counte er to track the number o of threads tha at are currently y accessing a resource or a pool of resou urces. When y you create a Semapho oreSlim objec ct, you specify y an initial value and an optional maximu um value. Wh hen a thread wants to access the pro otected resou urces, it calls th he Wait meth hod on the Se emaphoreSlim m object. If the value of the Semap phoreSlim ob bject is above e zero, the cou unter is decrem mented and t the thread is granted a access. When the thread ha as finished, it should s call the e Release me ethod on the Semapho oreSlim objec ct, and the counter is increm mented. If a thread calls the Wait metho od and the counter is s zero, the thr read is blocke ed until anothe er thread calls s the Release e method. For example, if your coffe ee shop has three coffee m machines and e each can only y process one order at a tim me, you might t use a Sem maphoreSlim m object to pre event more th han three thre eads simultane eously orderin ng a coffee.

Additio onal Reading: For more inf formation abo out the SemaphoreSlim class, see the SemaphoreSli S im Class page e at http://go.microsoft.com m/fwlink/?Link kID=267851.

10-42

Improving Application Performance and Responsiveness

The CountdownEvent class enables you to block a thread until a fixed number of threads have signaled the CountdownEvent object. When you create a CountdownEvent object, you specify an initial integer value. When a thread completes an operation, it can call the Signal method on the CountdownEvent object to decrement the integer value. Any threads that call the Wait method on the CountdownEvent object are blocked until the counter reaches zero. For example, if you need to run ten tasks before you continue with your code, you can create a CountdownEvent object with an initial value of ten, signal the CountdownEvent object from each task, and wait for the CountdownEvent object to reach zero before you proceed. This is useful because your code can dynamically set the initial value of the counter depending on how much work there is to be done.

Additional Reading: For more information about the CountdownEvent class, see the CountdownEvent Class page at http://go.microsoft.com/fwlink/?LinkID=267852. The ReaderWriterLockSlim class enables you to restrict write access to a resource to one thread at a time, while permitting multiple threads to read from the resource simultaneously. If a thread wants to read the resource, it calls the EnterReadLock method, reads the resource, and then calls the ExitReadLock method. If a thread wants to write to the resource, it calls the EnterWriteLock method. If one or more threads have a read lock on the resource, the EnterWriteLock method blocks until all read locks are released. When the thread has finished writing to the resource, it calls the ExitWriteLock method. Calls to the EnterReadLock method are blocked until the write lock is released. As a result, at any one time, a resource can be locked by either one writer or multiple readers. This type of read/write lock is useful in a wide range of scenarios. For example, a banking application might permit multiple threads to read an account balance simultaneously, but a thread that wants to modify the account balance requires an exclusive lock.

Additional Reading: For more information about the ReaderWriterLockSlim class, see the ReaderWriterLockSlim Class page at http://go.microsoft.com/fwlink/?LinkID=267853. The Barrier class enables you to temporarily halt the execution of several threads until they have all reached a particular point. When you create a Barrier object, you specify an initial number of participants. You can change this number at a later date by calling the AddParticipant and RemoveParticipant methods. When a thread reaches the synchronization point, it calls the SignalAndWait method on the Barrier object. This decrements the Barrier counter and also blocks the calling thread until the counter reaches zero. When the counter reaches zero, all threads are allowed to continue. The Barrier class is often used in forecasting scenarios, where various tasks perform interrelated calculations on one time window and then wait for all of the other tasks to reach the same point before performing interrelated calculations on the next time window.

Additional Reading: For more information about the Barrier class, see the Barrier Class page at http://go.microsoft.com/fwlink/?LinkID=267854. Many of these classes enable you to set timeouts in terms of the number of spins. When a thread is waiting for an event, it spins. The length of time a spin takes depends on the computer that is running the thread. For example, if you use the ManualResetEventSlim class, you can specify the maximum number of spins as an argument to the constructor. If a thread is waiting for the ManualResetEventSlim object to signal and it reaches the maximum number of spins, the thread is suspended and stops using processor resources. This helps to ensure that waiting tasks do not consume excessive processor time.

Programming in Visual C#

10-43 3

U Using Con ncurrent C Collection ns

The standard collection classes in the .NET Framework T k are, by default, not thread-safe. When you access c collections fro om tasks or ot ther multithre eading techniq ques, you mus st ensure that t you do not c compromise t integrity o the of the collectio ons. One way y to do this is to t use the syn nchronization primitives de escribed e earlier in this lesson to control concurren nt access to your collection ns. However, t the .NET Fram mework also i includes a set of collections s that are specifically designed for thread-safe access. . The following table d describes som me of the class ses and interfa aces that the S System.Colle ections.Concu urrent names space p provides. Class or inte erface ConcurrentBag<T> ConcurrentDictionary<TK Key, TValue> ConcurrentQ Queue<T> ConcurrentS Stack<T> IProducerCo onsumerColle ection<T> Descripti ion This clas ss provides a t thread-safe way to store an unord dered collection of items. This clas ss provides a t thread-safe alternative to the Dict tionary<TKey y, TValue> class. This clas ss provides a t thread-safe alternative to the Que eue<T> class. This clas ss provides a t thread-safe alternative to the Stac ck<T> class. This inte erface defines methods for impleme enting classes that exhibit produce er/consumer behavior; b in ot ther words, classes that distinguis sh between pr roducers who ms to a collect tion and consu umers who add item read item ms from a collection. This distinction d is importan ns need to nt because these collection impleme ent a read/wri ite locking pattern, where the colle ection can be locked either by a single writer or r by multiple readers. r The Concurr rentBag<T>, ConcurrentQ Queue<T>, and Con ncurrentStack k<T> classes all impleme ent this interfa ace.

10-44

Improving Application Performance and Responsiveness

Class or interface BlockingCollection<T>

Description This class acts as a wrapper for collections that implement the IProducerConsumerCollection<T> interface. For example, it can block read requests until a read lock is available, rather than simply refusing a request if a lock is unavailable. You can also use the BlockingCollection<T> class to limit the size of the underlying collection. In this case, requests to add items are blocked until space is available.

Consider an order management system for Fourth Coffee that uses a ConcurrentQueue<T> object to represent the queue of orders that customers have placed. Orders are added to the queue at a single order point, but they can be picked up by one of three baristas working in the store. The following example simulates this scenario by creating one task that places an order every 0.25 seconds and three tasks that pick up orders as they become available. The following code example shows how to use the ConcurrentQueue<T> class to queue and de-queue objects in a thread-safe way. Using the ConcurrentQueue<T> Collection
class Program { static ConcurrentQueue<string> queue = new ConcurrentQueue<string>(); static void PlaceOrders() { for (int i = 1; i <= 100; i++) { Thread.Sleep(250); String order = String.Format("Order {0}", i); queue.Enqueue(order); Console.WriteLine("Added {0}", order); } } static void ProcessOrders() { while (true) //continue indefinitely if (queue.TryDequeue(out order)) { Console.WriteLine("Processed {0}", order); } } static void Main(string[] args) { var taskPlaceOrders = Task.Run(() => PlaceOrders()); Task.Run(() => ProcessOrders()); Task.Run(() => ProcessOrders()); Task.Run(() => ProcessOrders()); taskPlaceOrders.Wait(); Console.WriteLine("Press ENTER to finish"); Console.ReadLine(); } }

Reference Links: For more information about using concurrent collections, see System.Collections.Concurrent Namespace at http://go.microsoft.com/fwlink/?LinkID=267855 and Concurrent Collections in the .NET Framework 4 at http://go.microsoft.com/fwlink/?LinkID=267856.

Programming in Visual C#

10-45 5

Demonstr D ration: Im mproving t the Respo onsiveness s and Perf formance of the A Applicatio on

I this demon In nstration, you will learn abo out the tasks t that you will p perform in the e lab for this module. m

10-46

Impro oving Application Performance and Resp ponsiveness

Lab: Im mproving the Responsivene ess and Perfor rmance of the Ap pplicati ion

Sc cenario
Yo ou have been asked to upda ate the Grade es application to ensure tha at the UI rema ains responsiv ve while the use er is waiting f for operations s to complete. . To achieve th his improvem ment in respon nsiveness, you decide to You also convert the logi ic that retrieve es the list of students s for a teacher to us se asynchrono ous methods. Y de ecide to provid de visual feedback to the u user to indicate when an op peration is tak king place.

Ob bjectives
Aft ter completing this lab, you u will be able to: ync and await t keywords to o implement asynchronous a methods. Use the asy Use events and user cont trols to provid de visual feedback during long-running operations.

timated Time: : 75 minutes Est Virtual Mac chine: 20483A A-SEA-DEV11-10, MSL-TMG G1 User Name: Student P Password: Pa$$w0rd

Programming in Visual C# 10-47

Exercise 1: Ensuring That the UI Remains Responsive When Retrieving Teacher Data
Scenario
In this exercise, you will modify the functionality that retrieves data for teachers to make use of asynchronous programming techniques. First, you will modify the code that gets the details of the current user (when the user is a teacher) to run asynchronously. You will use an asynchronous task to run the LINQ query and use the await operator to return the results of the query. Next, you will modify the code that retrieves the list of students for a teacher. In this case, you will configure the code that retrieves the list of students to run asynchronously. When the operation is complete, your code will invoke a callback method to update the UI with the list of students. Finally, you will build and test the application and verify that the UI remains responsive while the application is retrieving data. The main tasks for this exercise are as follows: 1. Build and run the application 2. Modify the code that retrieves teacher data to run asynchronously 3. Modify the code that retrieves and displays the list of students for a teacher to run asynchronously 4. Build and test the application

X Task 1: Build and run the application


1. 2. 3. 4. Start the MSL-TMG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-10 virtual machine and log on as Student with the password Pa$$w0rd. Start Visual Studio, and then open the Grades.sln solution from the E:\Labfiles\Starter\Exercise 1 folder. Set the following projects to start without debugging at startup: a. b. 5. 6. 7. 8. 9. Grades.Web Grades.WPF

Build the solution, and then resolve any compilation errors. Run the application. Log on as vallee with a password of password99. Notice that the UI briefly freezes while fetching the list of students for Esther Valle (try moving the application window after logging on but before the list of students appears). Close the application.

X Task 2: Modify the code that retrieves teacher data to run asynchronously
1. 2. In the Grades.WPF project, in the Services folder, open ServiceUtils.cs. Modify the GetTeacher method declaration so that it: a. b. 3. Runs asynchronously. Returns a Task<Teacher> object.

In the GetTeacher method, use the await operator to run the LINQ query asynchronously and return a Task<Teacher> object.

10-48

Improving Application Performance and Responsiveness

4. 5.

In the MainWindow class, modify the Refresh method declaration so that the method runs asynchronously. In the Refresh method, in the case "Teacher" block, modify the call to the GetTeacher method to run asynchronously.

X Task 3: Modify the code that retrieves and displays the list of students for a teacher to run asynchronously
1. 2. 3. In the StudentsPage class, modify the Refresh method declaration so that the method runs asynchronously. In the Refresh method, in the Callbacks region, locate the code that iterates through the returned set of students and updates the UI. Factor out this code into a new method named OnGetStudentsByTeacherComplete. This method should: a. b. c. 4. Accept a single argument of type IEnumerable<Student>. Return void. Use a Dispatcher object to update the UI.

In the ServiceUtils class, modify the GetStudentsByTeacher method declaration so that it: a. b. c. Runs asynchronously. Returns a Task object. Accepts a delegate argument that can represent the OnGetStudentsByTeacherComplete callback method.

5. 6. 7. 8.

Modify the GetStudentsByTeacher method so that it returns without passing a value if the call to IsConnected returns false. In the GetStudentsByTeacher method, use the await operator to run the LINQ query asynchronously and return a Task<Student> object. Modify the GetStudentsByTeacher method so that it invokes the callback method delegate asynchronously rather than returning the results. In the StudentsPage class, modify the Refresh method so that it: a. b. Calls the GetStudentsByTeacher method asynchronously. Passes the OnGetStudentsByTeacherComplete method as the second argument.

X Task 4: Build and test the application


1. 2. 3. 4. 5. Build the solution and resolve any compilation errors. Run the application. Log on as vallee with a password of password99. Verify that the application is more responsive than before while fetching the list of students for Esther Valle. Close the application, and then close the solution.

Results: After completing this exercise, you should have updated the Grades application to retrieve data asynchronously.

Programming in Visual C# 10-49

10-50

Improving Application Performance and Responsiveness

Exercise 2: Providing Visual Feedback During Long-Running Operations


Scenario
In this exercise, you will create a user control that displays a progress indicator while the Grades application is retrieving data. You will add this user control to the main page but will initially hide it from view. Next, you will modify the code that retrieves data so that it raises one event when the data retrieval starts and another event when the data retrieval is complete. You will create handler methods for these events that toggle the visibility of the progress indicator control, so that the application displays the progress indicator when data retrieval starts and hides it when data retrieval is complete. Finally, you will build and test the application and verify that the UI displays the progress indicator while the application is retrieving data. The main tasks for this exercise are as follows: 1. Create the BusyIndicator user control 2. Add StartBusy and EndBusy event handler methods 3. Raise the StartBusy and EndBusy events 4. Build and test the application

X Task 1: Create the BusyIndicator user control


1. 2. 3. 4. Start the MSL-TMG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-10 virtual machine and log on as Student with the password Pa$$w0rd. Start Visual Studio, and then open the Grades.sln solution from the E:\Labfiles\Starter\Exercise 2 folder. Set the following projects to start without debugging at startup: a. b. 5. 6. 7. Grades.Web Grades.WPF

Build the solution. In the Grades.WPF project, create a new user control named BusyIndicator.xaml. Move the BusyIndicator.xaml file into the Controls folder.

Note: It is better to create the user control at the project level and then move it into the Controls folder when it is created. This ensures that the user control is created in the same namespace as other project resources. 8. 9. Ensure that the user control does not specify dimensions by deleting the DesignWidth and DesignHeight properties. In the BusyIndicator.xaml file, modify the existing Grid element to have a background color of #99000000.

10. In the Grid element, add a Border element with the following characteristics: a. b. Set the corner radius to 6 units. Set the horizontal and vertical alignments to Center.

Programming in Visual C# 10-51

c. d.

Set the background to a horizontal linear gradient from light gray to dark gray. Add a drop shadow effect with opacity of 0.75.

11. In the Border element, add a Grid element with the following characteristics: a. b. Set the margin to 10 units. Define two rows with automatically determined heights.

12. In the first row of the Grid element, add a ProgressBar element with the following characteristics: a. b. c. d. e. Set the width to 200 units. Set the height to 25 units. Set the margin to 20 units. Set the name of the control to progress. Set the progress bar to provide generic, continuous feedback rather than actual values (hint: use the IsIndeterminate attribute).

13. In the second row of the Grid element, add a TextBlock element with the following characteristics: a. b. c. d. e. Set the font size to 14 points. Apply the Verdana font. Set the text alignment to Center. Display the message Please Wait Set the name of the control to txtMessage.

14. Save all files. 15. In the Grades.WPF project, in the MainWindow.xaml file, add a BusyIndicator element with the following characteristics: a. b. c. d. Set the margin to 0. Set the visibility to Collapsed. Set the name of the control to busyIndicator. Build the solution.

X Task 2: Add StartBusy and EndBusy event handler methods


1. In the MainWindow class, add a private method named StartBusy. The method should: a. b. 2. 3. Return void. Accept two arguments, of type object and EventArgs respectively.

In the StartBusy method, make the busyIndicator control visible. In the MainWindow class, add a private method named EndBusy. The method should: a. b. Return void. Accept two arguments, of type object and EventArgs respectively.

4.

In the EndBusy method, make the busyIndicator control hidden.

X Task 3: Raise the StartBusy and EndBusy events


1. In the StudentsPage class, add a public event named StartBusy.

10-52

Improving Application Performance and Responsiveness

2. 3. 4. 5. 6. 7. 8. 9.

Add a public event named EndBusy. Add a method named StartBusyEvent that takes no arguments and returns void. In the StartBusyEvent method, raise the StartBusy event. Add a method named EndBusyEvent that takes no arguments and returns void. In the EndBusyEvent method, raise the EndBusy event. In the MainWindow.xaml file, in the StudentsPage element, associate the StartBusy event handler method with the StartBusy event. In the StudentsPage element, associate the EndBusy event handler method with the EndBusy event. In the StudentsPage class, at the start of the Refresh method, raise the StartBusy event by calling the StartBusyEvent method.

10. At the end of the Refresh method, raise the EndBusy event by calling the EndBusyEvent method.

X Task 4: Build and test the application


1. 2. 3. 4. 5. Build the solution and resolve any compilation errors. Run the application. Log on as vallee with a password of password99. Verify that the application displays the busy indicator while waiting for the list of students to load. Close the application, and then close the solution.

Results: After completing this exercise, you should have updated the Grades application to display a progress indicator while the application is retrieving data.

Programming in Visual C#

10-53 3

Module Rev view an nd Take eaways

M Module Rev view


In this module I e, you have le earned a varie ety of asynchro onous programming techn niques for Visu ual C#, i including how w to use the Task Parallel Li ibrary, how to o use the asyn nc and await keywords, and d how to use s synchronizatio on primitives. T Test Your Kno owledge Question You create a and start thre ee tasks name ed task1, task k2, and task3. You want to block the joining thre ead until all of f these tasks are complete e. Which code e example sho ould you use to accomplish this? Select the correct answer r. task k1.Wait(); task k2.Wait(); task k3.Wait(); Task k.WaitAll(task1 1, task2, task3 3); Task k.WaitAny(task1, task2, task k3); Task k.WhenAll(task k1, task2, task k3); Task k.WhenAny(ta ask1, task2, tas sk3); T Test Your Kno owledge Question You have a s synchronous method with h the followin ng signature: public IEnum merable<strin ng> GetCoffe ees(string cou untry, int stre ength) You want to o convert this s method to an a asynchrono ous method. What should the

10-54

Improving Application Performance and Responsiveness

Question signature of the asynchronous method be? Select the correct answer. public async IEnumerable<string> GetCoffees(string country, int strength) public async Task<string> GetCoffees(string country, int strength) public async Task<IEnumerable<string>> GetCoffees(string country, int strength) public async Task GetCoffees(string country, int strength, out string result) public async Task GetCoffees(string country, int strength, out IEnumerable<string> result) Test Your Knowledge Question You want to ensure that no more than five threads can access a resource at any one time. Which synchronization primitive should you use? Select the correct answer. The ManualResetEventSlim class. The SemaphoreSlim class. The CountdownEvent class. The ReaderWriterLockSlim class. The Barrier class.

11-1

Module 11
Integrating with Unmanaged Code
Contents:
Module Overview Lesson 1: Creating and Using Dynamic Objects Lesson 2: Managing the Lifetime of Objects and Controlling Unmanaged Resources Lab: Upgrading the Grades Report Module Review and Takeaways 11-2 11-3 11-12 11-20 11-25

11-2 Integrat ting with Unmanage ed Code

Modu ule Ove erview

Software system ms can be com mplex and may y involve applications that are implemen nted in a varie ety of tec chnologies. Fo or example, so ome applications may be m managed Micr rosoft .NET Framework ap pplications, wh hereas others may be unma anaged C++ a applications. Y You may want t to use functionality from one ap pplication in another or use functionality that is exposed through Component Ob bject Model (COM) ass semblies, such h as the Micro osoft Word 14 4.0 Object Library assembly y, in your appl lications. In this module, y you will learn how to intero operate unma anaged code in your applic cations and ho ow to ensure that your code release es any unman naged resourc ces.

Ob bjectives
Aft ter completing this module e, you will be able to: ode into a Mic crosoft Visual C# applicat tion by using the Dynamic Language Integrate unmanaged co DLR). Runtime (D e lifetime of un nmanaged res sources and ensure e that yo our application n releases reso ources. Control the

Programming in i Visual C#

11-3 3

Lesson 1

Creat ting an nd Using g Dyna amic Ob bjects

There are man T ny different programming p languages av vailable, each w with its own s set of advanta ages and d disadvantages s and scenario os where it is better suited. Having the a ability to consume components that are i implemented in other languages enable es you to reuse e functionality y that may alr ready exist in your o organization. I this lesson, you will learn In n how to use the t DLR to int teroperate wit th unmanaged code.

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Describe the purpose o of dynamic ob bjects. Describe the purpose o of the DLR. Create a d dynamic obje ect. Invoke methods on a d dynamic objec ct.

11-4 Integrat ting with Unmanage ed Code

W What Are Dynamic D O Objects?

Vis sual C# is a strongly typed static languag ge. When you u create a variable, you specify the type of o that variable, and yo ou can only inv voke methods and access m members that t this type def fines. If you tr ry to call a me ethod that the e type does not implement t, your code w will not compile. This is goo od because the compile tim me checks catc ch a large num mber of possible errors eve en before you run your cod de. The .NET Frame ework provide es dynamic ob bjects so that you y can define objects that t are not cons strained by the e static type system s in Visual C#. Instead d, dynamic obj bjects are not t type checked until run time e, which enables you to write w code qu uickly without worrying abo out defining e every member r until you nee ed to call the em in your co ode. Yo ou can use dyn namic objects s in your .NET Framework a applications to o take advanta age of dynam mic lan nguages and unmanaged u c code.

Dy ynamic Lan nguages


Languages such h as IronPytho on and IronRuby are dynam mic and enable e you to write e code that is not compiled until r run time. Dynamic languag ges provide th he following benefits: b They enable e faster develo opment cycle es because the ey do not requ uire a build or r compile pro ocess. They have increased flexibility over sta atic languages s because the ere are no stat tic types to wo orry about. ot have a stron ngly typed obj ject model to o learn. They do no

ynamic langua ages do suffer r from slower execution tim mes in compar rison with com mpiled langua ages, Dy be ecause any optimization ste eps that a com mpiler may tak ke when comp piling the cod de are left out of the bu uild process.

Un nmanaged Code
Vis sual C# is a managed m langu uage, which m means that the e Visual C# co ode you write is executed b by a run ntime environ nment known as the Comm mon Language e Runtime (CL LR). The CLR p provides other r benefits, suc ch as memory y managemen nt, Code Access Security (CA AS), and exception handlin ng. Unmanage ed code suc ch as C++ exe ecutes outside e the CLR and d in general be enefits from f faster executio on times and being ext tremely flexib ble. Wh hen you build d applications by using the .NET Framew work, it is a com mmon use cas se to want to reuse un nmanaged cod de. Maybe you have a legacy C++ system m that was im mplemented a decade ago, or maybe

Programming in Visual C# 11-5

you just want to use a function in the user32.dll assembly that Windows provides. The process of reusing functionality that is implemented in technologies other than the .NET Framework is known as interoperability. These technologies can include: COM C++ Microsoft ActiveX Microsoft Win32 application programming interface (API)

Dynamic objects simplify the code that is required to interoperate with unmanaged code. Additional Reading: For more information about dynamic objects, see the DynamicObject Class page at http://go.microsoft.com/fwlink/?LinkID=267857.

11-6 Integrat ting with Unmanage ed Code

W What Is the e Dynamic c Languag ge Runtim me?

The .NET Frame ework provide es the DLR, wh hich contains t the necessary y services and components to support dy ynamic langua ages and prov vides an appro oach for intero operating with unmanaged d components s. The DLR is responsible r fo or managing t the interaction ns between th he executing assembly a and the dynamic object, for exa ample, an obj ject that is implemented in IronPython o or in a COM assembly. The DLR simplif fies interopera ating with dyn namic objects in the followi ings ways: It defers typ pe-safety chec cking for unm managed resou urces until run n time. Visual C# is a type-s safe language and, by default t, the Visual C C# compiler pe erforms type-safety checking at compile e time.

pe safety relies s on the comp piler being ab ble to compile e or interpret e each of the Note: Typ components tha at the solution n references. When W interop perating with unmanaged c components, t the compile-time ty ype-safety che eck is not alwa ays possible. It abstracts the intricate details d of inte eroperating wi ith unmanage ed componen nts, including marshaling m data between the manag ged and unma anaged enviro onments.

The DLR does not provide functionality tha at is pertinent t to a specific language but t provides a set of lan nguage binde ers. A language binder cont tains instructio ons on how to o invoke meth hods and mar rshal data be etween the un nmanaged language, such a as IronPython, and the .NET T Framework. The language binders als so perform run-time type c checks, which include check king that a me ethod with a g given signature actually exists in the object. Additiona al Reading: F For more infor rmation about the DLR, see e the Dynamic c Language Ru untime Overview page at ht ttp://go.micro osoft.com/fwli ink/?LinkID=2 267858.

Programming in i Visual C#

11-7 7

C Creating a Dynamic c Object

The DLR infrastructure prov T vides the dyn namic keyword to enable you to define d dynamic objects in your a applications. W When you use e the dynami ic keyword to declare a dyn namic object, it has the following i implications: It defines a variable of type object. You can assig gn any value t to this variable e and attempt t to call any methods. . At run time, the DLR will u use the langua age binders to o type check y your dynamic c code and ensure th hat the member you are try ying to invoke e exists. It instruct ts the compile er not to perfo orm type chec cking on any dynamic code e. It suppres sses the Micro osoft IntelliSen nse feature because Intel lliSense is una able to provide syntax assistance e for dynamic c objects.

To create a dy T ynamic object t to consume the Microsoft t.Office.Intero op.Word COM M assembly, pe erform the f following step ps: 1 1. 2 2. In your .N NET Framewor rk project, add d a reference to the Micros soft.Office.Inte erop.Word CO OM assembly. . Bring the Microsoft.O Office.Interop p.Word name espace into sco ope.

The following code example shows how to create an instance of th T he Applicatio on COM class in the M Microsoft.Of ffice.Interop. .Word names space by using g the dynamic keyword. D Dynamic Var riable Declara ation
using Micro osoft.Office e.Interop.Word; ... dynamic wor rd = new App plication();

After you hav A ve created an i instance of th he class, you can use the me embers that it t provides in t the same way y y would wit you th any.NET Fr ramework clas ss. Additio onal Reading: For more inf formation abo out the dynam mic keyword, see the Using g T Type dynamic c (C# Program mming Guide) page at http: ://go.microsoft.com/fwlink/ /?LinkID=267 7859.

11-8 Integrat ting with Unmanage ed Code

In nvoking M Methods on a Dynam mic Objec ct

Aft ter you have instantiated i a dynamic obje ect by using t the dynamic keyword, you can access th he pro operties and m methods by u using the stand dard Visual C# # dot notation. The following co ode example shows how yo ou can use the Add metho od of the Docu ument class in the Word int terop library t to create a new w Word docu ument. Inv voking a Met thod on a Dy ynamic Objec ct
/ // Start Microsoft Word. . d dynamic word = new Appli ication(); ... / // Create a n new document t. d dynamic doc = word.Docum ments.Add(); d doc.Activate();

Yo ou can also pa ass parameters s to dynamic object metho od calls as you u would with a any .NET Fram mework ob bject. The following co ode example shows how yo ou can pass a string variabl le to a method that a dynamic object exposes. assing Parameters to a Me ethod Pa
s string filePa ath = "C:\\F FourthCoffee e\\Documents\ \\Schedule.d docx"; ... d dynamic word = new Appli ication(); d dynamic doc = word.Docum ments.Open(f filePath); d doc.SaveAs(fi ilePath);

Tra aditionally wh hen consuming a COM asse embly, the .NE ET Framework k required you u to use the re ef keyword and pass a Type e.Missing obj ject to satisfy any optional parameters th hat a method contains. Also, any parameters that t you pass mu ust be of type object. This c can result in simple method d calls requirin ng a long list t of Type.Mis ssing objects and code that t is verbose an nd difficult to o read. By usin ng the dynam mic key yword, you ca an invoke the same method ds but with le ess code.

Programming in Visual C# 11-9

Best Practice: When using dynamic objects in your code to encapsulate classes that are exposed in COM assemblies, use the Object Browser feature in Microsoft Visual Studio to view the COM API. Additional Reading: For more information about how to create and consume dynamic methods, see the How to: Define and Execute Dynamic Methods page at http://go.microsoft.com/fwlink/?LinkID=267860.

11-10

Integr rating with Unmanag ged Code

Demonstration: Inte eroperatin ng with Microsoft W Word

In this demonstration, you wi ill use dynami ic objects to c consume the M Microsoft.Offi ice.Interop.Wo ord COM ass sembly in an existing e .NET Framework ap pplication. The application will use the W Word object m model to combine several text files that c contain excep ption inf formation into o an exception n report in Word format. The code uses the Word obj ject model to add data s, and formatt fro om the text files, line breaks ting to genera ate the final document. d

De emonstration Steps
1. 2. 3. Start the MSL-TMG1 virtual machine if it is not already running. 0483A-SEA-DE EV11-11 virtual machine. Start the 20 Log on to W Windows 8 as a Student with the passwo ord Pa$$w0r rd. Note: If necessary, click k Switch User r to display th he list of users s. 4. 5. 6. 7. 8. 9. Switch to th he Windows 8 Start window w. Click Visual Studio 2012. udio, on the F File menu, point to Open, and a then click k Project/Solution. In Visual Stu In the Open n Project dial log box, brow wse to the E:\D Democode\Sta arter\FourthCoffee.Exceptio onLogger folder, click k FourthCoffe ee.ExceptionLogger.sln, a and then click Open. In the Solut tion Explorer window, w right t-click the Fou urthCoffee.Exc ceptionLogge er project, and d then click Add Reference. ger FourthC Coffee.Excep ptionLogger d dialog box, pe erform the following In the Reference Manag steps, and t then click OK: a. b. c. Expand d COM, and th hen click Type e Libraries. In the S Search box, ty ype Word. In the a assembly list, select Microso oft Word 14.0 0 Object Library, and then s select the Mic crosoft Word 1 14.0 Object Library check b box.

Programming in Visual C# 11-11

10. In Visual Studio, on the View menu, click Task List. 11. In the Task List window, in the Categories list, click Comments. 12. Double-click the TODO: 01: Bring the Microsoft.Office.Interop.Word namespace into scope. task. 13. In the code editor, click in the blank line below the comment, and then type the following code:
using Microsoft.Office.Interop.Word;

14. Double-click the TODO: 02: Declare a global object to encapsulate Microsoft Word. task. 15. In the code editor, click in the blank line below the comment, and then type the following code:
dynamic _word;

16. Double-click the TODO: 03: Instantiate the _word object. task. 17. In the code editor, click in the blank line below the comment, and then type the following code:
this._word = new Application();

18. Double-click the TODO: 04: Create a blank Word document. task. 19. In the code editor, click in the blank line below the comment, and then type the following code:
this._word.Documents.Add().Activate();

20. In the code editor, look at the following helper methods that wrap the Word COM API: a. The GetEndOfDocument method places the cursor at the end of the document. The -1 converts the End property to a 0-based index value. Without the -1, the CLR will throw an IndexOutOfRange exception. The AppendText method adds text to the end of the document, in the bold and/or italic style. The InsertCarriageReturn method inserts a carriage return at the end of the document. The Save method deletes any file with the same name and then saves the current Word document.

b. c. d.

21. On the Build menu, click Build Solution. 22. On the Debug menu, click Start Without Debugging. 23. In the Exception Logger application, click Export. 24. In the Export Successful dialog box, click OK. 25. Close the Exception Logger application. 26. Open File Explorer and browse to the E:\Democode\Data\Exceptions folder. 27. Double-click Exceptions.docx, and then view the combined exception report in the Word document. 28. Close Microsoft Word. 29. Close File Explorer. 30. Close Visual Studio.

11-12

Integr rating with Unmanag ged Code

Lesson 2

Managing th he Lifetime of Object ts and Control C ling anaged Resour rces Unma

Wh hen interoper rating with un nmanaged res sources, it is im mportant that t you manage and release t these res sources when you are no lo onger using th hem. In this lesson, yo ou will learn a about the life cycle of a typical .NET Fram mework objec ct and how to ensure that ob bjects release the t resources that they hav ve been using when they are destroyed.

Le esson Obje ectives


Aft ter completing this lesson, you will be ab ble to: f a .NET Frame ework object. Describe the life cycle of p Implement the dispose pattern. Manage the e lifetime of a an object.

Programming in Visual C#

11-13 3

T Objec The ct Life Cyc cle

The life cycle of an object h T has several sta ages, which st tart at creation n of the objec ct and end in its d destruction. T To create an object o in your application, y you use the ne ew keyword. W When the CLR R executes c code to create e a new objec ct, it performs s the following g steps: 1 1. 2 2. It allocate es a block of m memory large e enough to h hold the objec ct. It initializes the block o of memory to the new obje ect.

The CLR hand T dles the allocation of memo ory for all man naged objects s. However, when you use u unmanaged o objects, you m may need to write w code to a allocate mem mory for the un nmanaged ob bjects that you u create. When you hav W ve finished wi ith an object, you can dispo ose of it to release any reso ources, such a as database c connections a file handle and es, that it consumed. When n you dispose of an object, the CLR uses a feature c called the gar rbage collecto or (GC) to perf form the follo owing steps: 1 1. 2 2. The GC re eleases resour rces. The mem mory that is allocated to the e object is recl laimed.

The GC runs a T automatically in a separate thread. When n the GC runs s, other thread ds in the appli ication are h halted, because the GC may move objec cts in memory y and therefor re must updat te the memor ry pointers. Additio onal Reading: For more inf formation abo out GC, see th he Garbage Co ollection page e at http://go.micr h rosoft.com/fw wlink/?LinkID= =267861.

11-14

Integr rating with Unmanag ged Code

Im mplementing the Dispose Pat ttern

The dispose pat ttern is a desig gn pattern tha at frees resources that an o object has used. The .NET Framework pro dispose ovides the IDisposable interface in the System name espace to enable you to im mplement the d pattern in your applications. efines a single e parameterles ss method named Dispose e. You should use the The IDisposable interface de Dispose method to release a all of the unmanaged resou urces that your object consu umed. If the o object is part of an inher ritance hierarc chy, the Dispo ose method can also releas se resources th hat the base t types consumed by ca alling the Disp pose method on the paren nt type. Invoki ing the Dispo ose method does not de estroy an object. The object t remains in memory m until t the final reference to the object is remov ved and the GC C reclaims any y remaining re esources. nmanaged resources, such as the Stream Ma any of the classes in the .NET Framework k that wrap un mWriter cla ass, implemen nt the IDispos sable interface e. You should also impleme ent the IDispo osable interfa ace when you create your r own classes that t reference e unmanaged types.

Im mplementin ng the IDisp posable Inte erface


To o implement the IDisposab ble interface in n your applica ation, perform m the following steps: 1. t that the Syst tem namespa ace is in scope e. Ensure that
using Sys stem;

2.

Implement the IDisposa able interface in your class d definition.


... public cl lass Managed dWord : IDisp posable { public c void Dispo ose() { thr row new NotI ImplementedEx xception(); } }

3.

Add a priva ate field to the e class, which you can use t to track the disposal status of the object t, and check whether the e Dispose me ethod has alre eady been invoked and the e resources released.
public cl lass Managed dWord : IDisposable

Programming in Visual C# 11-15

{ bool _isDisposed; ... }

4.

Add code to any public methods in your class to check whether the object has already been disposed of. If the object has been disposed of, you should throw an ObjectDisposedException.
public void OpenWordDocument(string filePath) { if (this._isDisposed) throw new ObjectDisposedException("ManagedWord"); ... }

5.

Add an overloaded implementation of the Dispose method that accepts a Boolean parameter. The overloaded Dispose method should dispose of both managed and unmanaged resources if it was called directly, in which case you pass a Boolean parameter with the value true. If you pass a Boolean parameter with the value of false, the Dispose method should only attempt to release unmanaged resources. You may want to do this if the object has already been disposed of or is about to be disposed of by the GC.
public class ManagedWord : IDisposable { ... protected virtual void Dispose(bool isDisposing) { if (this._isDisposed) return; if (isDisposing) { // Release only managed resources. ... } // Always release unmanaged resources. ... // Indicate that the object has been disposed. this._isDisposed = true; } }

6.

Add code to the parameterless Dispose method to invoke the overloaded Dispose method and then call the GC.SuppressFinalize method. The GC.SuppressFinalize method instructs the GC that the resources that the object referenced have already been released and the GC does not need to waste time running the finalization code.
public void Dispose() { Dispose(true); GC.SuppressFinalize(this); }

After you have implemented the IDisposable interface in your class definitions, you can then invoke the Dispose method on your object to release any resources that the object has consumed. You can invoke the Dispose method from a destructor that is defined in the class.

Implementing a Destructor
You can add a destructor to a class to perform any additional application-specific cleanup that is necessary when your class is garbage collected. To define a destructor, you add a tilde (~) followed by the name of the class. You then enclose the destructor logic in braces.

11-16

Integrating with Unmanaged Code

The following code example shows the syntax for adding a destructor. Defining a Destructor
class ManagedWord { ... // Destructor ~ManagedWord { // Destructor logic. } }

When you declare a destructor, the compiler automatically converts it to an override of the Finalize method of the object class. However, you cannot explicitly override the Finalize method; you must declare a destructor and let the compiler perform the conversion. If you want to guarantee that the Dispose method is always invoked, you can include it as part of the finalization process that the GC performs. To do this, you can add a call to the Dispose method in the destructor of the class. The following code example shows how to invoke the Dispose method from a destructor. Calling the Dispose Method from a Destructor
class ManagedWord { ... // Destructor ~ManagedWord { Dispose(false); } }

Additional Reading: For more information about the IDisposable interface, see the IDisposable Interface page at http://go.microsoft.com/fwlink/?LinkID=267862.

Programming in Visual C#

11-17 7

M Managing g the Lifet time of an n Object

Using types th U hat implemen nt the IDispos sable interface e is not suffici ient to manag ge resources. Y You must a remembe also er to invoke th he Dispose method m in you ur code when you have finis shed with the object. If you u c choose not to o implement a destructor th hat invokes th he Dispose method when t the GC proces sses the o object, you ca an do this in a number of o other ways. O approach One h is to explicit tly invoke the Dispose met thod after any y other code t that uses the o object. The following code example shows how you can invo T oke the Dispose method on n an object th hat i implements th he IDisposab ble interface. I Invoking the e Dispose Me ethod
var word = new Managed dWord(); // Code to o use the Ma anagedWord object. word.Dispos se();

Invoking the Dispose I D meth hod explicitly after code that uses the ob bject is perfec ctly acceptable e, but if your c code throws a an exception before b the call to the Dispo ose method, t the Dispose m method will n never be i invoked. A more reliab ble approach is to invoke th he Dispose method in the finally f block o of a try/catch h/finally or a t /finally sta try atement. Any code in the sc cope of the fi inally block w will always exe ecute, regardle ess of any e exceptions tha at might be th hrown. Theref fore, with this s approach, yo ou can always guarantee th hat your code w invoke the will e Dispose me ethod. T following code example shows how you can invo The oke the Dispose method in a finally bloc ck. I Invoking the e Dispose Me ethod in a finally Block
var word = default(Man nagedWord); try { word = n new ManagedW Word(); // Code to use the ManagedWord object. } catch { // Code e to handle any errors. }

11-18

Integrating with Unmanaged Code

finally { if(word!=null) word.Dispose(); }

Note: When explicitly invoking the Dispose method, it is good practice to check whether the object is not null beforehand, because you cannot guarantee the state of the object. Alternatively, you can use a using statement to implicitly invoke the Dispose method. A using block is exception safe, which means that if the code in the block throws an exception, the runtime will still dispose of the objects that are specified in the using statement. The following code example shows how to implicitly dispose of your object by using a using statement. Disposing Of an Object by Using a using Statement
using (var word = default(ManagedWord)) { // Code to use the ManagedWord object. }

If your object does not implement the IDisposable interface, a try/finally block is an exception-safe approach to execute code to release resources. You should aim to use a try/finally block when it is not possible to use a using statement. Additional Reading: For more information about using statements, see the using Statement (C# Reference) page at http://go.microsoft.com/fwlink/?LinkID=267863.

Programming in Visual C#

11-19 9

D Demonstr ration: Up pgrading the Grade es Report Lab

I this demon In nstration, you will learn abo out the tasks t that you will p perform in the e lab for this module. m

11-20

Integr rating with Unmanag ged Code

Lab: U Upgradi ing the e Grade es Report

Sc cenario
Yo ou have been asked to upgrade the grad des report functionality to g generate repo orts in Word fo ormat. In Mo odule 6, you w wrote code th hat generates reports as an XML file; now w you will upd date the code to ge enerate the report as a Wor rd document.

Ob bjectives
Aft ter completing this lab, you u will be able to: Use dynamic types. bject lifetime a and resources s. Manage ob

timated Time: : 75 minutes Est Virtual Mac chine: 20483A A-SEA-DEV11-11, MSL-TMG G1 User Name: Student P Password: Pa$$w0rd

Programming in Visual C# 11-21

Exercise 1: Generating the Grades Report by Using Word


Scenario
In this exercise, you will update the reporting functionality to generate reports in Word format. First you will review the existing code in the WordWrapper class that appends headings, text, breaks, and carriage returns to a document. You will write code to create an instance of Word, create a blank Word document, save a Word document, and navigate to the end of a document. You will then write code in the GenerateStudentReport method to create a blank document, add a heading and grade data to the document, and save the document using the methods that you reviewed and wrote in the WordWrapper class. You will run this method as a separate task. Finally, you will build and test the application and verify that the reports are now generated in Word format. The main tasks for this exercise are as follows: 1. Examine the WordWrapper class that provides a functional wrapper around the dynamic (COM) API for Word 2. Add code to the GeneratedStudentReport method to generate a Word document 3. Build and test the application

X Task 1: Examine the WordWrapper class that provides a functional wrapper around the dynamic (COM) API for Word
1. 2. 3. 4. Start the MSL-TMG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-11 virtual machine and log on as Student with the password Pa$$w0rd. Start Visual Studio and open the Grades.sln solution from the E:\Labfiles\Starter\Exercise 1 folder. Set the following projects to start without debugging at startup: a. b. 5. 6. 7. 8. 9. Grades.Web Grades.WPF

In the Grades.Utilities project, review the contents of the WordWrapper.cs file. In the WordWrapper class, add code to create a dynamic variable named _word for activating Word. In the class constructor, add code to instantiate the _word variable as a new Word Application object, but ensure that the application is not visible to the user. In the CreateBlankDocument method, add code to create a new Word document and then activate the new document. In the SaveAs method, add code to do the following: a. b. Save the active Word document using the file name that is passed to the method. Close the document.

10. In the GetEndOfDocument method, delete the existing return statement and add code to return the end point of the document as a Range object.

X Task 2: Add code to the GeneratedStudentReport method to generate a Word document


1. In the Grades.WPF project, in the Views folder, open StudentProfile.xaml.cs.

11-22

Integrating with Unmanaged Code

2. 3.

In the Utility and Helper methods region, locate the GenerateStudentReport method. In this method, add code to do the following: a. b. c. d. Call the CreateBlankDocument method of the Wrapper object. Add the heading Grade Report: and the students name to the blank document followed by two blank lines. Add the details of each grade for that student to the document, including: Subject name Assessment Date Comment Save the document.

4.

In the Events region, in the SaveReport_Click method, add code to generate the report by using a separate task, passing the student and the file name as parameters to the GenerateStudentReport method.

X Task 3: Build and test the application


1. 2. 3. 4. 5. Build the solution and resolve any compilation errors. Run the application. Log on as vallee with a password of password99. Generate a grade report for Kevin Liu, save the report in the E:\Labfiles\Starter\Exercise 1 folder, close the application, and in Visual Studio, close the solution. Open Kevin Lius grade report in Word, review the report, and then close Word.

Results: After completing this exercise, the application will generate grade reports in Word format.

Programming in Visual C# 11-23

Exercise 2: Controlling the Lifetime of Word Objects by Implementing the Dispose Pattern
Scenario
In this exercise, you will write code to ensure that Word is correctly terminated after generating a grades report. You will begin by observing that currently the Word object remains in memory after the application has generated a report. You will verify this by observing the running tasks in Task Manager. You will update the code in the WordWrapper class to implement the dispose pattern to ensure correct termination of the Word instance. You will then update the code in the GenerateStudentReport method to ensure that the WordWrapper object is disposed of when the method finishes. Finally, you will build and test the application and verify that Word now closes after the report is generated. The main tasks for this exercise are as follows: 1. Run the application to generate a grades report and view the Word task in Task Manager 2. Update the WordWrapper class to terminate Word correctly 3. Wrap the object that generates the Word doc in a using statement 4. Use Task Manager to observe that Word terminates correctly after generating a report

X Task 1: Run the application to generate a grades report and view the Word task in Task Manager
1. 2. In Visual Studio, open the Grades.sln solution from the E:\Labfiles\Starter\Exercise 2 folder. Set the following projects to start without debugging at startup: a. b. 3. 4. 5. 6. 7. 8. 9. Grades.Web Grades.WPF

Build the solution and resolve any compilation errors. Run the application. Log on as vallee with a password of password99. Generate a grade report for Kevin Liu, save the report in the E:\Labfiles\Starter\Exercise 2 folder, and then close the application. Use File Explorer to verify that the report has been generated. Open Task Manager, and then verify that Word is still running. In Task Manager, end the Word task, and then close Task Manager.

X Task 2: Update the WordWrapper class to terminate Word correctly


1. 2. 3. 4. In the Grades.Utilities project, open WordWrapper.cs. Modify the definition of the WordWrapper class so that it implements the IDisposable interface. In the WordWrapper class, create a protected virtual void method named Dispose that takes a Boolean parameter. Add code to this method to do the following:

11-24

Integrating with Unmanaged Code

a. b. c. d. e. f. 5. 6.

Check that the class is not yet disposed of. Check whether the Boolean parameter that is passed to the method is true. Check whether the _word variable is not null. If all of these checks are valid, use the Quit method of the Word object to release the managed resources. If the _word variable is still not null, use the ReleaseComObject method to release the unmanaged resources. Set the isDisposed property to true.

In the WordWrapper class, create a public method named Dispose. Add code to the method to do the following: a. b. Call the Dispose method, passing true as a parameter. Call the SuppressFinalize method of the GC.

7.

In the WordWrapper class, create a private Boolean variable named isDisposed and assign a default value of false.

X Task 3: Wrap the object that generates the Word doc in a using statement
1. 2. 3. In the Grades.WPF project, in the Views folder, open StudentProfile.xaml.cs. In the Utility and Helper methods region, locate the GenerateStudentReport method. Replace the current declaration for the wrapper variable with a using statement that declares the wrapper object as a var and encloses all of the code in the method.

X Task 4: Use Task Manager to observe that Word terminates correctly after generating a report
1. 2. 3. 4. 5. 6. Build the solution and resolve any compilation errors. Open Task Manager. Run the application. Log on as vallee with a password of password99. View George Lis grade report. Save the report in the E:\Labfiles\Starter\Exercise 2 folder. As you click Save, in the Task Manager window, verify that Microsoft Word (32 bit) appears and then disappears from the Background processes group. Close Task Manager, close the application, and then in Visual Studio, close the solution.

7.

Results: After completing this exercise, the application will terminate Word correctly after it has generated a grades report.

Programming in Visual C#

11-25 5

Module Rev view an nd Take eaways

M Module Rev view


In this module I e, you have le earned how to o interoperate e with COM as ssemblies and d how to ensure that your o objects dispos se of any reso ources they co onsume. T Test Your Kno owledge Question Which of the following statements s be est describes the dynamic keyword? Select the correct answer r. It de efines an obje ect of type obj ject and instru ucts the comp piler to perfor rm type chec cking. It de efines a nullab ble object and d instructs the e compiler to defer d type che ecking. It de efines an obje ect of type obj ject and instru ucts the comp piler to defer type t chec cking. It de efines a nullab ble object and d instructs the e compiler to perform p type checking. V Verify the correctness of th he statement b by placing a m mark in the co olumn to the r right. Statement You can use e a using statement to imp plicitly invoke the Dispose method on an object th hat implements the IDisposable pattern n. Answer

12-1

Module 12
Creating Reusable Types and Assemblies
Contents:
Module Overview Lesson 1: Examining Object Metadata Lesson 2: Creating and Using Custom Attributes Lesson 3: Generating Managed Code Lesson 4: Versioning, Signing, and Deploying Assemblies Lab: Specifying the Data to Include in the Grades Report Module Review and Takeaways 12-2 12-3 12-16 12-26 12-36 12-49 12-56

12-2 Creating g Reusable Types an nd Assemblies

Modu ule Ove erview

Sys stems often consist of man ny component ts, some of wh hich may be shared s with ot ther applicatio ons in your org ganizations in nfrastructure. When you de esign applicat tions, it is important to thin nk about reuse e and consider how th he functionalit ty you are imp plementing might m be usefu ul in other app plications. you will learn how to consu ume existing a assemblies by y using reflect tion and how to add In this module, y additional meta adata to types s and type me embers by usin ng attributes. You will also learn how to generate code at run time e by using the e Code Docum ment Object M Model (CodeD DOM) and how w to ensure th hat your ass semblies are s signed and ve ersioned, and available to o other applicati ions, by using the global as ssembly cac che (GAC).

Ob bjectives
Aft ter completing this module e, you will be able to: on to inspect and execute assemblies. Use reflectio Create and consume custom attribute es. Generate m managed code e at run time b by using Code eDOM. Version, sign, and deploy y your assemb blies to the GA AC.

Programming in i Visual C#

12-3 3

Lesson 1

Exam mining O Object Metadata

Sometimes ap S pplications ne eed to load an n existing com mpiled assemb bly, view its co ontents, and ex xecute For example, a unit testing f functionality. g utility may re equire the ability to obtain a reference t to a type and e execute some e of the public c methods tha at it exposes. R Reflection pro ovides a way f for you to exa amine the t types in a com mpiled assemb bly. In this lesson, you will learn I n how to use reflection r to e examine the m metadata of objects and execute f functionality t that the objec ct exposes.

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Describe the purpose o of reflection. Load an a assembly. Examine t the metadata of an existing g type. Invoke th he members th hat an assemb bly exposes.

12-4 Creating g Reusable Types an nd Assemblies

W What Is Ref flection?

Re eflection is a p powerful featu ure that enables you to insp pect and perfo orm dynamic manipulation n of ass semblies, type es, and type m members at ru un time. Re eflection is use ed throughout the Microso oft .NET Fram mework. Refle ection is used by some of th he classes tha at the base cla ass library pro ovides and som me of the utilities that ship p with Microso oft Visual Stud dio. For exa ample, the serialization classes in the Sy ystem.Runtim me.Serializatio on namespace use reflectio on to de etermine which type memb bers should be e serialized wh hen serializing g types.

Re eflection Us sage Scenarios


The following ta able describes s some of the possible uses s for reflection n in your applications. U Use Examining me E etadata and d dependencies s of an assemb bly. Finding memb F bers in a type e t that have bee en decorated with w a particular at ttribute. Determining whether D w a typ pe i implements a specific i interface. Defining and executing a D m method at run n time. Scenario You might m choose to do this if you y are consuming an unkn nown assem mbly in your application and d you want to o determine w whether your a application sa atisfies the unknown assem mblys depende encies. You might m choose to do this if you y are implem menting a generic storag ge repository, , which will inspect each typ pe and determ mine which memb bers it needs t to persist. You might m choose to do this if you y are creatin ng a pluggable applic cation that en nables you to include new a assemblies at run time, but yo ou only want your applicat tion to load ty ypes that implement a specif fic interface. You might m choose to do this if you y are implem menting a virt tualized platfo orm that can r read types and d methods that are implem mented in a langu uage such as JavaScript, and d then creatin ng managed imple ementations th hat you can e execute in you ur .NET Framew work applic cation.

Exe ecuting code by using refle ection is marg ginally slower than executin ng static Micro osoft Visual C# code, so you should o only use reflec ction to create e and execute e code when y you really have e to and not j just be ecause reflection makes it p possible.

Programming in Visual C# 12-5

Reflection in the .NET Framework


The .NET Framework provides the System.Reflection namespace, which contains classes that enable you to take advantage of reflection in your applications. The following list describes some of these classes: Assembly. This class enables you to load and inspect the metadata and types in a physical assembly. TypeInfo. This class enables you to inspect the characteristics of a type. ParameterInfo. This class enables you to inspect the characteristics of any parameters that a member accepts. ConstructorInfo. This class enables you to inspect the constructor of the type. FieldInfo. This class enables you to inspect the characteristics of fields that are defined within a type. MemberInfo. This class enables you to inspect members that a type exposes. PropertyInfo. This class enables you to inspect the characteristics of properties that are defined within a type. MethodInfo. This class enables you to inspect the characteristics of the methods that are defined within a type.

The System namespace includes the Type class, which also exposes a selection of members that you will find useful when you use reflection. For example, the GetFields instance method enables you to get a list of FieldInfo objects, representing the fields that are defined within a type. Additional Reading: For more information about the Type class, see the Type Class page at http://go.microsoft.com/fwlink/?LinkID=267864. Additional Reading: For more information about reflection in the .NET Framework class, see the Reflection in the .NET Framework page at http://go.microsoft.com/fwlink/?LinkID=267865.

12-6 Creating g Reusable Types an nd Assemblies

Lo oading As ssemblies by Using Reflection n

The System.Ref flection name espace provid des the Assem mbly class, wh hich enables y you to encapsu ulate an ass sembly in you ur code so tha at you can insp pect any meta adata that is a associated wit th that assemb bly. The Assembly c class provides s a number of f static and ins stance membe ers that you c can use to load d and exa amine the con ntents of asse emblies. There e are two ways s that you can n load an asse embly into you ur ap pplication by using u reflectio on: Reflection-o only context, in which you can view the metadata tha at is associated d with the ass sembly and not execute e code. xecute the loa Execution c context, in which you can ex aded assembl ly.

embly in reflec ction-only con ntext can imp prove perform mance; howeve er, if you do tr ry to Loading an asse exe ecute it, the C Common Lang guage Runtim me (CLR) will th hrow an Inval lidOperation nException ex xception. To o load an assem mbly, the Ass sembly class p provides a number of static c methods, wh hich include the fol llowing: sembly in exe ecution contex xt by using an n absolute LoadFrom. This method enables you to load an ass file path to the assembly y. The followin ng code example shows how w to load the FourthCoff fee.Service.Ex xceptionHan ndling assemb bly.
var assem mblyPath = "C:\\F FourthCoffee e\\Libs\\FourthCoffee.Se ervice.Excep ptionHandling g.dll"; var assem mbly = Assem mbly.LoadFrom m(assemblyPa ath);

ReflectionO OnlyLoad. Th his method en nables you to load an assem mbly in reflect tion-only cont text from a binary large e object (BLOB) that repres sents the assem mbly. The following code example e show ws how to load the Fo ourthCoffee.S Service.Excep ptionHandlin ng assembly fr rom a byte array.
var assem mblyPath = "C:\\F FourthCoffee e\\Libs\\FourthCoffee.Se ervice.Excep ptionHandling g.dll"; var rawBy ytes = File.ReadAllBytes(assemblyPa ath); var assem mbly = Assem mbly.ReflectionOnlyLoad( (rawBytes);

ReflectionO OnlyLoadFro om. This method enables yo ou to load an assembly in r reflection-only y context by using an n absolute file path to the assembly. a The following cod de example sh hows how to load the FourthCoff fee.Service.Ex xceptionHan ndling assemb bly.

Programming in Visual C# 12-7

var assemblyPath = "C:\\FourthCoffee\\Libs\\FourthCoffee.Service.ExceptionHandling.dll"; var assembly = Assembly.ReflectionOnlyLoadFrom(assemblyPath);

After you have loaded an assembly and have created an instance of the Assembly class, you can use any of the instance members to examine the contents of the assembly. The following list describes some of the instance members that the Assembly class provides: FullName. This property enables you to get the full name of the assembly, which includes the assembly version and public key token. The following code example shows the full name of the File class in the System.IO namespace.
mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

GetReferencedAssemblies. This method enables you to get a list of all of the names of any assemblies that the loaded assembly references. GlobalAssemblyCache. This property enables you to determine whether the assembly was loaded from the GAC. Location. This property enables you to get the absolute path to the assembly. ReflectionOnly. This property enables you to determine whether the assembly was loaded in a reflection-only context or in an execution context. If you load an assembly in reflection-only context, you can only examine the code. GetType. This method enables you to get an instance of the Type class that encapsulates a specific type in an assembly, based on the name of the type. GetTypes. This method enables you to get all of the types in an assembly in an array of type Type.

Additional Reading: For more information about the Assembly class, see the Assembly Class page at http://go.microsoft.com/fwlink/?LinkID=267866.

12-8 Creating g Reusable Types an nd Assemblies

Ex xamining Types by Using Ref flection

Re eflection enables you to exa amine the def finition of any y type in an as ssembly. Depe ending on whether you are e looking for a type with a specific name e or you want to iterate thr rough each ty ype in the asse embly in seq quence, you c can use the Ge etType and G GetTypes met thods that the e Assembly class provides. The following co ode example shows how to o load a type by using the GetType G met thod, passing the fully qu ualified name of the type as s a parameter r to the metho od call. Lo oad a Type by y Using the G GetType Meth hod
v var assembly = FourthCof ffeeServices s.GetAssembly y(); ... v var type = as ssembly.GetT Type("Fourth hCoffee.Servi ice.Exceptio onHandling.H HandleError") );

If y you use the G GetType meth hod and specif fy a name of a type that do oes not exist in the assembly, the Ge etType metho od returns null. The following co ode example shows how to o iterate throu ugh each of th he types in an n assembly by using the Ge etTypes meth hod. The GetT Types method d returns an array of Type o objects. Ite erate All Type es in an Asse embly by Usin ng the GetTy ypes Method
v var assembly = FourthCof ffeeServices s.GetAssembly y(); ... f foreach (var type in ass sembly.GetTy ypes()) { // Code to o process ea ach type. var typeNa ame = type.F FullName; }

Aft ter you have created c an ins stance of the T Type class, yo ou can then use any of its m members to in nspect the typ pes definition n. The followin ng list describ bes some of th he key membe ers that the Ty ype class prov vides: GetConstru uctors. This m method enable es you to get all of the con nstructors that t exist in a typ pe. The GetConstru uctors metho od returns an a array that con ntains Constru uctorInfo obj jects. The follo owing code example show how to ge et each of the e constructors that exists in a type and th hen get each of o the parameters.
var type = FourthCof ffeeServices.GetHandleEr rrorType();

Programming in Visual C# 12-9

var constructors = type.GetConstructors(); foreach (var constructor in constructors) { var parameters = constructor.GetParameters(); }

GetFields. This method enables you to get all of the fields that exist in the current type. The GetFields method returns an array that contains FieldInfo objects. The following code example shows how to iterate through each field in a type and then determine whether the field is static or instance by using the IsStatic property that the FieldInfo class provides.
var type = FourthCoffeeServices.GetHandleErrorType(); var fields = type.GetFields(); foreach (var field in fields) { var isStatic = field.IsStatic; }

GetProperties. This method enables you to get all of the properties that exist in the current type. The GetProperties method returns an array that contains PropertyInfo objects. The following code example shows how to iterate through each property and then get the propertys name.
var type = FourthCoffeeServices.GetHandleErrorType(); var properties = type.GetProperties(); foreach (var property in properties) { var propertyName = property.Name; }

GetMethods. This method enables you to get all of the methods that exist in the current type. The GetMethods method returns an array that contains MethodInfo objects. The following code example shows how to iterate through each method and then get the methods name.
var type = FourthCoffeeServices.GetHandleErrorType(); var methods = type.GetMethods(); foreach (var method in methods) { var methodName = method.Name; }

GetMembers. This method enables you to get any members that exist in the current type, including properties and methods. The GetMembers method returns an array that contains MemberInfo objects. The following code example shows how to iterate through each member and then determine whether the member is a property or method.
var type = FourthCoffeeServices.GetHandleErrorType(); var members = type.GetMembers(); foreach (var member in members) { if (member.MemberType == MemberTypes.Method) { // Process the method. } if (member.MemberType == MemberTypes.Property) { // Process the property. } }

12-10

Creating Reusable Types and Assemblies

You can use these members to get a collection of xxxxInfo objects that represents the different members that a type exposes. If you loaded the type in execution context, you can then use the xxxxInfo objects to execute each member. Additional Reading: For more information about the Type class, see the Type Class page at http://go.microsoft.com/fwlink/?LinkID=267864.

Programming in Visual C#

12-11 1

I Invoking Members by Using Reflectio on

The reflection T n application p programming g interface (AP PI) in the .NET T Framework e enables you to o invoke o objects and use the functio onality that they encapsulat te. Invoking an object by using reflection n follows the s same pattern that you use to invoke an object in Visu ual C#, which t typically invol lves the follow wing steps: 1 1. 2 2. 3 3. Create an n instance of t the type. Invoke methods on the e instance. Get or set t property val lues on the instance.

When you inv W voke static me embers by using reflection, there is no ne eed to explicitly create an instance i of t type. the

I Instantiatin ng a Type
To create an instance of a t T type by using reflection, yo ou need to get a reference to a construct tor that the t type exposes and then use the Invoke m method. To instantiate a typ pe by using th he Constructo orInfo class, p perform the fo ollowing step ps: 1 1. Create an n instance of t the Construct torInfo class t that represents the constru uctor you will use to initialize an a instance of f the type. The e following co ode example s shows how to o initialize an o object by using the e default const tructor.
var typ pe = FourthCoffeeService es.GetHandle eErrorType(); ... var con nstructor = type.GetCons structor(new w Type[0]);

Note: T To get the default construct tor, you pass an a empty arra ay of type Typ pe to the GetConstruct G tor method call. If you wan nt to invoke a constructor t that accepts p parameters, yo ou m must pass a T Type array tha at contains the e types that th he constructo or accepts. 2 2. Call the In nvoke metho od on the Con nstructorInfo o object to init tialize an insta ance of the ty ype, passing an object t array that represents any parameters th hat the constr ructor call exp pects. The follo owing code example shows how to o invoke the d default constru uctor.

12-12

Creating Reusable Types and Assemblies

var initializedObject = constructor.Invoke(new object[0]);

You now have an instance of the type that you can use to invoke any instance methods that are defined in the type.

Invoking Methods
To invoke an instance method, perform the following steps: 1. Create an instance of the MethodInfo class that represents the method you want to invoke. The following code example shows how to get a method named LogError.
var type = FourthCoffeeServices.GetHandleErrorType(); ... var methodToExecute = type.GetMethod("LogError");

2.

Call the Invoke method on the MethodInfo object, passing the initialized object and an object array that represents any parameters that the method call expects. You can then cast the return value of the Invoke method to the type of value you were expecting from the method call. The following code example shows how to execute the LogError instance method that accepts a string parameter and returns a string value.
var initializedObject = FourthCoffeeServices.InstantiateHandleErrorType(); ... var response = methodToExecute.Invoke(initializedObject, new object[] { "Error message" }) as string;

When you invoke static methods, there is no need to create an instance of the type. Instead, you just create an instance of the MethodInfo class that represents the method you want to invoke and then call the Invoke method. To invoke a static method, perform the following steps: 1. Create an instance of the MethodInfo class that represents the method you want to invoke. The following code example shows how to get a method named FlushLog.
var type = FourthCoffeeServices.GetHandleErrorType(); ... var methodToExecute = type.GetMethod("FlushLog");

2.

Call the Invoke method on the MethodInfo object, passing a null value to satisfy the initialized object and an object array that represents any parameters that the method call expects. The following code example shows how to execute the FlushLog static method that accepts no parameters and returns a Boolean value.
var isFlushed = methodToExecute.Invoke(null, new object[0]) as bool;

Getting and Setting Properties Values


To get or set the value of an instance property, you must first perform the following steps: 1. Create an instance of the PropertyInfo class that represents the property you want to get or set. The following code example shows how to get a property named LastErrorMessage.
var type = FourthCoffeeServices.GetHandleErrorType(); ... var property = type.GetProperty("LastErrorMessage");

2.

If you want to get the value of a property, you must invoke the GetValue method on the PropertyInfo object. The GetValue method accepts an instance of the type as a parameter. The following code example shows how to get the value of the LastErrorMessage property.

Programming in Visual C# 12-13

var initializedObject = FourthCoffeeServices.InstantiateHandleErrorType(); ... var lastErrorMessage = property.GetValue(initializedObject) as string;

3.

If you want to set the value of a property, you must invoke SetValue method on the PropertyInfo object. The SetValue method accepts an instance of the type and the value you want to set the property to as parameters. The following code example shows how to set the LastErrorMessage property to the text Database connection error.
var initializedObject = FourthCoffeeServices.InstantiateHandleErrorType(); ... property.SetValue(initializedObject, "Database connection error");

When you get or set a static property, there is no need to create an instance of the type. Instead, you just create an instance of the PropertyInfo class and then call either the GetValue or SetValue method. To get or set the value of a static property, perform the following steps: 1. Create an instance of the PropertyInfo class that represents the property you want to get or set. The following code example shows how to get a property named LastErrorMessage.
var type = FourthCoffeeServices.GetHandleErrorType(); ... var property = type.GetProperty("LastErrorMessage");

2.

If you want to get the value of a property, you must invoke the GetValue method on the PropertyInfo object, passing a null value to satisfy the initialized object parameter. The following code example shows how to get the value of the LastErrorMessage static property.
var lastErrorMessage = property.GetValue(null) as string;

3.

If you want to set the value of a property, you must invoke the SetValue method on the PropertyInfo object, passing a null value to satisfy the initialized object parameter, and the value you want to set the property too. The following code example shows how to set the LastErrorMessage static property to the text Database connection error.
property.SetValue(null, "Database connection error");

12-14

Creating Reusable Types and Assemblies

Demonstration: Insp pecting As ssemblies

In this demonstration, you wi ill create a too ol that you can use to inspe ect the conten nts of an assembly. System.Reflec ction classes t to load an ass sembly, get al ll of the types in that The application will use the S ass sembly, and then for each t type, get all o of the properties and metho ods.

De emonstration Steps
1. 2. 3. Start the MSL-TMG1 virtual machine if it is not already running. 0483A-SEA-DE EV11-12 virtual machine. Start the 20 Log on to W Windows 8 as a Student with the passwo ord Pa$$w0r rd. Note: If necessary, click k Switch User r to display th he list of users s. 4. 5. 6. 7. 8. 9. he Windows 8 Start window w. Switch to th Click Visual Studio 2012. udio, on the F File menu, point to Open, and a then click k Project/Solution. In Visual Stu In the Open n Project dial log box, brow wse to E:\Demo ocode\Starter r\FourthCoffe ee.TypeInspect tor folder, click Fourth hCoffee.Type eInspector.sln, and then click Open. In Solution Explorer, righ ht-click Fourth hCoffee.Type eInspector, and then click Set as StartU Up Project. On the Buil ld menu, click k Build Soluti ion.

0. In Visual Stu udio, on the V View menu, click Task List. 10 k List window, , in the Categ gories list, click Comments s. 11. In the Task ck the TODO: 01: Bring the System.Reflec ction namespace into scope. task. 12. Double-clic e editor, click i in the blank line below the comment, an nd then type t the following code: 13. In the code
using System.Reflecti ion;

4. In the Task List window, double-click the t TODO: 02 2: Create an Assembly objec ct. task. 14

Programming in Visual C# 12-15

15. In the code editor, click in the blank line below the comment, and then type the following code:
return Assembly.ReflectionOnlyLoadFrom(path);

16. In the Task List window, double-click the TODO: 03: Get all the types from the current assembly. task. 17. In the code editor, click in the blank line below the comment, and then type the following code:
return assembly.GetTypes();

18. In the Task List window, double-click the TODO: 04: Get a specific type from the current assembly. task. 19. In the code editor, click in the blank line below the comment, and then type the following code:
return assembly.GetType(typeName);

20. In the code editor, locate the RenderMethods method, and then review the use of the IsPublic, IsStatic, ReturnType, and Name properties of the MethodInfo class. 21. Locate the RenderProperties method, and then review the use of the DeclaringType and Name properties of the PropertyInfo class. 22. On the Build menu, click Build Solution. 23. On the Debug menu, click Start Without Debugging. 24. In the Fourth Coffee Type Inspector application, click Load Assembly. 25. In the Open dialog box, browse to E:\Democode\Starter\FourthCoffee.TypeInspector\FourthCoffee.Core\bin\Debug folder, click FourthCoffee.Core.dll, and then click Open. The Types list now contains a list of all of the types that the assembly exposes. 26. In the Types list, click FourthCoffee.Core.Encryptor, and then click Inspect Type. The Members list now shows all of the methods that the type exposes. 27. Close Fourth Coffee Type Inspector. 28. In Visual Studio, close the solution.

12-16

Creating Reusable Types and Assemblies

Lesson 2

Creati ing and d Using Custom m Attributes

about a type or type memb The .NET Frame ework uses att tributes to pro ovide addition nal metadata a ber. The .NET Framework k provides ma any attributes out of the bo ox that you ca an use in your r applications. In this lesson, yo ou will learn h how to create your own cus stom attribute es and read th he metadata t that is encapsulated in n custom attrib butes at run time by using reflection.

Le esson Obje ectives


Aft ter completing this lesson, you will be ab ble to: Describe the purpose of attributes. attributes. Create and use custom a Process cus stom attribute es by using ref flection

Programming in Visual C#

12-17 7

W What Are Attribute es?

Attributes pro A ovide a mecha anism that use es the declara ative programming model t to include add ditional m metadata abo out elements, such as types s, properties, a and methods, in your application. Your a application c use the ad can dditional information that attributes pro ovide to control application n behavior and d how data is p processed at run r time. You can also use the information that attrib butes encapsulate in case to ools and o other utilities that aid the d development process, such as unit test fr rameworks. The .NET Fram T mework make es extensive us se of attribute es throughout t the base clas ss library. The following list t d describes som me of the attributes that the e .NET Framew work provides s: The Obso olete attribute e in the Syste em namespace e, which you c can use to ind dicate that a t type or a type e member has been supe erseded and is i only there t to ensure back kward compatibility. The Seria alizable attrib bute in the Sys stem namesp pace, which yo ou can use to indicate that an IFormatt ter implement tation can ser rialize and des serialize a type. The NonS Serialized att tribute in the System name espace, which h you can use to indicate th hat an IFormatt ter implement tation should not serialize or deserialize a member in a type. The Data aContract attr ribute in the S System.Runti ime.Serialization namespa ace, which you can use to indicate t that a DataCo ontractSeriali izer object can serialize and d deserialize a type. The Quer ryInterceptor r attribute in t the System.D Data.Services namespace, w which you can n use to control ac ccess to an en ntity in Windo ow Communic cation Founda ation (WCF) D Data Services. The Conf figurationPro operty attribu ute in the Syst tem.Configuration names space, which you y can use to map a property mem mber to a sec ction in an app plication conf figuration file.

All attributes in the .NET Fr A ramework der rive either dire ectly from the e abstract Attribute base c class in the S System name espace or from m another attr ribute.

A Applying A Attributes
T use an attr To ribute in your code, perform m the followin ng steps: 1 1. 2 2. 3 3. Bring the namespace t that contains t the attribute you y want to use u into scope e. Apply the e attribute to the code elem ment, satisfyin ng any parame eters that the constructor e expects. Optionally set any of the named parameters that t the attribute exposes.

12-18

Creating Reusable Types and Assemblies

The following code example shows how to apply the DataContract attribute to the SalesPerson class definition and set the Name and IsReference named parameters. Applying the DataContract Attribute
[DataContract(Name = "SalesPersonContract", IsReference=false)] public class SalesPerson { ... }

You can apply multiple attributes to a single element to create a hierarchy of metadata that describes the element. The following code example shows how to apply the Obsolete and DataMember attributes to the Name property in the SalesPerson class, to indicate that the property should be serialized but will be removed from the type definition in the next release. Applying the Obsolete and DataContract Attributes
[DataContract(Name = "SalesPersonContract", IsReference=false)] public class SalesPerson { [Obsolete("This property will be removed in the next release. Use the FirstName and LastName properties instead.")] [DataMember] public string Name { get; set; } }

Additional Reading: For more information about the Attribute class, see the Attribute Class page at http://go.microsoft.com/fwlink/?LinkID=267867.

Programming in Visual C#

12-19 9

C Creating a and Using g Custom A Attributes s

The .NET Fram T mework provid des an extensive set of attr ributes that yo ou can use in y your applications. H However, ther re will be a tim me when you need an attribute that the .NET Framew work does not provide. For e example, may ybe you want to include inf formation abo out the develo oper who auth hored the sou urce code for a application an n, or maybe yo ou need some e additional d data for a cust tom testing framework you u are using to t test the applic cation. T create an a To attribute, perf form the following steps: 1 1. 2 2. Create a t type that deri ives from the Attribute base class or ano other existing g attribute typ pe. Apply the e AttributeUs sage attribute e to your custom attribute class to describe which elements you can apply y this attribute e to.

Note: If f you apply an n attribute to an element th hat conflicts w with the value of the AttributeUsa A age attribute, the compiler will throw an error at build d time. 3 3. 4 4. Define a c constructor to o initialize the e custom attrib bute. Define an ny properties t that you want t to enable us sers of the attribute to optionally provide e information. Any properties that you u define that have a get ac ccessor will be e exposed thro ough the attribute as a named p parameter.

The code exam T mple shows h how to create an attribute t that encapsula ates metadata a about the de eveloper who o c creates the ele ement. C Creating a Cu ustom Attrib bute
[Attribute eUsage(AttributeTargets.All)] public clas ss Developer rInfo : Attribute { private string _ema ailAddress; private int _revision; public D DeveloperInf fo(string emailAddress, int revisio on) { this. ._emailAddre ess = emailAddress; this. ._revision = revision; }

12-20

Creating Reusable Types and Assemblies

public { get } public { get } }

string EmailAddress { return this._emailAddress; } int Revision { return this._revision; }

Using a custom attribute is no different from using an attribute that the .NET Framework provides. You simply apply the attribute to an element and ensure that you pass the required information to the constructor. The following code example shows how to apply the DeveloperInfo attribute to a type definition. Applying a Custom Attribute
[DeveloperInfo("holly@fourthcoffee.com", 3)] public class SalePerson { ... [DeveloperInfo("linda@fourthcoffee.com", 1)] public IEnumerable<Sale> GetAllSales() { ... } }

Additional Reading: For more information about how to create custom attributes, see the Creating Custom Attributes (C# and Visual Basic) page at http://go.microsoft.com/fwlink/?LinkID=267868.

Programming in Visual C#

12-21 1

P Processing g Attribut tes by Using Reflect tion

If you use the I e existing attributes that the e .NET Framew work provides s, they normally have a pur rpose other t than just to ex xist in your co ode. For exam mple, the IForm matter serializ zers use the S Serializable at ttribute d during the ser rializing and d deserializing p processes. Similarly, you can use attrib S butes to encap psulate metad data about an n element in y your code. For r example, if y create an attribute that provides inf you formation abo out the develo oper who auth hored the elem ment, you m want a way may w to extract this informati ion so that yo ou can produc ce a documen nt listing all of f the d developers wh ho were involved in develo oping the application. Similar to acce S essing other t type and mem mber informat tion, you can a also use reflec ction to proce ess attributes. T System.R The Reflection namespace prov vides a collect tion of extens sion methods that you can use to access a attributes and d the metadat ta they encaps sulate. The following list de escribes some e of these met thods: GetCusto omAttribute. This method enables you to get a speci ific attribute t that was used on an element. The following g code examp ple shows how w to get a Dev veloperInfo attribute a that has been applied to o a type.
var typ pe = FourthCoffeeService es.GetHandle eErrorType(); var get tInheritedAttributes = f false; var att tribute = type e.GetCustomA Attribute(typ peof(Develop perInfo), getInheritedAt ttributes);

Note: T The getInherite edAttributes p parameter inst tructs the Get tCustomAttri ibute method d call t return eithe to er only attribu utes that have e been explicit tly applied to the current ty ype, or attribu utes t that have bee en either explicitly applied o or inherited fr rom any paren nt type. GetCusto omAttribute. This generic method also enables you t to get a specif fic attribute th hat was used on an ele ement. This is a generic met thod, so you c can specify th he type of attribute you wan nt the GetCusto omAttribute method to re eturn. This me eans that you d do not have t to write conditional logic to filter an array of obj jects to determ mine the type e of an attribu ute and perfor rm any casting g. The following g code example shows how w to get a Dev veloperInfo attribute that h has been applied to a type. .
var typ pe = FourthCoffeeService es.GetHandle eErrorType(); var get tInheritedAttributes = f false;

12-22

Creating Reusable Types and Assemblies

var attribute = type.GetCustomAttribute<DeveloperInfo>(getInheritedAttributes);

GetCustomAttributes. This method enables you to get a list of specific attributes that were used on an element. Typically, you would use this method if more than one attribute of the same type has been applied to an element, in which case this method call would return all instances. The following code example shows how to get all of the DeveloperInfo attributes that were applied to a type.
var type = FourthCoffeeServices.GetHandleErrorType(); var getInheritedAttributes = false; var attributes = type.GetCustomAttributes(typeof(DeveloperInfo), getInheritedAttributes);

GetCustomAttributes. This generic method enables you to get a list of specific attributes that were used on an element. Similar to the GetCustomAttribute generic method, because this is a generic method, the method call will only return attributes that match the generic type. The following code example shows how to get all of the DeveloperInfo attributes that were applied to a type.
var type = FourthCoffeeServices.GetHandleErrorType(); var getInheritedAttributes = false; var attributes = type.GetCustomAttributes<DeveloperInfo>(getInheritedAttributes);

The following code example shows how to iterate through each of the custom attributes that have been applied to a type definition and then access the data that any DeveloperInfo attributes encapsulate. Iterating Custom Attributes That Have Been Applied to a Type
var type = FourthCoffee.GetSalesPersonType(); var attributes = type.GetCustomAttributes(typeof(DeveloperInfo), false); foreach (var attribute in attributes) { var developerEmailAddress = attribute.EmailAddress; var codeRevision = attribute.Revision; }

Note: The false value that is passed to the GetCustomAttributes method instructs the method to only get custom attributes that have been explicitly applied to the current type, not attributes that have been inherited. To access custom attributes that have been applied to a member, you must create an xxxxInfo object that represents the member and then invoke the GetCustomAttributes method. The following code example shows how to iterate through each of the custom attributes that have been applied to a method called GetAllSales and then access the data that any DeveloperInfo attributes have encapsulated. Iterate Custom Attributes That Have Been Applied to a Method
var type = FourthCoffee.GetSalesPersonType(); var methodToInspect = type.GetMethod("GetAllSales"); var attributes = methodToInspect.type.GetCustomAttributes(typeof(DeveloperInfo), false); foreach (var attribute in attributes) { var developerEmailAddress = attribute.EmailAddress; var codeRevision = attribute.Revision; }

Programming in Visual C# 12-23

Additional Reading: For more information about how to process custom attributes, see the Accessing Custom Attributes page at http://go.microsoft.com/fwlink/?LinkID=267869.

12-24

Creating Reusable Types and Assemblies

Demonstration: Con nsuming C Custom At ttributes by b Using R Reflection n

In this demonstration, you wi ill use reflectio on to read the e DeveloperInfo attributes s that have be een used to pro ovide addition nal metadata on types and type membe ers. The application uses the GetC CustomAttribute generic method that the Type and d MemberInf fo classes pro ovide to extra act any additio onal information that a cus stom Develop perInfo attribute encapsula ates.

De emonstration Steps
1. 2. 3. Start the MSL-TMG1 virtual machine if it is not already running. 0483A-SEA-DE EV11-12 virtual machine. Start the 20 Log on to W Windows 8 as Student with h the password Pa$$w0rd. Note: If necessary, click k Switch User r to display th he list of users s. 4. 5. 6. 7. 8. 9. he Windows 8 Start window w. Switch to th Click Visual Studio 2012. udio, on the F File menu, point to Open, and a then click k Project/Solution. In Visual Stu In the Open n Project dial log box, brow wse to E:\Demo ocode\Starter r\FourthCoffe ee.MetadataEx xtractor folder, click k FourthCoffe ee.MetadataE Extractor.sln, and then clic ck Open. In Solution Explorer, righ ht-click Fourth hCoffee.MetaD DataExtractor, , and then clic ck Set as Start tUp Project. In Visual Stu udio, on the V View menu, click Task List.

0. In the Task k List window, , in the Categ gories list, click Comments s. 10 ck the TODO: 01: Invoke the e Type.GetCustomAttribute e method. tas sk. 11. Double-clic e editor, click i in the blank line below the comment, an nd then type t the following code: 12. In the code
var typeAttribute = t type.GetCust tomAttribute< <DeveloperIn nfo>(false);

t TODO: 02 2: Invoke the M MemberInfo.G GetCustomAtt tribute 13. In the Task List window, double-click the method. tas sk.

Programming in Visual C# 12-25

14. In the code editor, click in the blank line below the comment, and then type the following code:
var memberAttribute = member.GetCustomAttribute<DeveloperInfo>(false);

15. On the Build menu, click Build Solution. 16. On the Debug menu, click Start Without Debugging. 17. In the Fourth Coffee Metadata Extractor application, click Load. The list box now contains a list of all of the members in the Encryptor type and the details from any DeveloperInfo attributes that were found. 18. Close Fourth Coffee Metadata Extractor. 19. In Visual Studio, close the solution.

12-26

Creating Reusable Types and Assemblies

Lesson 3

Gener rating M Manage ed Code

Yo ou can use Visual Studio to write manage ed code when n you have cle early defined requirements r upon wh hich to base your implemen ntation. Howe ever, sometim mes you may w want to genera ate code at ru un time based on a vary ying set of req quirements. In this scenario, , you need a framework f that enables you to define ins structions that t a process can translate into executable e code. The .N NET Framewor rk provides the Co odeDOM featu ure for this ve ery purpose. In this lesson, yo ou will learn h how to genera ate managed code at run ti ime by using CodeDOM.

Le esson Obje ectives


Aft ter completing this lesson, you will be ab ble to: Describe the purpose of CodeDOM. pe by using CodeDOM. Define a typ Compile a C CodeDOM mo odel into sour rce code files. Compile source code file es into an asse embly.

Programming in Visual C#

12-27 7

W What Is CodeDOM?

CodeDOM is a feature of th C he .NET Frame ework that en nables you to generate cod de at run time. CodeDOM e enables you to o build a mod del that represents the source code that you want to c create and then generate t source code by using o the one of the cod de generators that are inclu uded in CodeD DOM. By defa ault, C CodeDOM inc cludes code g generators for Visual C#, Microsoft Visual Basic, and Microsoft JSc cript. CodeDOM is a powerful fea C u can use for generating te emplate sourc ce files that co ontain ature that you b boilerplate co ode or even ge enerating sou urce code files s that serve as s a proxy betw ween your app plication and a remote entity. To use Cod deDOM in your application n, use the follo owing namesp paces: System.C CodeDom. Th his namespace e contains typ pes that enable e you to defin ne a model that represents the sourc ce code you w want to genera ate. System.C CodeDom.Co ompiler. This n namespace co ontains types that enable you to generat te and manage c compiled code. Microsof ft.CSharp.CSh harpCodePro ovider. This na amespace con ntains the Visu ual C# code compiler c and generator. Microsof ft.JScript.JScriptCodeProv vider. This na amespace con ntains the JScr ript code compiler and generator. Microsof ft.VisualBasic c.VBCodePro ovider. This na amespace con ntains the Visu ual Basic code e compiler and gene erator.

You can use the classes in t Y the System.CodeDom nam mespace to cr reate a model that represen nts the code y want to c you create. The mo odel can inclu ude anything f from a complex class hierar rchy to a single class with s some membe ers. For examp ple, you can us se the CodeN Namespace cl lass to represe ent a namespa ace, and you c use the CodeMemberMethod class can s to represent t a method. T following table describ The bes some of th he classes you u can use to cr reate your mo odel. Class CodeCompileUnit CodeNamespace Description Enables yo ou to encapsu ulate a collecti ion of types that ultima ately will com mpile into an a assembly. Enables yo ou to define a namespace t that you can

12-28

Creating Reusable Types and Assemblies

Class

Description use to organize your class hierarchy.

CodeTypeDeclaration CodeMemberMethod

Enables you to define a class, structure, interface, or enumeration in your model. Enables you to define a method in your model and add it to a type, such as a class or an interface. Enables you to define a field, such as an int variable, and add it to a type, such as a class or struct. Enables you to define a property with get and set accessors and add it to a type, such as a class or struct. Enables you to define a constructor so that you can create an instance type in your model. Enables you to define a static constructor so that you can create a singleton type in your model. Enables you to define an entry point in your type, which is typically a static method with the name Main. Enables you to create a set of instructions that represents an expression that you want to execute. Enables you to create a set of instructions that detail a method in a particular type that you want to execute. Typically, you would use this class with the CodeMethodInvokeExpression class when you implement the body of method in a model. Enables you to represent a reference type that you want to use as part of an expression in your model. Typically, you would use this class with the CodeMethodInvokeExpression class and the CodeTypeReferenceExpression class when you implement the body of method in a model. Enables you to define an expression value, which you may want to pass as a parameter to a method or store in a variable.

CodeMemberField

CodeMemberProperty

CodeConstructor CodeTypeConstructor CodeEntryPoint

CodeMethodInvokeExpression

CodeMethodReferenceExpression

CodeTypeReferenceExpression

CodePrimitiveExpression

After you have defined your model by using the classes in the System.CodeDom namespace, you can then use a code generator provider, such as the CSharpCodeProvider class in the Microsoft.CSharp.CSharpCodeProvider namespace, to compile your model and generate your code. Additional Reading: For more information about CodeDOM, see the Dynamic Source Code Generation and Compilation page at http://go.microsoft.com/fwlink/?LinkID=267870.

Programming in Visual C# 12-29

12-30

Creating Reusable Types and Assemblies

Defining a Type and Type Members

De efining a type by using Cod deDOM follow ws the same pattern as defining a type in n native Visual C#. The on nly difference is that when u using CodeDO OM, you write e a set of instr ructions that a code genera ator pro ovider will int terpret to gen nerate the source code that t represents yo our model. The System.Cod deDOM namespace includ des the types that t you can use u to write th hese instructio ons. The fol llowing steps describe how w to use some of the System m.CodeDOM types to define a type that t contains an entry point method m name ed Main: 1. Create a Co odeCompileU Unit object to represent the e assembly that will contain n the type. The following code examp ple shows how w to create a C CodeCompile eUnit object.
var unit = new CodeC CompileUnit();

2.

Create a Co odeNamespace object to r represent the namespace th hat the type w will be scoped d to and add the nam mespace to th he CodeComp pileUnit obje ect. The follow wing code example shows h how to define the F FourthCoffee e.Dynamic na amespace.
var dynam micNamespace e = new CodeNamespace("F FourthCoffee e.Dynamic"); unit.Name espaces.Add( (dynamicNamespace);

3.

Import any additional na amespaces tha at the types in n the namespa ace will use. T The following code example shows how to b bring the Syst tem namespac ce into scope.
dynamicNa amespace.Imp ports.Add(new w CodeNamesp paceImport(" "System"));

4.

Create a Co odeTypeDeclaration objec ct that represe ents the type you want to a add to the namespace. The followin ng code exam mple shows ho ow to create a type named Program.
var progr ramType = ne ew CodeTypeDeclaration(" "Program"); dynamicNa amespace.Typ pes.Add(programType);

5.

Create a Co odeEntryPoin ntMethod obj ject to represent the static main method d in the Progr ram type. The followin ng code exam mple shows ho ow to define a an entry point t method nam med Main and d add it to the Program type.
var mainM Method = new w CodeEntryPo ointMethod() );

Programming in Visual C# 12-31

programType.Members.Add(mainMethod);

6.

Define the body of the Main method by using the CodeMethodInvokeExpression, CodeTypeReferenceExpression, and CodePrimitiveExpression classes. The parameters that you pass to the constructors of these objects enable you to define which method you want to invoke and the parameters that the method expects. The following code example shows how invoke the Console.WriteLine method to write the message Hello Development Team..!! to the console window.
var expression = new CodeMethodInvokeExpression( new CodeTypeReferenceExpression("Console"), "WriteLine", new CodePrimitiveExpression("Hello Development Team..!!")); mainMethod.Statements.Add(expression);

After you have defined your model, you can then use a code generator provider to compile and generate your code. Additional Reading: For more information about how to define a model by using CodeDOM, see the Using the CodeDOM page at http://go.microsoft.com/fwlink/?LinkID=267871.

12-32

Creating Reusable Types and Assemblies

Co ompiling a CodeDO OM Mode el

Aft ter you have defined d the co ontents of you ur assembly b by using the ty ypes in the Sy ystem.CodeD DOM namespace, you u can then com mpile and gen nerate an asse embly. You ca an split the pro ocess for com mpiling and ge enerating an a assembly into the following g parts: 1. 2. Compiling t the model and generating source code files f for each t type. Generating an assembly that contains the necessary y references and a the types that are defin ned in the source code e files.

Co ompiling a Model into o a Source C Code File


To o compile your model and g generate sour rce code files, perform the following step ps: 1. nstance of the e code genera ator provider y you want to u use. The follow wing code exa ample Create an in shows how to create an instance i of th he CSharpCod deProvider class that will p produce Visua al C# code.
var provi ider = new C CSharpCodePro ovider();

2.

Create a Str reamWriter o object that the code gener rator will use t to write the co ompiled code e to a file. The followin ng code exam mple shows ho ow to create a StreamWrit ter object.
var fileN Name = "prog gram.cs"; var strea am = new Str reamWriter(fileName);

3.

Create an In ndentedText tWriter objec ct that will writ te the indente ed source cod de to a file. Th he following code examp ple shows how w to create an n IndentedTe extWriter object.
var textW Writer = new w IndentedTex xtWriter(str ream);

4.

Create a Co odeGeneratorOptions object that encap psulates your code generat tion settings. The following co ode example shows how to o create a Cod deGeneratorO Options obje ect and set the e BlankLines sBetweenMem mbers property so that me embers are se eparated by a blank line.
var opti ions = new C CodeGeneratorOptions(); options. .BlankLinesB BetweenMembers = true;

Programming in Visual C# 12-33

5.

Invoke the GenerateCodeFromCompileUnit method on the CSharpCodeProvider object to generate the source code. The following code example shows how to invoke the GenerateCodeFromCompileUnit method, passing the CodeCompileUnit, IndentedTextWriter, and CodeGeneratorOptions objects as parameters.
var compileUnit = FourthCoffee.GetModel(); provider.GenerateCodeFromCompileUnit(compileunit, textWriter, options);

6.

Close the IndentedTextWriter and StreamWriter objects. The following code example shows how to close the IndentedTextWriter and StreamWriter objects, flushing the compiled code to the output file.
textWriter.Close(); stream.Close();

After you have executed the code to compile your model, you will have a source .cs file that contains the compiled Visual C# code. The following code example shows the compiled Visual C# code for a model that contains the Program type with an entry point method called Main. Compiled Visual C# Code
//-----------------------------------------------------------------------------// <auto-generated> // This code was generated by a tool. // Runtime Version:4.0.30319.17626 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </auto-generated> //-----------------------------------------------------------------------------namespace FourthCoffee.Dynamic { using System; public class Program { public static void Main() { Console.WriteLine("Hello Development Team..!!"); } } }

12-34

Creating Reusable Types and Assemblies

Co ompiling Source Co ode into a an Assemb bly

Aft ter you have compiled c you ur CodeDOM model m into on ne or more so ource code file es, you can co ompile the file es into an asse embly. To o generate an executable as ssembly that c contains the F FourthCoffee e.Dynamic.Pr rogram type from f a source code file e, perform the e following ste eps: 1. Create an in nstance of the e code genera ator provider y you want to u use. The follow wing code exa ample shows how to create an instance i of th he CSharpCod deProvider class that will p produce the executable assembly.
var provi ider = new C CSharpCodePro ovider();

2.

Create a Co ompilerParam meters object t that you will use to define e the settings for the compiler, such as which assem mblies to reference, and wh hether to generate a .dll or r an .exe file. The T following code example shows how to create a Comp pilerParameters object, ad dd a reference e to the System m.dll file, and instruct t the compiler to generate an executable file named FourthCoffee. .exe.
var compi ilerSettings s = new CompilerParamete ers(); compilerS Settings.Ref ferencedAssem mblies.Add(" "System.dll" "); compilerS Settings.Gen nerateExecutable = true; ; compilerS Settings.Out tputAssembly = "FourthCo offee.exe";

3.

Invoke the CompileAsse emblyFromFi ile method on n the CSharpC CodeProvide er object to ge enerate the assembly. T The following code example e shows how t to invoke the CompileAssemblyFromF File method, pa assing the Com mpilerParameters object and a a string v variable that contains the path to the source code e file.
var sourc ceCodeFileNa ame = "program.cs"; var compi ilationResults = provider.CompileAs ssemblyFromF File( compil lerSettings, source eCodeFileNam me);

Note: The e CompileAss semblyFromF File method also a accepts an array of sou urce file name es, so you can compile several so ource code files into a single assembly.

Programming in Visual C# 12-35

4.

You can then use the properties that the CompilerResults object provides to determine whether the compilation was successful. The following code example shows how to iterate the CompilationErrorCollection object by using the Errors property.
var buildFailed = false; foreach (var error in compilationResults.Errors) { var errorMessage = error.ToString(); buildFailed = true; }

You have now generated an assembly that displays the message Hello Development Team..!! when it is executed. Additional Reading: For more information about how to compile a CodeDOM model, see the Generating and Compiling Source Code from a CodeDOM Graph page at http://go.microsoft.com/fwlink/?LinkID=267872.

12-36

Creating Reusable Types and Assemblies

Lesson 4

Versio oning, S Signing g, and Deployi D ng Assemblies

Wh hen you finish h developing an application n, you should sign and vers sion the assem mbly before yo ou dis stribute it to u users. You must also consid der how and w where the asse embly is going g to be installed. In this lesson, yo ou will learn h how to version n assemblies a and install an assembly into o the GAC.

Le esson Obje ectives


Aft ter completing this lesson, you will be ab ble to: es. Describe the key features of assemblie Describe the GAC. w to sign an assembly. Explain how Describe the key features of assembly y versioning. ssembly in the e GAC. Install an as

Programming in Visual C#

12-37 7

W What Is an n Assemb bly?

An assembly i A is a collection of types and resources tha at form a unit of functionality. An assembly might c consist of a single portable e executable (P PE) file, such a as an executable (.exe) prog gram or dynamic link l library (.dll) fil le, or it might consist of mu ultiple PE files s and external resource files s, such as bitm maps or data f files. An assem mbly is the building block of o a .NET Fram mework applic cation because e an application consists of f o or more a one assemblies.

C Contents of Assemblie es
A assembly c An consists of the e following co omponents: Intermedi iate language e (IL) code. The e compiler tra anslates the so ource code int to IL, which is the set of instructio ons that the ju ust-in-time (JIT T) compiler th hen translates to CPU-speci ific code befo ore the applicatio on runs. Resources s. These includ de images and d assembly m metadata. Asse embly metada ata exists in th he form of the e assembly manifest. Type met tadata. Type m metadata prov vides informat tion about av vailable classes s, interfaces, m methods, and propertie es, similar to th he way that a type library p provides infor rmation about t COM compo onents. The assem mbly manifest t. This contains assembly metadata and p provides infor rmation about t the assembly such as the title, the descr ription, and ve ersion informa ation. The manifest also contains information about link ks to the other r files in the assembly. The information in the manifes st is used at run time to resolve references and v n be stored in validate loade ed assemblies. . The assembly y manifest can n a separate file but is of ften part of on ne of the PE f files.

B Boundaries s of Assemb blies


By arranging y B your code int to assemblies, you create a set of boundaries that you u can use to is solate c configuration to a particula ar assembly. T The following list describes some of the boundaries b th hat assemblies s p provide: Security boundary b . You u set security permissions p at an assembly y level. You ca an use these p permissions to o request specific access for an application, for example, file I/O permissions if the applicat tion must is loaded at ru write to a disk. When t the assembly i un time, the permissions p th hat are reques sted are entered in nto the securi ity policy and used to determine whethe er permissions s can be grant ted.

12-38

Creating Reusable Types and Assemblies

Type boundary. An assembly provides a boundary for data types, because each type has the assembly name as part of its identity. As a result, two types can have the same name in different assemblies without any conflict. Reference scope boundary. An assembly provides a reference scope boundary by using the assembly manifest to resolve type and resource requests. This metadata specifies which types and resources are exposed outside the assembly.

Benefits of Assemblies
Assemblies provide you with the following benefits: Single units of deployment. The client application loads assemblies when it needs them, which enables a minimal download strategy where appropriate. Versioning. An assembly is the smallest unit in a .NET Framework application that you can version. The assembly manifest describes the version information and any version dependencies that are specified for any dependent assemblies. You can only version assemblies that have strong names.

Additional Reading: For more information about assemblies, see the Assemblies in the Common Language Runtime page at http://go.microsoft.com/fwlink/?LinkID=267873.

Programming in Visual C#

12-39 9

W What Is th he GAC?

When you cre W eate an assem mbly, by default you create a private asse embly that a si ingle applicat tion can use. I you need to If o create an assembly that m multiple applic cations can sh hare, you shou uld give the assembly a s strong name a and install the e assembly int to the GAC. A strong name is a unique name for an a assembly that t consists of th he assemblys name, versio on number, c culture inform mation, and a digital signatu ure that conta ains a public a and private ke ey. The GAC store T es the assemb blies that you want to share e between mu ultiple applications. When y you add an a assembly to th he GAC, the GAC G performs s integrity che ecks on all of t the files that f form the assem mbly. These c checks ensure e that nothing g has tampere ed with an assembly. For ex xample, the GA AC checks for r changes to a f that the manifest file m does not reflect. You can exam Y mine the GAC by using File Explorer. Brow wse to C:\Win ndows\assemb bly to see the list of a assemblies in the GAC. The e information in the list of installed assem mblies include es the followin ng: The globa al assembly name The versio on number of f the assembly y The culture of the asse embly, if applicable The publi ic key token o of the assembly in the stron ng name The type of assembly

B Benefits of f Using the GAC


Although you A u can install strong-named assemblies in directories on n the comput ter, the GAC o offers several b benefits, inclu uding the follo owing: Side-by-side deploymen tion. Different versions of an assembly in n the GAC do not affect nt and execut each othe er. Therefore, applications that t reference e different ver rsions of an as ssembly do no ot fail if a later inco ompatible vers sion of the ass sembly is insta alled into the cache. Improved d loading time. When you in nstall a strong g-named assem mbly in the GAC, it undergoes strongname validation, which h ensures that t the digital signature is val lid. The verific cation process s occurs at installatio on time, so str rong-named a assemblies in the GAC load faster at run time than ass semblies that are not in nstalled in the e GAC.

12-40

Creating Reusable Types and Assemblies

Reduced memory consumption. If multiple applications reference an assembly, the operating system loads only one instance of the assembly, which can reduce the total memory that is used on the computer. Improved search time. The CLR can locate a strong-named assembly in the GAC faster than it can locate a strong-named assembly that is in a directory. This is because the runtime checks the GAC for a referenced assembly before it checks other locations. Improved maintainability. With a single file that multiple applications share, you can easily make fixes that affect all of the applications.

Programming in Visual C#

12-41 1

S Signing A Assemblies s

When you sig W gn an assembly y, you give th he assembly a strong name. A strong nam me provides an assembly w a globally unique nam with me that applica ations use wh hen they reference your ass sembly. This ensures that n one else ca no an compile an n assembly with the same n name as yours s and imperso onate your ass sembly. This h helps to avoid d malicious co ode overwritin ng one of your assemblies a and then bein ng run from an n application t that expects to be using yo our authentic code. A strong name requires two o cryptograph hic keys, a public key and a private key, known as a ke ey pair. The c compiler uses s the key pair at build time to create the strong name. The strong n name consists of the simple e t text name of t the assembly, , the version number, n optio onal culture in nformation, th he public key, and a digital s signature.

C Creating Ke ey Pairs
You must hav Y ve a key pair to o sign an asse embly with a strong s name. To create a k key pair, use th he Strong N Name tool (Sn n.exe) that the e .NET Framew work provides s. To create a key pair file, p perform the following f s steps: 1 1. 2 2. Open the e Visual Studio o 2012 command prompt. In the Co ommand Prom mpt window, use the Sn.ex xe tool with th he K switch to o create a new w key file. The following g code example shows how w to create a new key file wi ith the name FourthCoffee eKeyFile.
sn -k FourthCoffee F KeyFile.snk

A After you hav ve created a ke ey file, you can then sign yo our assembly. .

S Signing an Assembly
When you hav W ve created the e key pair, you can then associate the ke ey file with yo our assembly. Y You can a achieve this using the Sign ning tab in the e project prop perties pane. W When you spe ecify a key file e in the p properties pane, Visual Studio adds the A AssemblyKey yFileAttribut te attribute to o the AssemblyInfo class i your applic in cation. The following code example shows how to associate t T the FourthCof ffeeKeyFile.sn nk file with you ur assembly b using the A by AssemblyKey yFileAttribute e attribute.

12-42

Creating Reusable Types and Assemblies

The AssemblyKeyFileAttribute attribute


[assembly: AssemblyKeyFileAttribute("FourthCoffeeKeyFile.snk")]

Delay-Signing an Assembly
When you sign an assembly, you might not have access to a private key. For example, for security reasons, some organizations restrict access to their private key to just a few individuals. The public key will generally be available because as its name implies, it is publicly accessible. In this situation, you can use delayed signing at build time. You provide the public key and reserve space in the PE file for the strongname signature. However, you defer the addition of the private key until a later stage, typically just before the assembly ships. You can enable delay-signing on the Signing tab of the project properties window as follows: 1. 2. 3. 4. 5. In Solution Explorer, right-click the project, and then click Properties. In the properties window of the project, click the Signing tab. Select the Sign the assembly check box. Specify a key file. Select the Delay sign only check box.

You cannot run or debug a delay-signed project. You can, however, use the Sn.exe tool with the -Vr option to skip verification, which means that the identity of the assemblies will not be checked. However, you should only use this option at development time because it creates a security vulnerability. The following code example turns off verification for an assembly called FourthCoffee.Core.dll. Disabling Verification
sn Vr FourthCoffee.Core.dll

You can then submit the assembly to the signing authority of your organization for the actual strongname signing. Use the R option with the Sn.exe tool to resign a delay-signed assembly. The following code example signs an assembly called FourthCoffee.Core.dll with a strong name by using the sgKey.snk key pair. Signing an Assembly
sn -R FourthCoffee.Core.dll sgKey.snk

Additional Reading: For more information about delay signing, see the Delay Signing an Assembly page at http://go.microsoft.com/fwlink/?LinkID=267874.

Programming in Visual C#

12-43 3

V Versioning g Assemb blies

is typically 1.0 All assemblies A s are given a v version number by Visual S Studio, which i 0.0.0. It is the responsibility o the develop of per to increment the assem mblys version number as th he assembly e evolves. It is important I t to version as ssemblies so t that you can k keep track of w which version n of your application users a using. Wit are thout a version number, de ebugging and reproducing production is ssues can be d difficult.

A Assembly V Version Num mber


The version number of an assembly T a is a four-part strin ng with the fo ollowing form mat: <major v version >.<min nor version>.< <build numbe er>.<revision> >. For example e, version 1.2.3.0 indicates 1 as the m major version, 2 as the min nor version, 3 as the build n number, and 0 as the revisio on number. The assembly manifest stor T res the version n number along with other r identity information such as the in conjunction a assembly nam me and public key. The CLR uses the vers sion number, i n with the ava ailable c configuration information, to load the p proper version n of a referenc ced assembly. By default, ap B pplications onl ly run with the version of a an assembly with w which the ey were built. To T change an n a application to o use a differe ent version of an assembly, you can creat te a version policy in one o of the c configuration files: the app plication config guration file, the publisher policy file, or r the compute er's a administrator configuration n file.

R Redirecting g Binding R Requests


When you wa W ant to update a strong-nam med component without red deploying the e client applic cation that u uses it, you ca an use a publisher policy file to redirect a binding request to a new wer instance of f the c component. W When a client t application m makes a binding request, th he runtime pe erforms the fo ollowing tasks: It checks the original a assembly refer rence for the version v to be bound. It checks the configura ation files for version v policy y instructions.

The following code example shows a publisher policy T y file. To redire ect one versio on to another, use the <bindingRed direct> eleme ent. The oldVe ersion attribu ute can specify y either a sing gle version or a range of v versions. For e example, <bin ndingRedirec ct oldVersion n="1.1.0.0-1. .2.0.0" newV Version="2.0.0.0"/> s specifies that the runtime s should use version 2.0.0.0 in nstead of the assembly ver rsions between n 1.1.0.0 and 1 1.2.0.0.

12-44

Creating Reusable Types and Assemblies

Assembly Binding Redirect


<configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name=" FourthCoffee.Core" publicKeyToken="32ab4ba45e0a69a1" culture="en-us" /> <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/> </dependentAssembly> </assemblyBinding> </runtime> </configuration>

Additional Reading: For more information about versioning, see the Assembly Versioning page at http://go.microsoft.com/fwlink/?LinkID=267875.

Programming in Visual C#

12-45 5

I Installing an Assem mbly into the t GAC

The GAC is a f T folder on file system where e you can insta all your assem mblies. You can install your assemblies i into the GAC in a variety of f ways, which include the fo ollowing: Global As ssembly Cache e tool (Gacutil l.exe). You can n use Gacutil.e exe to add str rong-named a assemblies to the GAC a and to view th he contents o of the GAC. Ga acutil.exe is fo or developmen nt purposes. Y You should not use th he tool to inst tall production assemblies into the GAC. . Microsoft t Windows Installer 2.0. This s is the recom mmended and most commo on way to add d assemblies to the GA AC. The installer provides benefits such a as reference co ounting of ass semblies in th he GAC.

I Installing a an Assembly y into the G GAC by Using Gacutil. .exe


To install an a T assembly into the GAC by using u the Gacu util.exe comm mand-line tool l, perform the e following s steps: 1 1. 2 2. Open the e Visual Studio o 2012 command prompt a as an administ trator. In the Co ommand Prom mpt window, type the follo owing comma and:
gacutil i "<pathT ToAssembly>"

V Viewing an n Assembly in the GAC C by Using G Gacutil.exe e


To view an assembly that is T s installed into o the GAC by using the Gac cutil.exe comm mand-line too ol, perform t following steps: the 1 1. 2 2. Open the e Visual Studio o 2012 command prompt a as an administ trator. In the Co ommand Prom mpt window, type the follo owing comma and:
gacutil l "<assemblyName>"

Additio onal Reading: For more inf formation abo out the GAC, s see the Globa al Assembly Ca ache p page at http:/ //go.microsoft t.com/fwlink/ /?LinkID=2678 876.

12-46

Creating Reusable Types and Assemblies

Demonstration: Sign ning and I Installing an Assem mbly into t the GAC

In this demonstration, you wi ill use the Sn.e exe and Gacutil.exe comma and-line tools s to sign and install an existing assemb bly into the GA AC.

De emonstration Steps
1. 2. 3. Start the MSL-TMG1 virtual machine if it is not already running. 0483A-SEA-DE EV11-12 virtual machine. Start the 20 Log on to W Windows 8 as Student with h the password Pa$$w0rd. Note: If necessary, click k Switch User r to display th he list of users s. 4. 5. 6. 7. 8. 9. he Windows 8 Start window w. Switch to th In the Searc ch box, type c command, right-click VS201 12 x64 Cross Tools T Comma and Prompt, a and then click Run as s administrato or. In the User r Account Con ntrol dialog b box, in the Password box, type Pa$$w0 0rd, and then click Yes. In the VS20 012 x64 Cross Tools Comm mand Promp pt window, ch hange to the E:\Democod de\Starter\FourthCoffee.Co ore\FourthCof ffee.Core directory. Run the gen nerateKeyFile.cmd file. The e generateKey yFile.cmd file u uses the Sn ap pplication to g generate a key file. he Windows 8 Start window w. Switch to th

0. Click Visual Studio 2012. 10 udio, on the F File menu, point to Open, and a then click k Project/Solution. 11. In Visual Stu n Project dial log box, brow wse to the E:\D Democode\Sta arter\FourthCoffee.Core folder, click 12. In the Open FourthCoff fee.Core.sln, and then click Open. ht-click the Fo ourthCoffee.C Core project, and then click k Open Folde er in File 13. In Solution Explorer, righ Explorer. 4. In File Explo orer, highlight t the FourthCo offeeKeyFile.s snk file that th he Sn applicat tion generated d. 14

Programming in Visual C# 12-47

15. Switch to Visual Studio 2012. 16. In Solution Explorer, right-click FourthCoffee.Core, and then click Properties. 17. On the Signing tab, select Sign the assembly. 18. In the Choose a strong name key file list, click Browse. 19. In the Select File dialog box, click FourthCoffeeKeyFile.snk, and then click Open. 20. On the Build menu, click Build Solution. 21. Switch to File Explorer. 22. In the E:\Democode\Starter\FourthCoffee.Core\FourthCoffee.Core folder, right-click the installAssemblyInGac.cmd file, and then click Edit. 23. In Notepad, view the Gacutil command. 24. Close Notepad, and then close File Explorer. 25. Switch to the VS2012 x64 Cross Tools Command Prompt window, and then run the installAssemblyInGac command. Verify that the command ran successfully. 26. Run the verifyGacInstall command, and then ensure that the number of items found equals one. 27. Close the VS2012 x64 Cross Tools Command Prompt window. 28. In Visual Studio, close the solution.

12-48

Creating Reusable Types and Assemblies

Demonstration: Spe ecifying th he Data to o Include in the Grades Report Lab

In this demonstration, you wi ill see the task ks that you wi ill perform in the lab for this module.

Programming in Visual C#

12-49 9

Lab: Specify ying the e Data to Inclu ude in the t Gra ades Re eport

S Scenario
You decide to Y o update the G Grades applica ation to use custom c attribu utes to define the fields and d properties t that should be e included in a grade report and to form mat them appropriately. This will enable further r reusability of the Microsoft t Word report ting functiona ality. You will host t Y this code in th he GAC to ensure that it is available to other o applications that requ uire its s services.

O Objectives
A After complet ting this lab, you y will be able to: Define cu ustom attribut tes. Use reflec ction to examine metadata at run time. Sign an assembly and d deploy it to th he GAC.

E Estimated Tim me: 75 minutes Virtual Machine: 20483 3-SEA-DEV11-12, MSL-TMG G1 User Nam me: Student Password d: Pa$$w0rd

12-50

Creating Reusable Types and Assemblies

Exercise 1: Creating and Applying the IncludeInReport attribute


Scenario
In this exercise, you will create the IncludeInReport attribute to specify the fields and the format of each field that is included in the grades report. First, you will write code for the IncludeInReportAttribute class and define the members that are contained in it. Next, you will apply the attribute to the appropriate properties in the LocalGrade class in the Data.cs file. Finally, you will build the application and then use the MSIL Disassembler utility (IL DASM) to examine the metadata that the attribute generates. The main tasks for this exercise are as follows: 1. Write the code for the IncludeInReportAttribute class 2. Apply the IncludeInReportAttribute attribute to the appropriate properties 3. Build the application and review the metadata for the LocalGrades class

X Task 1: Write the code for the IncludeInReportAttribute class


1. 2. 3. 4. Start the MSL-TMG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-12 virtual machine and log on as Student with the password Pa$$w0rd. Start Visual Studio, and then open the Grades.sln solution from the E:\Labfiles\Starter\Exercise 1 folder. Set the following projects to start without debugging at startup: a. b. 5. 6. 7. 8. 9. Grades.Web Grades.WPF

In the Grades.Utilities project, in the IncludeInReport.cs class, add code to specify that the IncludeInReportAttribute class is an attribute class. Add code to specify that the possible targets to which the IncludeInReport attribute can be applied are fields and properties and that the attribute can be applied only once to each entity. In the IncludeInReportAttribute class, define a private Boolean variable named _include to hold the value of the attribute. In the IncludeInReportAttribute class, define two public read/write Boolean properties named Underline and Bold. In the IncludeInReportAttribute class, define a public read/write string property named Label.

10. In the IncludeInReportAttribute class, create a default constructor that sets the properties as follows: _include: true Underline: false Bold: false Label: string.Empty

11. Create another constructor that takes a Boolean parameter named includeInReport and sets the properties as follows:

Programming in Visual C# 12-51

_include: _includeInReport Underline: false Bold: false Label: string.Empty

X Task 2: Apply the IncludeInReportAttribute attribute to the appropriate properties


1. In the Grades.WPF project, in the Data.cs file, in the LocalGrade class, add the IncludeInReport attribute to the appropriate properties of the LocalGrade class as follows: SubjectName property: Label: Subject Name Bold: true Underline: true AssessmentDate property: Label: Date Assessment property: Label: Grade Comments property: Label: Comments

X Task 3: Build the application and review the metadata for the LocalGrades class
1. 2. Build the solution, and then resolve any compilation errors. Use the IL DASM utility to examine the metadata of the LocalGrades class in the Grades.WPF.exe assembly.

Note: The IL DASM utility is located in the C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools folder, and the Grades.WPF.exe assembly is located in the E:\Labfiles\Starter\Exercise 1\Grades.WPF\bin\Debug folder. 3. Verify that the IncludeInReport attribute has been applied to the specified properties in the class.

Results: After completing this exercise, the Grades.Utilities assembly will contain an IncludeInReport custom attribute and the Grades class will contain fields and properties that are tagged with that attribute.

12-52

Creating Reusable Types and Assemblies

Exercise 2: Updating the Report


Scenario
In this exercise, you will update the grades report to include fields and properties only if they are tagged with the IncludeInReport attribute. First, you will implement a method named GetItemsToInclude in a static helper class called IncludeProcessor that implements the logic that is necessary to discover the fields and properties that are tagged with the IncludeInReport attribute. You will then update the code for the StudentProfile view to include fields and properties in the report only if they are tagged with the IncludeInReport attribute and to format them appropriately. The main tasks for this exercise are as follows: 1. Implement a static helper class called IncludeProcessor 2. Update the report functionality for the StudentProfile view

X Task 1: Implement a static helper class called IncludeProcessor


1. 2. 3. 4. In Visual Studio, open the Grades.sln solution from the E:\Labfiles\Starter\Exercise 2 folder. In the Grades.Utilities project, open IncludeInReport.cs. Locate the FormatField struct declaration, and then add two string members named Value and Label and two Boolean members named IsBold and IsUnderlined. In the GetItemsToInclude method of the IncludeProcessor class, after the variable declarations, add code to find all of the public fields and properties in the dataForReport object and use the AddRange method add them to the fieldsAndProperties list. Add code to iterate through all of the public fields and properties. In the loop, add code to retrieve all the custom attributes applied to an item. Then use the Array.Find method to test whether any of the custom attributes applied to the item are the IncludeInReport attribute. At the end of the loop, add code to find the value of the item that is tagged with the IncludeInReport attribute. At the end of the loop, add code to construct a FormatField item containing the value of the item and the label, bold, and underline values from the attribute.

5. 6. 7. 8. 9.

10. At the end of the loop, add code to add the FormatField item to the collection to be returned.

X Task 2: Update the report functionality for the StudentProfile view


1. In the Grades.WPF project, in the StudentProfile.xaml.cs class, in the GenerateStudentReport method, at the start of the foreach loop, add code to use the IncludeProcessor class to determine which fields in the Grade object are tagged with the IncludeInReport attribute. Add code to include each tagged item in the output, using the format that is specified by the properties of the IncludeInReport attribute for each item. Build the solution, and then resolve any compilation errors. Close the solution.

2. 3. 4.

Results: After completing this exercise, the application will be updated to use reflection to include only the tagged fields and properties in the grades report.

Programming in Visual C# 12-53

12-54

Creating Reusable Types and Assemblies

Exercise 3: Storing the Grades.Utilities Assembly Centrally


Scenario
In this exercise, you will store the Grades.Utilities assembly in the GAC. First, you will use Sn.exe to generate a key pair and then use the key pair to sign the Grades.Utilities assembly. Next, you will use Gacutil.exe to add the assembly to the GAC. You will then update the reference for the Grades.Utilities assembly in the Grades.WPF project to use the new signed assembly that is hosted in the GAC, and finally you will test the application to ensure that the reports are correctly generated. The main tasks for this exercise are as follows: 1. Sign the Grades.Utilities assembly and deploy it to the GAC 2. Reference the Grades.Utilities assembly in the GAC from the application

X Task 1: Sign the Grades.Utilities assembly and deploy it to the GAC


1. 2. In Visual Studio, open the Grades.sln solution from the E:\Labfiles\Starter\Exercise 3 folder. Set the following projects to start without debugging at startup: a. b. 3. 4. 5. 6. 7. 8. Grades.Web Grades.WPF

Run the VS2012 x86 Native Tools Command Prompt window as Administrator. Run the Sn.exe utility to create a key pair file named GradesKey.snk in the E:\Labfiles\Starter folder. In Visual Studio, set the properties of the Grades.Utilities project to use the key pair that you have just created to sign the assembly. Build the solution, and then resolve any compilation errors. At the command prompt, use the Gacutil utility to add the Grades.Utilities assembly to the GAC. Close the Command Prompt window.

X Task 2: Reference the Grades.Utilities assembly in the GAC from the application
1. 2. 3. 4. 5. 6. 7. 8. 9. In Visual Studio, remove the current reference to the Grades.Utilities project from the Grades.WPF project. Add a new reference to the signed Grades.Utilities.dll assembly. Build the solution, and then resolve any compilation errors. Run the application. Log on as vallee with a password of password99. Create and save a grades report for Kevin Liu. Close the application, and then close the solution. Open the grades report that you just created in Word and verify that the document contains a correctly formatted report. Close Word.

Programming in Visual C# 12-55

Results: After completing this exercise, you will have a signed version of the Grades.Utilities assembly deployed to the GAC.

12-56

Creating Reusable Types and Assemblies

Modu ule Revi iew and d Takea aways

M Module Revie ew
In this module, y you learned how h to consum me existing as ssemblies by u using reflectio on and how to o add additional meta adata to types s and type me embers by usin ng attributes. You also learned how to g generate code at run time e by using Co odeDOM and how you can ensure that y your assemblie es are versioned and ava ailable to other application ns by using the GAC. Ve erify the correc ctness of the statement by placing a ma ark in the column to the rig ght. S Statement You are developing an app Y plication that enables e users to browse the object m model of a co ompiled type. At no point w will the applica ation attempt t to e execute any c code; it will me erely serve as a viewer. You u notice the co ode that l loads the asse embly uses the e Assembly.L LoadFrom sta atic method. T This is the m most suitable method takin ng into account the require ements of the e a application. Test Your Know wledge Q Question Y You are develo oping a custo om attribute. You want to derive your custom c attrib bute class fr rom the abstract base clas ss that underp pins all attributes. Which c class should y you use? S Select the cor rrect answer. Attribu ute Contex xtAttribute Extens sionAttribute DataA Attribute Answer

Programming in Visual C# 12-57

Question AddInAttribute Test Your Knowledge Question You are reviewing some code that uses CodeDOM to generate managed Visual C# at run time. What does the following line of code do? var method = new CodeEntryPointMethod(); Select the correct answer. Defines an instance method with a random name. Defines an instance method named EntryPoint. Defines a static method named EntryPoint. Defines an instance method named Main. Defines a static method named Main. Verify the correctness of the statement by placing a mark in the column to the right. Statement The FourthCoffee.Core.dll assembly has 2.1.0.24 as its version number. The number 24 in the version number refers to the build number. Answer

13-1

Module 13
Encrypting and Decrypting Data
Contents:
Module Overview Lesson 1: Implementing Symmetric Encryption Lesson 2: Implementing Asymmetric Encryption Lab: Encrypting and Decrypting the Grades Report Module Review and Takeaways 13-2 13-3 13-15 13-26 13-32

13-2 Encrypting and Decrypting Data

Modu ule Ove erview

It i is a common requirement for f applications to be able to secure info ormation, whe ether it is a ca ase of encrypting files saved to disk k or web reque ests sent over r an untrusted d connection t to other remo ote systems. The Microsoft .NET Framew work provides s a variety of c classes that en nable you to secure s your da ata by usi ing encryption and hashing g. In this module, y you will learn how to imple ement symme etric and asym mmetric encryption and how w to use hashes to gener rate mathema atical represen ntations of your data. You w will also learn how to create and ma anage X509 certificates and d how to use t them in the asymmetric en ncryption proc cess.

Ob bjectives
Aft ter completing this module e, you will be able to: ta by using symmetric encryption. Encrypt dat Encrypt dat ta by using asy cryption. ymmetric enc

Program mming in C# 13-3 3

Lesson 1

Implementi ing Sym mmetric c Encry yption

Symmetric en S ncryption is the process of p performing a cryptographic c transformation of data by y using a algorithm. Sy m mathematical ymmetric encryption is an e established te echnique and is used by ma any a applications to provide a ro obust way of protecting co onfidential dat ta. In this lesson, you will learn I n about severa al .NET Frame ework classes t o secure data that enable applications to b means of e by encryption and hashing.

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Describe symmetric en ncryption. Encrypt a and decrypt da ata by using s symmetric enc cryption. Create dig gital fingerpri ints of data by y using hashe es.

13-4 Encrypting and Decrypting Data

W What Is Sym mmetric Encryption E n?

The name symm metric is derive ed from the fa act that the sa ame secret ke ey is used to e encrypt and de ecrypt the data. Therefore, , when you us se symmetric e encryption, yo ou must keep the secret ke ey secure. To o help improve e the effective eness of symm metric encrypt tion, many sym mmetric encry yption algorit thms also use e an initializat tion vector (IV V) in addition to a secret ke ey. The IV is an n arbitrary blo ock of bytes that helps to ran ndomize the f first encrypted d block of dat ta. The IV mak kes it much m more difficult f for a malicious s user to de ecrypt your da ata.

Ad dvantages a and Disadv vantages of f Symmetric Encryptio on


The following ta able describes s some of the advantages and a disadvant tages of symm metric encrypt tion. A Advantage There is no lim T mit on the am mount of data you can e encrypt. Symmetric alg S gorithms are f fast and consu ume far f fewer system resources tha an asymmetric c a algorithms. Disadvantage e The same key is used to encrypt and de ecrypt the key is comprom mised, anyone e can data. If the k encrypt and decrypt the d data. If you choose e to use a diff ferent secret k key for different data, you could end e up with many m y need to manage. m different secret keys that you

Symmetric algorithms are perfect for quick kly encrypting g large amoun nts of data.

Sy ymmetric Encryption C Classes in the .NET Fra amework


The .NET Frame ework contains a number of classes in the System.Sec curity.Crypto ography name espace, wh hich provide managed m implementations of common s symmetric enc cryption algor rithms, such as a Ad dvanced Encry yption Standard (AES), Data a Encryption S Standard (DES S), and TripleD DES. Each .NET T Fra amework sym mmetric encryp ption class is d derived from t the abstract S SymmetricAlg gorithm base e class. The following ta able describes s the key char racteristics of t the.NET Fram mework encryp ption classes.

A Algorithm

.NET Frame ework Class

Encryption Technique

Block Size S

Key y Size

Programming in C# 13-5

Algorithm DES

.NET Framework Class DESCryptoServiceProvider

Encryption Technique Bit shifting and bit substitution SubstitutionPermutation Network (SPN) Feistel network

Block Size 64 bits

Key Size 64 bits

AES

AesManaged

128 bits

128, 192, or 256 bits 40-128 bits (increments of 8 bits) 128, 192, or 256 bits

Rivest Cipher 2 (RC2)

RC2CryptoServiceProvider

64 bit

Rijndael

RijndaelManaged

SPN

128-256 bits (increments of 32 bits) 64 bit

TripleDES

TripleDESCryptoServiceProvider

Bit shifting and bit substitution

128-192 bits

Each of the .NET Framework encryption classes are known as block ciphers, which means that the algorithm will chunk data into fixed-length blocks and then perform a cryptographic transformation on each block. Note: You can measure the strength of an encryption algorithm by the key size. The higher the number of bits, the more difficult it is for a malicious user trying a large number of possible secret keys to decrypt your data. Additional Reading: For more information about symmetric encryption in the .NET Framework, see the SymmetricAlgorithm Class page at http://go.microsoft.com/fwlink/?LinkID=267877.

13-6 Encrypting and Decrypting Data

En ncrypting Data by Using U Sym mmetric En ncryption

Yo ou can encrypt t data by usin ng any of the s symmetric encryption class ses in the Sy ystem.Securit ty.Cryptograp phy namespa ace. However, these classes only provide managed implementation ns of a particular encryption n algorithm; for example, the AesManag ged class prov vides a ma anaged imple ementation of the AES algorithm. Aside f from encrypting and decrypting data by y using an alg gorithm, the encryption e pro ocess typically y involves the following tas sks: Derive a sec cret key and a an IV from a password p or sa alt. A salt is a random colle ection of bits u used in combinatio on with a passw word to gene erate a secret key and an IV V. A salt makes s it much mor re difficult for a malicio ous user to ra andomly disco over the secret key. Read and w write encrypted data to and d from a stream.

To o help simplify y the encryptio on logic in yo our application ns, the .NET Framework inc cludes a numb ber of other cry yptography classes that you u can use.

Th he Rfc2898DeriveByte es and Cryp ptoStream C Classes


The Rfc2898De eriveBytes cla ass provides an implementa ation of the password-base ed key derivat tion fun nction (PBKDF F2), which com mplies with th he Public-Key Cryptography y Standards (P PKCS). You can use the PB BKDF2 functionality to deriv ve your secret t keys and you ur IVs from a password and d a salt. al Reading: F For more infor rmation about the Rfc2898 8DeriveBytes s class, see the Additiona Rfc c2898DeriveB Bytes Class pag ge at http://g go.microsoft.com/fwlink/?LinkID=267878 8. The CryptoStre eam class is de erived from th he abstract St tream base cla ass in the Sys stem.IO name espace, and it p provides strea aming functionality specific c to reading and writing cry yptographic tr ransformation ns. Additiona al Reading: F For more infor rmation about the CryptoS Stream class, see the Cry yptoStream C Class page at http://go.micr h rosoft.com/fw wlink/?LinkID= =267879.

Sy ymmetrically Encrypting and Dec crypting Da ata


The following st teps describe how to encry ypt and decryp pt data by using the AesManaged class:

Programming in C# 13-7

1.

Create an Rfc2898DeriveBytes object, which you will use to derive the secret key and the IV. The following code example shows how to create an instance of the Rfc2898DeriveBytes class, passing values for the password and salt into the constructor.
var password = "Pa$$w0rd"; var salt = "S@lt"; var rgb = new Rfc2898DeriveBytes(password, Encoding.Unicode.GetBytes(salt));

2.

Create an instance of the encryption class that you want to use to encrypt the data. The following code example shows how to create an AesManaged object.
var algorithm = new AesManaged();

3.

Generate the secret key and the IV from the Rfc2898DeriveBytes object. The following code example shows how to generate the secret key and the IV by using the algorithms KeySize and BlockSize properties.
var rgbKey = rgb.GetBytes(algorithm.KeySize / 8); var rgbIV = rgb.GetBytes(algorithm.BlockSize / 8);

Note: You typically use the algorithms KeySize and BlockSize properties when generating the secret key and the IV, so that the secret key and the IV that you generate are compatible with the algorithm. 4. Create a stream object that you will use to buffer the encrypted or unencrypted bytes. The following code example shows how to create an instance of the MemoryStream class.
var bufferStream = new MemoryStream();

5.

Create either a symmetric encryptor or decryptor depending on whether you want to encrypt or decrypt data. The following code example shows how to invoke the CreateEncryptor method to create an encryptor and how to invoke the CreateDecryptor method to create a decryptor. Both methods accept the secret key and the IV as parameters.
// Create an encryptor object. var algorithm = algorithm.CreateEncryptor(rgbKey, rgbIV); ... // Create a decryptor object. var algorithm = algorithm.CreateDecryptor(rgbKey, rgbIV);

6.

Create a CryptoStream object, which you will use to write the cryptographic bytes to the buffer stream. The following code example shows how to create an instance of the CryptoStream class, passing the bufferStream object, the algorithm object, and the stream mode as parameters.
var cryptoStream = new CryptoStream( bufferStream, algorithm, CryptoStreamMode.Write)

7.

Invoke the Write and FlushFinalBlock methods on the CryptoStream object, to perform the cryptographic transform. The following code example shows how to invoke the Write and FlushFinalBlock methods of the CryptoStream object.
var bytesToTransform = FourthCoffeeDataService.GetBytes(); cryptoStream.Write(bytesToTransform, 0, bytesToTransform.Length); cryptoStream.FlushFinalBlock();

13-8

Encrypting and Decrypting Data

8.

Invoke the Close method on the CryptoStream and the MemoryStream objects, so that the transformed data is flushed to the buffer stream. The following code example shows how to invoke the Close methods on both the CryptoStream and the MemoryStream objects.
cryptoStream.Close(); bufferStream.Close();

Program mming in C# 13-9 9

H Hashing D Data

Hashing is the H e process of g generating a n numerical repr resentation of f your data. Ty ypically, hash algorithms c compute hash hes by mappin ng the binary representatio on of your dat ta to the binary values of a fixed-length h hash. If you use a proven h hash algorithm m, it is conside ered unlikely t that you could d compute the same hash f from two diffe erent pieces of o data. Theref fore, hashes are a considered d a reliable wa ay to generate e a unique d digital fingerp print that can help to ensur re the integrit ty of data. Consider the e C example of th he FourthCoffee.Beverage s service, which sends messag ges to the F FourthCoffee. .Inventory service. When th he FourthCoffe ee.Inventory service s receive es a message, , how do the t two services know k that the message was s not sabotage ed during the e transmission n? You could u use hashes, as s t following steps describe: the 1 1. 2 2. 3 3. Compute e a hash of the e message bef fore the Fourt thCoffee.Beve erage service sends s the mes ssage. Compute e a hash of the e message wh hen the Fourth hCoffee.Inventory service re eceives the message. Compare the two hash hes. If the two hashes are id dentical, the d data has not b been tampered d with. If the data has been modified, the two hashes will not match. m

The .NET Fram T mework provid des a number r of classes in the System.S Security.Cryp ptography namespace, w which encapsulate common hash algorit thms.

H Hash Algor rithms in th he .NET Framework


T following table describ The bes some of th he hash classe es that the .NE ET Framework k provides. .NET Framew work Class SHA512Ma anaged Descriptio on The SHA5 512Managed d class is an im mplementation of the Secure Ha ash Algorithm m (SHA) and is s able to comp pute a 512bit hash. T The .NET Fram mework also includes classe es that implemen nt the SHA1, S SHA256, and SHA384 algor rithms. The HMA ACSHA512 cla ass uses a com mbination of t the SHA512 hash algo orithm and the e Hash-Based d Message Aut thentication Code (HM MAC) to comp pute a 512-bit t hash. The MAC CTripleDES cla ass uses a com mbination of the t TripleDES encryptio on algorithm a and a Message Authenticat tion Code

HMACSHA A512

MACTriple eDES

13-10

Encrypting and Decrypting Data

.NET Framework Class

Description (MAC) to compute a 64-bit hash.

MD5CryptoServiceProvider

The MD5CryptoServiceProvider class is an implementation of the Message Digest (MD) algorithm, which uses block chaining to compute a 128-bit hash. The RIPEMD160Managed class is derived from the MD algorithm and is able to compute a 160-bit hash.

RIPEMD160Managed

Computing a Hash by Using the HMACSHA512 Class


To compute a hash by using the HMACSHA512 class, perform the following steps: 1. Generate a secret key that the hash algorithm will use to hash the data. The sender would need access to the key to generate the hash, and the receiver would need access to the key to verify the hash. Create an instance of the hash algorithm. Invoke the ComputeHash method, passing in a stream that contains the data you want to hash. The ComputeHash method returns a byte array that represents the hash of your data.

2. 3.

The following code example shows how to compute a hash by using the HMACSHA512 class. Hashing Data by Using the HMACSHA512 class
public byte[] ComputeHash(byte[] dataToHash, byte[] secretKey) { using (var hashAlgorithm = new HMACSHA1(secretKey)) { using (var bufferStream = new MemoryStream(dataToHash)) { return hashAlgorithm.ComputeHash(bufferStream); } } }

Additional Reading: For more information about hashing in the .NET Framework, see the Hash Values section on the Cryptographic Services page at http://go.microsoft.com/fwlink/?LinkID=267880.

Programm ming in C# 13-11 1

D Demonstr ration: En ncrypting and Decry ypting Da ata

I this demon In nstration, you will use symm metric encrypt tion to encryp pt and decrypt t a message.

D Demonstra ation Steps


1 1. 2 2. 3 3. Start the MSL-TMG1 vi irtual machine e if it is not already running g. Start the 20483A-SEA A-DEV11-13 v virtual machine. Log on to o Windows 8 as Student with the pass sword Pa$$w0rd. Note: If f necessary, click Switch Us ser to display the list of use ers. 4 4. 5 5. 6 6. 7 7. 8 8. 9 9. Switch to the Windows s 8 Start wind dow. Click Visu ual Studio 20 012. In Micros soft Visual Studio, on the File menu, po oint to Open, and then clic ck Project/So olution. In the Op pen Project dialog box, bro owse to the E: :\Democode\ \FourthCoffe ee.MessageSa afe folder, click Four rthCoffee.Me essageSafe.sln, and then c click Open. In Visual Studio, on the e View menu, , click Task Li ist. In the Tas sk List windo ow, in the Cate egories list, click Commen nts.

1 Double-c 10. click the TODO O: 01: Instant tiate the _alg gorithm obje ect. task. 1 Explain th 11. hat the follow wing code crea ates an instanc ce of the AesManaged cla ass.
this._al lgorithm = new n AesManaged();

1 Double-c 12. click the TODO O: 02: Dispos se of the _alg gorithm object. task. 1 Explain th 13. hat the follow wing code dete ermines wheth her the _algorithm object is not null and then invokes th he Dispose method m to rele ease any resou urces that the e algorithm may have used. .
if (this s._algorithm m != null) { this._algorithm. .Dispose();

13-12

Encrypting and Decrypting Data

14. Double-click the TODO: 03: Derive a Rfc2898DeriveBytes object from the password and salt. task. 15. Explain that the following code creates an instance of the Rfc2898DeriveBytes class by using a password (that the user provides at run time) and salt (hard-coded value in the application).
return new Rfc2898DeriveBytes(password, this._salt);

16. Double-click the TODO: 04: Generate the secret key by using the Rfc2898DeriveBytes object. task. 17. Explain that the following code uses the Rfc2898DeriveBytes object to derive the secret key by using the algorithms key size in bytes.
return passwordHash.GetBytes(this._algorithm.KeySize / 8);

Note: The KeySize property returns the size of the key in bits, so to get the value in bytes, you divide the value by 8. 18. Double-click the TODO: 05: Generate the IV by using the Rfc2898DeriveBytes object. task. 19. Explain that the following code uses the Rfc2898DeriveBytes object to derive the IV by using the algorithms block size in bytes.
return passwordHash.GetBytes(this._algorithm.BlockSize / 8);

Note: The BlockSize property returns the size of the block in bits, so to get the value in bytes, you divide the value by 8. 20. Double-click the TODO: 06: Create a new MemoryStream object. task. 21. Explain that the following code creates an instance of the MemoryStream class, which will be used as a buffer for the transformed data.
var bufferStream = new MemoryStream();

22. Double-click the TODO: 07: Create a new CryptoStream object. task. 23. Explain that the following code creates an instance of the CryptoStream class, which will transform the data and write it to the underlying memory stream.
var cryptoStream = new CryptoStream( bufferStream, transformer, CryptoStreamMode.Write);

24. Double-click the TODO: 08: Write the bytes to the CryptoStream object. task. 25. Explain that the following code writes the transformed data to the underlying memory stream.
cryptoStream.Write(bytesToTransform, 0, bytesToTransform.Length); cryptoStream.FlushFinalBlock();

26. Double-click the TODO: 09: Read the transformed bytes from the MemoryStream object. task.

Programming in C# 13-13

27. Explain that the following code uses the ToArray method to extract the transformed data from the memory stream as a byte array.
var transformedBytes = bufferStream.ToArray();

28. Double-click the TODO: 10: Close the CryptoStream and MemoryStream objects. task. 29. Explain that the following code closes the cryptoStream and bufferStream objects.
cryptoStream.Close(); bufferStream.Close();

30. Double-click the TODO: 11: Use the _algorithm object to create an ICryptoTransform encryptor object. task. 31. Explain that the following code creates an ICryptoTransform object that will encrypt data.
var transformer = this._algorithm.CreateEncryptor(key, iv);

32. Double-click the TODO: 12: Invoke the TransformBytes method and return the encrypted bytes. task. 33. Explain that the following code invokes the TransformBytes helper method, which will use the ICryptoTransform object to encrypt the data.
return this.TransformBytes(transformer, bytesToEncypt);

34. Double-click the TODO: 13: Use the _algorithm object to create an ICryptoTransform decryptor object. task. 35. Explain that the following code creates an ICryptoTransform object that will decrypt data.
var transformer = this._algorithm.CreateDecryptor(key, iv);

36. Double-click the TODO: 14: Invoke the TransformBytes method and return the decrypted bytes. task. 37. Explain that the following code invokes the TransformBytes helper method, which will use the ICryptoTransform object to decrypt the data.
return this.TransformBytes(transformer, bytesToDecypt);

38. On the Build menu, click Build Solution. 39. On the Debug menu, click Start Without Debugging. 40. In the Fourth Coffee Message Safe application, in the Password box, type Pa$$w0rd. 41. In the Message box, type This is my secure message, and then click Save. 42. Close the Fourth Coffee Message Safe application. 43. Open File Explorer and browse to the E:\Democode\Data folder. 44. Double-click protected_message.txt, and then view the encrypted text in Notepad. 45. Close Notepad, and then close File Explorer. 46. In Visual Studio, on the Debug menu, click Start Without Debugging. 47. In the Fourth Coffee Message Safe application, in the Password box, type Pa$$w0rd, and then click Load.

13-14

Encrypting and Decrypting Data

48. Verify that the Message box now displays the text This is my secure message. 49. Close the Fourth Coffee Message Safe application. 50. Close Visual Studio 2012.

Programm ming in C# 13-15 5

Lesson 2

Implementi ing Asy ymmetr ric Encr ryption

Asymmetric e A encryption is the process of f performing a cryptograph hic transforma ation of data b by using an ncryption algo a asymmetric en orithm and a combination of public and d private keys. . In this lesson, you will learn I n about the classes and too ols that you ca an use to implement asymm metric e encryption in your applicat tions.

L Lesson Ob bjectives
A After complet ting this lesson, you will be able to: Describe asymmetric e encryption. Encrypt a and decrypt da ata by using a asymmetric en ncryption. Create an nd manage X5 509 certificate es. Manage encryption e ke eys in your app plications.

13-16

Encryp pting and Decrypting Data

W What Is Asy ymmetric Encryptio on?

Un nlike symmetr ric encryption, , where one se ecret key is us sed to perform m both the en ncryption and the de ecryption, asym mmetric encry yption uses a public key to perform the encryption an nd a private ke ey to pe erform the dec cryption. cally linked, in Note: The e public and p private keys ar re mathematic n that the priv vate key is use ed to derive the pu ublic key. How wever, you can nnot derive a private key fr rom a public k key. Also, you can only decryp pt data by usin ng the private e key that is lin nked to the public key that t was used to encrypt the data a. t uses asymme etric encryptio on, the public c key is made available to any application n that In a system that req quires the ability to encrypt data. Howev ver, the privat te key is kept safe and is on nly distributed d to ap pplications tha at require the ability to decrypt the data. . For example, HTTPS uses asymmetric encryption to encrypt and d decrypt the browsers session key when establishing a secure connection betwee en the bro owser and the e server. Note: You u can also use e asymmetric algorithms a to sign data. Sig gning is the process of ge enerating a dig gital signature e so that you can ensure th he integrity of f the data. Wh hen signing data, you use th he private key y to perform th he signing and then use the public key t to verify the data.

Ad dvantages a and Disadv vantages of f Asymmetr ric Encryption


The following ta able describes s some of the advantages and a disadvant tages of asymmetric encryp ption.

Programming in C# 13-17

Advantage Asymmetric encryption relies on two keys, so it is easier to distribute the keys and to enforce who can encrypt and decrypt the data.

Disadvantage With asymmetric encryption, there is a limit on the amount of data that you can encrypt. The limit is different for each algorithm and is typically proportional with the key size of the algorithm. For example, an RSACryptoServiceProvider object with a key length of 1,024 bits can only encrypt a message that is smaller than 128 bytes. Asymmetric algorithms are very slow in comparison to symmetric algorithms.

Asymmetric algorithms use larger keys than symmetric algorithms, and they are therefore less susceptible to being cracked by using brute force attacks.

Asymmetric encryption is a powerful encryption technique, but it is not designed for encrypting large amounts of data. If you want to encrypt large amounts of data with asymmetric encryption, you should consider using a combination of asymmetric and symmetric encryption. Best Practice: To encrypt data by using asymmetric and symmetric encryption, perform the following steps: 1. 2. 3. Encrypt the data by using a symmetric algorithm, such as the AesManaged class. Encrypt the symmetric secret key by using an asymmetric algorithm. Create a stream and write bytes for the following: The length of the IV The length of the encrypted secret key The IV The encrypted secret key The encrypted data

To decrypt, simply step through the stream extracting the data, decrypt the symmetric encryption key, and then decrypt the data.

Asymmetric Encryption Classes in the .NET Framework


The .NET Framework contains a number of classes in the System.Security.Cryptography namespace, which enable you to implement asymmetric encryption and signing. Each .NET Framework asymmetric class is derived from the AsymmetricAlgorithm base class. The following list describes some of these classes: RSACryptoServiceProvider. This class provides an implementation of the RSA algorithm, which is named after its creators, Ron Rivest, Adi Shamir, and Leonard Adleman. By default, the RSACryptoServiceProvider class supports key lengths ranging from 384 to 512 bits in 8-bit increments, but optionally, if you have the Microsoft Enhanced Cryptographic Provider installed, the RSACryptoServiceProvider class will support keys up to 16,384 bits in length. You can use the RSACryptoServiceProvider class to perform both encryption and signing.

13-18

Encrypting and Decrypting Data

DSACryptoServiceProvider. This class provides an implementation of the Digital Signature Algorithm (DSA) algorithm and supports keys ranging from 512 to 1,024 bits in 64-bit increments. Although the RSACryptoServiceProvider class supports both encryption and signing, the DSACryptoServiceProvider class only supports signing.

. Additional Reading: For more information about asymmetric encryption in the .NET Framework, see the Public-Key Encryption section on the Cryptographic Services page at http://go.microsoft.com/fwlink/?LinkID=267881.

Programm ming in C# 13-19 9

E Encryptin g Data by y Using As symmetric c Encryption

You can encry Y ypt your data asymmetrically by using th he RSACrypto oServiceProv vider class in t the S System.Secur rity.Cryptogr raphy namesp pace.

E Encrypting Data by Us sing the RS SACryptoSe erviceProvid der Class


The RSACryp T ptoServicePro ovider class provides a num mber of memb bers that enab ble you to imp plement a asymmetric en ncryption functionality in your y applicatio ons, including g the ability to o import and e export key i information and encrypt an nd decrypt da ata. You can creat Y te an instance of the RSACr ryptoService eProvider clas ss by using the e default cons structor. If y choose th you his approach, the RSACryp ptoServicePro ovider class will w generate a set of public and private k keys. The following code example shows how to create an instance of th T he RSACrypto oServiceProv vider class by u using the defa ault construct tor. I Instantiating g the RSACryp ptoServicePr rovider Class
var rsaProv vider = new RSACryptoServiceProvide er();

After you hav A ve created an i instance of th he RSACrypto oServiceProvi ider class, you u can then use e the Encrypt t a Decrypt methods to p and protect your d data. The following code example shows how you can use t T the Encrypt a and Decrypt m methods to p protect the c contents of a string variable. E Encrypting and Decryptin ng Data by Using U the RSA ACryptoServiceProvider C Class
var plainTe ext = "hello o world"; var rawByte es = Encodin ng.Default.GetBytes(plai inText); var decrypt tedText = st tring.Empty; using (var rsaProvider r = new RSACryptoService eProvider()) ) { var use eOaepPadding g = true; var enc cryptedBytes s = rsaProvider.Encrypt( (rawBytes, useOaepPaddi u ng); var dec cryptedBytes s = rsaProvider.Decrypt( (encryptedBy ytes, useOaepPadding); decrypt tedText = En ncoding.Default.GetStrin ng(decrypted dBytes); } // The decr ryptedText variable v will now contai in " hello world" w

13-20

Encrypting and Decrypting Data

Note: You use the useOaepPadding parameter to determine whether the Encrypt and Decrypt methods use Optimal Asymmetric Encryption Padding (OAEP). If you pass true, the methods use OAEP, and if you pass false, the methods use PKCS#1 v1.5 padding. Typically, applications do not encrypt and decrypt data in the scope of the same RSACryptoServiceProvider object. One application may perform the encryption, and then another performs the decryption. If you attempt to use different RSACryptoServiceProvider objects to perform the encryption and decryption, without sharing the keys, the Decrypt method will throw a CryptographicException exception. The RSACryptoServiceProvider class exposes members that enable you to export and import the public and private keys. The following code example shows how to instantiate different RSACryptoServiceProvider objects and use the ExportCspBlob and ImportCspBlob methods to share the public and private keys. Importing and Exporting Keys
var keys = default(byte[]); var exportPrivateKey = true; using (var rsaProvider = new RSACryptoServiceProvider()) { keys = rsaProvider.ExportCspBlob(exportPrivateKey); // Code to perform encryption. } var decryptedText = string.Empty; using (var rsaProvider = new RSACryptoServiceProvider()) { rsaProvider.ImportCspBlob(keys); // Code to perform decryption. }

Note: The exportPrivateKey parameter instructs the ExportCspBlob method to include the private key in the return value. If you pass false into the ExportCspBlob method, the return value will not contain the private key. If you try to decrypt data without a private key, the Common Language Runtime (CLR) will throw a CryptographicException exception. Instead of maintaining and persisting keys in your application, you can use the public and private keys in an X509 certificate, stored in the certificate store on the computer that is running your application. Additional Reading: For more information about the RSACryptoServiceProvider class, see the RSACryptoServiceProvider Class page at http://go.microsoft.com/fwlink/?LinkID=267882.

Programm ming in C# 13-21 1

C Creating a and Mana aging X509 Certifica ates

An X509 certificate is a digital document A t that contain ns information n, such as the name of the organization o certificate sto t that is supplyi ing the data. X X509 certifica ates are norma ally stored in c ores. In a typic cal Windows i installation, th here are user account, a servi ice account, and local computer machine certificate stores. X509 certificates can also c X contain public c and private k keys, which yo ou can use in the asymmetric encryption n p process. You c can create and d manage you ur X509 certif ficates by usin ng the tools th hat Windows and a the .NET F Framework pr rovide.

C Creating a Certificate by Using M MakeCert


MakeCert is a certificate cre M eation tool th hat the .NET Framework pro ovides. You ca an access the tool by using t Visual Studio command the d prompt. The e MakeCert to ool provides a number of command-line e switches t that enable yo ou to configure the X509 certificate to m meet the requirements of your applicatio on. e switches. T following table describ The bes some of th he MakeCert c command-line Switch -n -a -pe -r -sr -ss -sky Description This enables you to o specify the n name of the ce ertificate. This enables you to o specify the a algorithm that t the certificat te uses. This enables you to o create a cert tificate that allows you to export the priv vate key. This enables you to o create a self-signed certifi icate. This enables you to o specify the n name of the ce ertificate store e where the M MakeCert tool mport the generated certific cate. will im This enables you to o specify the n name of the co ontainer in th he certificate store s where will import the generated c certificate. the MakeCert tool w This enables you to o specify the ty ype of key tha at the certifica ate will contain.

The following code example shows how you can use t T the MakeCert t command-line tool to gen nerate a selfs signed certific cate, which co ontains both a public and a private key.

13-22

Encrypting and Decrypting Data

MakeCert Example
makecert -n "CN=FourthCoffee" -a sha1 -pe -r -sr LocalMachine -ss my -sky exchange

Additional Reading: For more information about MakeCert, see the Makecert.exe (Certificate Creation Tool) page at http://go.microsoft.com/fwlink/?LinkID=267883.

Managing X509 Certificates by Using the Microsoft Management Console Certificates Snap-in
The Microsoft Management Console (MMC) Certificates snap-in enables you to manage any X509 certificates installed in the context of your user account, service account, or local computer. To open a certificate store by using the MMC snap-in, perform the following steps: 1. 2. 3. 4. 5. Log on as an administrator. If you log on without administrative privileges, you will only be able to view certificates in your user account certificate store. In the Windows 8 Start window, use search to find mmc.exe, and then click mmc.exe. In the MMC window, on the File menu, click Add/Remove Snap-in. In the Add or Remove Snap-ins dialog box, in the Available snap-ins list, click Certificates, and then click Add. In the Certificates snap-in dialog box, click either My user account, Service account, or Computer account, and then perform one of the following steps: a. b. i. ii. c. 6. If you chose My user account, click Finish. If you chose Service account, click Next, and then perform the following steps: In the Select Computer dialog box, click Next. In the Certificates snap-in dialog box, in the Service account list, click the service account you want to manage, and then click Finish. If you chose Computer account, click Next, and then click Finish.

In the Add or Remove Snap-ins dialog box, repeat steps 4 and 5 if you want to add additional certificate stores to your session, and then click OK.

After you have opened one or more certificate stores, you can perform any of the following tasks: View the properties that are associated with any X509 certificate in any of the certificate stores, such as Personal or Trusted Root Certificate Authorities stores. Export an X509 certificate from a certificate store to the file system. Manage the private keys that are associated with an X509 certificate. Issue a request to renew an existing X509 certificate.

Additional Reading: For more information about managing certificates, see the Working with Certificates page at http://go.microsoft.com/fwlink/?LinkID=267884.

Programm ming in C# 13-23 3

M Managing g Encrypti ion Keys

The .NET Fram T mework provid des the Syste em.Security.C Cryptography y.X509Certifi icates namesp pace, which c contains a number of classe es that enable e you to use X509 X certificat tes and their k keys in your applications. T These classes include the fo ollowing: X509Stor re. This class e enables you to access a cer rtificate store and perform operations, su uch as finding an n X509 certific cate with a pa articular name e. X509Cert tificate2. This class enable es you create a an in-memory y representation of an X509 9 certificate that curre ently exists in a certificate s store. When yo ou have instantiated an X5 509Certificate e2 object, you can t then use its members m to access information, such as th he X509 certif ficates public c and private keys. PublicKe ey. This class e enables you to o manipulate the various pieces of metadata that are associated with an X X509 certificates public key y, such as the public keys v value.

The following code example shows how to use the X5 T 509Store and d X509Certificate2 classes to e enumerate the personal ce ertificate store e on the local machine. E Enumerating g a Certificate e Store
var store = new X509St tore(StoreName.My, Store eLocation.Lo ocalMachine); var certifi icate = defa ault(X509Certificate2); var certifi icateName = "CN=FourthCoffee"; store.Open( (OpenFlags.R ReadOnly); foreach (va ar storeCert tificate in store.Certif ficates) { if (stor reCertificat te.SubjectName.Name == c certificateN Name) { certi ificate = st toreCertificate; conti inue; } } store.Close e();

After you hav A ve created an X X509Certifica ate2 object, y you can use its members to o determine w whether the X X509 certificate contains ei ither a public or private key y. The followin ng list describ bes some of th he members y can use: you

13-24

Encrypting and Decrypting Data

HasPrivateKey. This property enables you to determine whether the X509 certificate contains a private key. FriendlyName. This property enables you to get the friendly name that is associated with the X509 certificate. GetPublicKeyString. This method enables you to extract the public key that the X509 certificate contains as a string value. PublicKey. This property enables you to get the public key that the X509 certificate contains as a PublicKey object. PrivateKey. This property enables you to get the private key that the X509 certificate contains as an AsymmetricAlgorithm object.

You can use the PublicKey and PrivateKey properties of the X509Certificate2 class to create an instance of the RSACryptoServiceProvider class. The following code example shows how you can use the PublicKey and PrivateKey properties to create an instance of the RSACryptoServiceProvider class.. Instantiating the RSACryptoServiceProvider Class
var certificate = new X509Certificate2(); // Code to set the public and private keys. // Create an RSA encryptor. var rsaEncryptorProvider = (RSACryptoServiceProvider)certificate.PublicKey.Key; // Create an RSA decryptor. var rsaDecryptorProvider = (RSACryptoServiceProvider)certificate.PrivateKey;

Additional Reading: For more information about managing encryption keys in your application, see the System.Security.Cryptography.X509Certificates Namespace page at http://go.microsoft.com/fwlink/?LinkID=267885.

Programm ming in C# 13-25 5

D Demonstr ration: En ncrypting and Decry ypting Gra ade Reports Lab

I this demon In nstration, you will learn abo out the tasks t that you will p perform in the e lab for this module. m

13-26

Encryp pting and Decrypting Data

Lab: E Encrypting and d Decry ypting t the Gra ades Re eport

Sc cenario
Yo ou have been asked to upda ate the Grade es application to ensure tha at reports are secure when they are sto ored on a user r's computer. You decide to o use asymme etric encryptio on to protect the report as it is ge enerated, befo ore it is written n to disk. Adm ministrative sta aff will need t to merge repo orts for each c class into on ne document, so you decide e to develop a separate application that generates a combined c rep port and pri ints it.

Ob bjectives
Aft ter completing this lab, you u will be able to: ta by using asy ymmetric enc cryption. Encrypt dat Decrypt dat ta.

timated Time: : 75 minutes Est Virtual Mac chine: 20483A A-SEA-DEV11-13, MSL-TMG G1 User Name: Student P Password: Pa$$w0rd

Programming in C# 13-27

Exercise 1: Encrypting the Grades Report


Scenario
In this exercise, you will update the reporting functionality to encrypt the report as it is generated, but before it is saved to disk. First, you will create an asymmetric certificate by using a prewritten batch file. The batch file uses the MakeCert tool that ships with the Windows Software Development Kit (SDK). You will create a self-signed certificate named Grades using the SHA-1 hash algorithm and store it in the LocalMachine certificate store. You will then write code in the Grades application to retrieve the certificate by looping through the certificates in the LocalMachine store and checking the name of the certificate against the name that is stored in the App.Config file. Next, you will use the classes that are provided in the System.Security.Cryptography and System.Security.Cryptography.X509Certificates namespaces to write the EncryptWithX509 method in the Grades.Utilities.WordWrapper class. You will get the public key from the certificate that you created and use it to create an instance of the RSAPKCS1KeyExchangeFormatter class. You will use this to encrypt the data for the report and then return the encrypted buffered data to the calling method as a byte array. You will then write code in the EncryptAndSaveToDisk method to write the returned data to the file that the user specifies. Finally, you will build and test the application and verify that the reports are now encrypted. The main tasks for this exercise are as follows: 1. Create an asymmetric certificate 2. Retrieve the Grade certificate 3. Encrypt the data 4. Write the encrypted data to disk 5. Build and test the application

X Task 1: Create an asymmetric certificate


1. 2. 3. 4. Start the MSL-TMG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-13 virtual machine and log on as Student with the password Pa$$w0rd. Start Visual Studio, and then open the Grades.sln solution from the E:\Labfiles\Starter\Exercise 1 folder. Set the following projects to start without debugging at startup: a. b. 5. 6. 7. Grades.Web Grades.WPF

In the Grades.Utilities project, review the contents of the CreateCertificate.cmd file. In a command window running as Administrator, navigate to the E:\Labfiles\Starter\Exercise 1\Grades.Utilities folder and then run CreateCertificate.cmd. Verify that the command returns a success message, and then close the command window.

13-28

Encrypting and Decrypting Data

X Task 2: Retrieve the Grade certificate


1. 2. 3. In the Grades.Utilities project, in the WordWrapper class, locate the GetCertificate method. Add code to this method to loop through the certificates in the store.Certificates collection. Inside the loop, if the SubjectName.Name property matches the _certificateSubjectName variable, return the certificate to the calling method.

X Task 3: Encrypt the data


1. 2. In the Grades.Utilities project, in the WordWrapper class, locate the EncryptWithX509 method. Add code to this method to get the public key from the X509 certificate, cast it to a RSACryptoServiceProvider object, and store it in a variable named provider. Note: You use the PublicKey.Key property of a certificate to retrieve the public key. 3. In the EncryptWithX509 method, add code to create an instance of the AesManaged encryption class named algorithm. Enclose this line of code in a using statement and add a closing brace at the end of the method. Add code to create an instance of the MemoryStream class to hold the unencrypted data. Enclose this line of code in a using statement and add a closing brace at the end of the method. Add the following code to create an AES encryptor based on the key and IV.
using (var encryptor = algorithm.CreateEncryptor()) { var keyFormatter = new RSAPKCS1KeyExchangeFormatter(provider); var encryptedKey = keyFormatter.CreateKeyExchange(algorithm.Key, algorithm.GetType());

4. 5.

6. 7.

Add a closing brace for the using statement at the end of the method. Add the following code to create byte arrays to get the length of the encryption key and IV.
var keyLength = BitConverter.GetBytes(encryptedKey.Length); var ivLength = BitConverter.GetBytes(algorithm.IV.Length);

8.

Add code to write the following data to the unencrypted memory stream object by using the Write method of the MemoryStream instance. a. b. c. d. e. The length of the secret key. The length of the IV. The encrypted secret key. The IV. The encrypted data.

9.

Add code to create an instance of a CryptoStream object, passing the unencrypted memory stream, the AES encryptor, and the CryptoStreamMode.Write constant as parameters. Enclose this line of code in a using statement and add a closing brace at the end of the method.

10. Add code to call the Write and FlushFinalBlock methods of the CryptoStream object to write all the data to the memory stream. 11. Add code to return the encrypted buffered data to the calling method.

Programming in C# 13-29

X Task 4: Write the encrypted data to disk


1. In the Grades.Utilities project, in the WordWrapper class, in the EncryptAndSaveToDisk method, add code to write the encrypted bytes to the file path passed to the method.

X Task 5: Build and test the application


1. 2. 3. 4. 5. 6. Build the solution and resolve any compilation errors. Run the application. Log on as vallee with a password of password99. Generate grade reports for George Li and Kevin Liu, saving each report in the E:\Labfiles\Reports folder. Close the application, and then close the solution. Attempt to open one of the reports that you created in the previous step by using Internet Explorer and Notepad.

Results: After completing this exercise, you should have updated the Grades application to encrypt generated reports.

13-30

Encrypting and Decrypting Data

Exercise 2: Decrypting the Grades Report


Scenario
In this exercise, you will create a separate utility to enable users to print reports. Users will be able to select a folder that contains encrypted reports, and the application will then generate one combined report and send it to the default printer. First, you will use the classes that are provided in the System.Security.Cryptography and System.Security.Cryptography.X509Certificates namespaces to write the DecryptWithX509 method in the SchoolReports.WordWrapper class. You will get the private key from the certificate and use it to create an instance of the RSACryptoServiceProvider class. You will use this to decrypt the data from the individual reports and then return the decrypted data to the calling method as a byte array. Finally, you will build and test the application and verify that a printed version of the composite report has been generated. The main tasks for this exercise are as follows: 1. Decrypt the data 2. Build and test the solution

X Task 1: Decrypt the data


1. 2. 3. In Visual Studio, open the School-Reports.sln solution from the E:\Labfiles\Starter\Exercise 2 folder. In the WordWrapper class, locate the DecryptWithX509 method. Add code to this method to get the private key from the X509 certificate, cast it to a RSACryptoServiceProvider object, and store it in a variable named provider. Note: You can use the PrivateKey property of a certificate to retrieve the private key. 4. In the DecryptWithX509 method, add code to create an instance of the AesManaged encryption class named algorithm. Enclose this line of code in a using statement and add a closing brace at the end of the method. Add code to create an instance of the MemoryStream class, passing the byte array that the method received as a parameter. Enclose this line of code in a using statement and add a closing brace at the end of the method. Add the following code to create byte arrays to get the length of the encryption key and IV.
var keyLength = new byte[4]; var ivLength = new byte[4];

5.

6.

7. 8. 9.

Add code to read the key and IV lengths from index 0 in the memory stream and then convert the two lengths to integers. Add code to determine the starting position and length of the encrypted data. Add code to create byte arrays to store the encrypted key, the IV, and the encrypted data.

10. Add code to read the key, IV, and encrypted data from the memory stream and store them in the byte arrays that you have just created. 11. Add code to decrypt the encrypted AES managed key by calling the Decrypt method of the provider object.

Programming in C# 13-31

12. Add code to create a new instance of the MemoryStream class to store the decrypted data. Enclose this line of code in a using statement and add a closing brace at the end of the method. 13. Add code to create an AES decryptor object, passing the decrypted key and the IV as parameters. Enclose this line of code in a using statement and add a closing brace at the end of the method. 14. Add code to create an instance of a CryptoStream object, passing the memory stream for the decrypted data, the AES decryptor, and the CryptoStreamMode.Write constant as parameters. Enclose this line of code in a using statement and add a closing brace at the end of the method. 15. Add code to call the Write and FlushFinalBlock methods of the CryptoStream object to write all of the data to the memory stream. 16. Add code to return the decrypted buffered data to the calling method.

X Task 2: Build and test the solution


1. 2. 3. 4. Build the solution, and then resolve any compilation errors. Run the application, and then print a composite report that contains the two reports that you generated earlier. Save the .oxps file in the E:\Labfiles\Reports\ClassReport folder. Close the application, close the solution, and then close Visual Studio. Open the composite report in the XPS Reader and verify that the data has printed correctly.

Results: After completing this exercise, you should have a composite unencrypted report that was generated from the encrypted reports.

13-32

Encryp pting and Decrypting Data

Modu ule Revi iew and d Takea aways

M Module Revie ew
In this module, y you learned how h to implem ment symmetric and asymm metric encrypt tion and how to use hashes to gener rate mathema atical represen ntations of your data. Test Your Know wledge Q Question F Fourth Coffee e wants you to o implement an encryptio on utility that can encrypt and d decrypt large image files. E Each image w will be more th han 200 meg gabytes (MB) in size. F Fourth Coffee e envisages th hat only a sma all internal te eam will use this tool, so co ontrolling w who can encry ypt and decry ypt the data i is not a conce ern. Which of f the following te echniques will you choose e? S Select the cor rrect answer. Symm metric encryption Asymm metric encryption Hashin ng Ve erify the correc ctness of the statement by placing a ma ark in the column to the rig ght. S Statement Is the followin I ng statement true or false? Asymmetric e encryption uses a p public key to encrypt data. Answer

Programm ming in C# 13-33 3

Cour rse Eval luation

Y Your evaluatio on of this cou urse will help M Microsoft und derstand the q quality of your r learning exp perience. P Please work w with your train ning provider to access the course evalua ation form. Microsoft will keep your an M nswers to this survey private e and confide ential and will use your resp ponses to i improve your future learnin ng experience e. Your open a and honest fe eedback is valu uable and app preciated.

MCT USE ONLY. STUDENT USE PROHIBITED


L01-1

Module 01: Review of Visual C# Syntax

Lab: Developing the Class Enrollment Application


Exercise 1: Implementing Edit Functionality for the Students List
X Task 1: Detect whether the user has pressed the Enter key
1. 2. 3. Start the MSL-TMG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-01 virtual machine. Log on to Windows 8 as Student with the password Pa$$w0rd. Note: If necessary, click Switch User to display the list of users. 4. 5. 6. 7. 8. 9. Switch to the Windows 8 Start window. Click Visual Studio 2012. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click School.sln, and then click Open. In Solution Explorer, expand School, and then expand MainWindow.xaml. Double-click MainWindow.xaml.cs.

10. In Visual Studio, on the View menu, click Task List. 11. In the Task List window, in the Categories list, click Comments.

12. Double-click the TODO: Exercise 1: Task 1a: If the user pressed Enter, edit the details for the currently selected student task. 13. In the code editor, click at the beginning of the comment line, press Enter, and in the blank space above the comment, type the following code:
switch (e.Key) {

14. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
case Key.Enter: Student student = this.studentsList.SelectedItem as Student;

15. After all the comments in this method, type the following code:
break; }

MCT USE ONLY. STUDENT USE PROHIBITED

L01-2 Programming in Visual C#

X Task 2: Initialize the StudentForm window and populate it with the details of the currently selected student
1. 2.

In the Task List window, double-click the TODO: Exercise 1: Task 2a: Use the StudentsForm to display and edit the details of the student task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
StudentForm sf = new StudentForm();

3. 4.

In the Task List window, double-click the TODO: Exercise 1: Task 2b: Set the title of the form and populate the fields on the form with the details of the student task.

In the code editor, click at the end of the comment line, press Enter, and then type the following code:
sf.Title = "Edit Student Details"; sf.firstName.Text = student.FirstName; sf.lastName.Text = student.LastName; sf.dateOfBirth.Text = student.DateOfBirth.ToString("d");

X Task 3: Display the StudentForm window and copy the updated student details entered back to the Student object
1. 2. In the Task List window, double-click the TODO: Exercise 1: Task 3a: Display the form task.

In the code editor, click at the end of the comment line, press Enter, and then type the following code:
if (sf.ShowDialog().Value) {

3.

After all the comments in this method, add the following code:
}

4. 5.

In the Task List window, double-click the TODO: Exercise 1: Task 3b: When the user closes the form, copy the details back to the student task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
student.FirstName = sf.firstName.Text; student.LastName = sf.lastName.Text; student.DateOfBirth = DateTime.Parse(sf.dateOfBirth.Text);

6. 7. 8.

In the Task List window, double-click the TODO: Exercise 1: Task 3c: Enable saving (changes are not made permanent until they are written back to the database) task. In the code editor, click at the end of the comment line, press Enter, and then type the following code: saveChanges.IsEnabled = true;

X Task 4: Run the application and verify that the edit functionality works as expected
1. On the Build menu, click Build Solution.

MCT USE ONLY. STUDENT USE PROHIBITED


L01-3

2. 3.

On the Debug menu, click Start Without Debugging. Verify that the application starts and displays the initial list of students. The initial students list should look like this:

FIGURE 01.1: THE INITIAL STUDENTS LIST 4. 5. Click the row containing the name Kevin Liu.

Press Enter and verify that the Edit Student Details window appears and displays the correct details: The Edit Student Details window should look similar to the following:

FIGURE 01.2: EDIT STUDENT DETAILS FORM 6. 7. 8. In the Last Name text box, delete the existing contents, type Cook, and then click OK.

Verify that Liu has changed to Cook in the students list, and that the Save Changes button is now enabled. Close the application.

X Task 5: Use the Visual Studio Debugger to step through the code.
1. 2. 3.

In Visual Studio, in the Task List window, double-click the TODO: Exercise 1: Task 2b: Set the title of the form and populate the fields on the form with the details of the student task.

In the following line of code, right-click the word Title in sf.Title = "Edit Student Details";, point to Breakpoint, and then click Insert Breakpoint. On the Debug menu, click Start Debugging.

MCT USE ONLY. STUDENT USE PROHIBITED

L01-4 Programming in Visual C#

4. 5. 6. 7. 8. 9.

Click the row containing the name George Li, and then press Enter. When Visual Studio enters break mode, in the bottom left window, click the Watch 1 tab. In the Watch 1 window, click below Name to create a blank row. In the Name column, type sf.Title, and then press Enter. In the Watch 1 window, click below sf.Title to create a blank row. Type sf.firstName.Text,and then press Enter.

10. In the Watch 1 window, click below sf.firstName.Text to create a blank row. 11. Type sf.lastName.Text, and then press Enter. 12. In the Watch 1 window, click below sf.lastName.Text to create a blank row. 13. Type sf.dateOfBirthText, and then press Enter. 14. On the Debug menu, click Step Over. 15. Repeat step 14 three times. 16. In the bottom middle window, click the Immediate Window tab. 17. In the Immediate Window, type sf.firstName.Text, and then press Enter. 18. Verify that "George" is displayed.

19. In the Watch 1 window, in the sf.firstName.Text row, right-click the Value field, and then click Edit Value. 20. Type "Dominik" and press Enter. 21. In the Immediate Window, type sf.lastName.Text, and then press Enter. 22. Verify that "Li" is displayed 23. Type sf.lastName.Text = "Dubicki";, and then press Enter.

24. In the Watch 1 window, in the sf.lastName.Text row, verify that the Value column has changed to "Dubicki". 25. On the Debug menu, click Continue. 26. Verify that the Edit Student Details form contains the information in the following table: Field First Name Last Name Date of Birth 27. Close the application. 28. In Visual Studio, on the Debug menu, click Delete All Breakpoints. 29. In the Microsoft Visual Studio dialog box, click Yes. 30. On the File menu, click Close Solution. 31. In the Microsoft Visual Studio dialog box, click Yes. Value Dominik Dubicki 8/10/2005

MCT USE ONLY. STUDENT USE PROHIBITED


L01-5

Results: After completing this exercise, users will be able to edit the details of a student.

MCT USE ONLY. STUDENT USE PROHIBITED

L01-6 Programming in Visual C#

Exercise 2: Implementing Insert Functionality for the Students List


X Task 1: Add logic to the key down method to detect if the Insert key has been pressed.
1. 2. 3. 4. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click School.sln, and then click Open. In the Task List window, double-click the TODO: Exercise 2: Task 1a: If the user pressed Insert, add a new student task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
case Key.Insert:

X Task 2: Initialize the student form


1. 2.

In the Task List window, double-click the TODO: Exercise 2: Task 2a: Use the StudentsForm to get the details of the student from the user task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
sf = new StudentForm();

3. 4.

In the Task List window, double-click the TODO: Exercise 2: Task 2b: Set the title of the form to indicate which class the student will be added to (the class for the currently selected teacher) task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
sf.Title = "New Student for Class " + teacher.Class;

X Task 3: Display the StudentForm window and enable the user to provide the details of the new student
1. 2. In the Task List window, double-click the TODO: Exercise 2: Task 3a: Display the form and get the details of the new student task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
if (sf.ShowDialog().Value) {

3.

After all the comments in this method, add the following code:
} break;

4. 5.

In the Task List window, double-click the TODO: Exercise 2: Task 3b: When the user closes the form, retrieve the details of the student from the form and use them to create a new Student object task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:

MCT USE ONLY. STUDENT USE PROHIBITED


L01-7

Student newStudent = new Student(); newStudent.FirstName = sf.firstName.Text; newStudent.LastName = sf.lastName.Text; newStudent.DateOfBirth = DateTime.Parse(sf.dateOfBirth.Text);

X Task 4: Assign the new student to a class and enable the user to save the details of the new student
1. 2. In the Task List window, double-click the TODO: Exercise 2: Task 4a: Assign the new student to the current teacher task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
this.teacher.Students.Add(newStudent);

3. 4.

In the Task List window, double-click the TODO: Exercise 2: Task 4b: Add the student to the list displayed on the form task.

In the code editor, click at the end of the comment line, press Enter, and then type the following code:
this.studentsInfo.Add(newStudent);

5. 6.

In the Task List window, double-click the TODO: Exercise 2: Task 4c: Enable saving (changes are not made permanent until they are written back to the database) task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
saveChanges.IsEnabled = true;

X Task 5: Run the application and verify that the insert functionality works as expected
1. 2. 3. 4. 5. 6. 7. 8. 9. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging. Verify that the application starts and displays the initial list of students. Click the row containing the name Kevin Liu. Press Insert and verify that the new student window appears: In the First Name text box, type Darren. In the Last Name text box, type Parker. In the Date of Birth text box, type 02/03/2006, and then click OK.

Verify that Darren Parker has been added to the students list, and that the Save Changes button is now enabled. Note: The ID of any new student will be 0 until they are saved to the database.

10. Close the application. 11. On the File menu, click Close Solution.

MCT USE ONLY. STUDENT USE PROHIBITED

L01-8 Programming in Visual C#

Results: After completing this exercise, users will be able to add new students to a class.

MCT USE ONLY. STUDENT USE PROHIBITED


L01-9

Exercise 3: Implementing Delete Functionality for the Students List

X Task 1: Add logic to the key down method to detect if the Delete key has been pressed.
1. 2. 3. 4. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 3, click School.sln, and then click Open. In the Task List window, double-click the TODO Exercise: 3: Task 1a: If the user pressed Delete, remove the currently selected student task.

In the code editor, click at the end of the comment line, press Enter, and then type the following code:
case Key.Delete: student = this.studentsList.SelectedItem as Student;

X Task 2: Prompt the user to confirm that they want to remove the selected student from the class
1. 2.

In the Task List window, double-click the TODO: Exercise 3: Task 2a: Prompt the user to confirm that the student should be removed task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
MessageBoxResult response = MessageBox.Show( string.Format("Remove {0}", student.FirstName + " " + student.LastName), "Confirm", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No);

X Task 3: Remove the student and enable the user to save the changes
1. 2.

In the Task List window, double-click the TODO: Exercise 3: Task 3a: If the user clicked Yes, remove the student from the database task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
if (response == MessageBoxResult.Yes) { this.schoolContext.Students.DeleteObject(student);

3.

After the final comment in this method, type the following code:
} break;

4. 5.

In the Task List window, double-click the TODO: Exercise 3: Task 3b: Enable saving (changes are not made permanent until they are written back to the database) task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
saveChanges.IsEnabled = true;

X Task 4: Run the application and verify that the delete functionality works as expected
1. On the Build menu, click Build Solution.

MCT USE ONLY. STUDENT USE PROHIBITED

L01-10 Programming in Visual C#

2. 3. 4. 5. 6. 7. 8. 9.

On the Debug menu, click Start Without Debugging. Verify that the application starts and displays the initial list of students. Click on the drop-down menu containing the text Esther Valle: Class 3C. Click the list item containing the text David Waite : Class 4B. Click the row containing the name Jon Orton. Press Delete and verify that the confirmation prompt appears.

In the Confirm dialog box, click Yes, verify that Jon Orton is removed from the students list, and then verify that the Save Changes button is enabled. Close the application.

10. On the File menu, click Close Solution.

Results: After completing this exercise, users will be able to remove students from classes.

MCT USE ONLY. STUDENT USE PROHIBITED


L01-11

Exercise 4: Displaying a Students Age


X Task 1: Examine the MainWindow XAML
1. 2. 3. 4. 5. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 4, click School.sln, and then click Open. On the Build menu, click Build Solution.

In Solution Explorer, expand the School, and then double-click the MainWindow.xaml and view the XAML code. Take note of the following lines of markup:
<app:AgeConverter x:key="ageConverter"/> <GridViewColumn Width="75" Header="Age" DisplayMemberBinding="{Binding Path=DateOfBirth, Converter={StaticResource ageConverter}}" />

X Task 2: Add logic to the AgeConverter class to calculate a students age from their date of birth
1. 2.

In the Task List window, double-click the TODO: Exercise 4: Task 2a: Check that the value provided is not null. If it is, return an empty string task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
if (value != null) {

3.

In the code editor, after all the comments in this method, delete the following line of code:
return "";

4. 5.

In the Task List window, double-click the TODO: Exercise 4: Task 2b: Convert the value provided into a DateTime value task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
DateTime studentDateOfBirth = (DateTime)value;

6. 7.

In the Task List window, double-click the TODO: Exercise 4: Task 2c: Work out the difference between the current date and the value provided task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
TimeSpan difference = DateTime.Now.Subtract(studentDateOfBirth);

8. 9.

In the Task List window, double-click the TODO: Exercise 4: Task 2d: Convert this result into a number of years task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
int ageInYears = (int)(difference.Days / 365.25);

MCT USE ONLY. STUDENT USE PROHIBITED

L01-12 Programming in Visual C#

10. In the Task List window, double-click the TODO: Exercise 4: Task 2e: Convert the number of years into a string and return it task. 11. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
return ageInYears.ToString(); } else { return ""; }

X Task 3: Run the application and verify that the students age now appears correctly
1. 2. 3. 4. 5. 6. 7. 8. 9. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging. Verify that the application starts and displays the initial list of students, with their ages. Click the row containing the name Kevin Liu. Press Insert.

In the new student window, enter your first name in the First Name box, your last name in the Last Name box and your date of birth in the Date of Birth box. Click OK and verify that your name and age display correctly in the student list. Close the application. On the File menu, click Close Solution.

Results: After completing this exercise, the application will display a students age in years.

Module 02: Creating Methods, Handling Exceptions, and Monitoring Applications

MCT USE ONLY. STUDENT USE PROHIBITED


L02-1

Lab: Extending the Class Enrollment Application Functionality


Exercise 1: Refactoring the Enrollment Code

X Task 1: Copy the code for editing a student into the studentsList_MouseDoubleClick event handler
1. 2. 3. Start the MSL-TMG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-02 virtual machine. Log on to Windows 8 as Student with the password Pa$$w0rd. Note: If necessary, click Switch User to display the list of users. 4. 5. 6. 7. 8. 9. Switch to the Windows 8 Start window. Click Visual Studio 2012. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click School.sln, and then click Open. In Solution Explorer, expand School, expand MainWindow.xaml, and then double-click MainWindow.xaml.cs. On the View menu, click Task List.

10. In the Task List window, in the Categories list, click Comments.

11. Double-click the TODO: Exercise 1: Task 1a: If the user double-clicks a student, edit the details for that student task. 12. Above the comment, in the studentsList_Keydown method, locate the case Key.Enter: block, and copy the following code to the clipboard:
Student student = this.studentsList.SelectedItem as Student; // TODO: Exercise 1: Task 3a: Refactor as the editStudent method // Use the StudentsForm to display and edit the details of the student StudentForm sf = new StudentForm(); // Set the title of the form and populate the fields on the form with the details of the student sf.Title = "Edit Student Details"; sf.firstName.Text = student.FirstName; sf.lastName.Text = student.LastName; sf.dateOfBirth.Text = student.DateOfBirth.ToString("d"); // Format the date to omit the time element // Display the form if (sf.ShowDialog().Value) { // When the user closes the form, copy the details back to the student student.FirstName = sf.firstName.Text; student.LastName = sf.lastName.Text;

MCT USE ONLY. STUDENT USE PROHIBITED

L02-2 Programming in Visual C#

student.DateOfBirth = DateTime.Parse(sf.dateOfBirth.Text); // Enable saving (changes are not made permanent until they are written back to the database) saveChanges.IsEnabled = true; }

13. Double-click the TODO: Exercise 1: Task 1a: If the user double-clicks a student, edit the details for the student task. 14. Paste the code from the clipboard into studentsList_MouseDoubleClick method.

X Task 2: Run the application and verify that the user can now double-click a student to edit their details
1. 2. 3. 4. 5. 6. 7. 8. 9. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging. Click the row containing the name Kevin Liu and then press Enter. Verify that the Edit Student Details window appears, displaying the correct details. In the Last Name box, delete the existing contents, type Cook, and then click OK.

Verify that Liu has changed to Cook in the students list, and that the Save Changes button is now enabled. Double-click the row containing the name George Li. Verify that the Edit Student Details window appears, displaying the correct details. In the First Name box, delete the existing contents, and then type Darren.

10. In the Last Name box, delete the existing contents, type Parker, and then click OK. 11. Verify that George Li has changed to Darren Parker. 12. Close the application.

X Task 3: Use the Analyze Solution for Code Clones wizard to detect the duplicated code
1. 2. 3. 4. On the Analyze menu, click Analyze Solution for Code Clones. In the Code Clone Analysis Results window, expand Exact Match.

Double-click the second row containing the text MainWindow:studentsList_MouseDoubleClick. In the code editor, in the studentsList_MouseDoubleClick method, delete the following line of code:
Student student = this.studentsList.SelectedItem as Student;

5.

In the studentsList_MouseDoubleClick method, highlight all of the code:

// TODO: Exercise 1: Task 3a: Refactor as the editStudent method // Use the StudentsForm to display and edit the details of the student StudentForm sf = new StudentForm(); // Set the title of the form and populate the fields on the form with the details of the student sf.Title = "Edit Student Details"; sf.firstName.Text = student.FirstName; sf.lastName.Text = student.LastName; sf.dateOfBirth.Text = student.DateOfBirth.ToString("d"); // Format the date to omit the time element

// Display the form if (sf.ShowDialog().Value) { // When the user closes the form, copy the details back to the student student.FirstName = sf.firstName.Text; student.LastName = sf.lastName.Text; student.DateOfBirth = DateTime.Parse(sf.dateOfBirth.Text); // Enable saving (changes are not made permanent until they are written back to the database) saveChanges.IsEnabled = true; }

MCT USE ONLY. STUDENT USE PROHIBITED


L02-3

6. 7. 8.

On the Edit menu, point to Refactor, and then click Extract Method.

In the Extract Method dialog box, in the New method name box, delete the existing contents, type editStudent, and then click OK.

In the studentsList_MouseDoubleClick method, modify the call to the editStudent method to look like the following code:
editStudent(this.studentsList.SelectedItem as Student);

9.

Locate the editStudent method, and modify the method parameters to look like the following code:
private void editStudent(Student student)

Note: The generated method is located below the method that it was generated from. 10. In the Code Clone Analysis Results window, double-click the row containing the text MainWindow:studentsList_KeyDown

11. In the code editor, in the studentsList_KeyDown method, in the case Key.Enter: block, delete the code shown in step 5. 12. Click at the end of the Student student = this.studentsList.SelectedItem as Student; code line, press Enter, and then type the following code:
editStudent(student);

13. Below the Code Clone Analysis Results window, click Task List.

X Task 4: Refactor the logic that adds and deletes a student into the addNewStudent and deleteStudent methods
1. 2.

In the Task List window, double-click the TODO: Exercise 1: Task 4a: Refactor as the addNewStudent method task. In the code editor, locate the case Key.Insert: block, and then highlight the following code:

// TODO: Exercise 1: Task 4a: Refactor as the addNewStudent method // Use the StudentsForm to get the details of the student from the user sf = new StudentForm(); // Set the title of the form to indicate which class the student will be added to (the class for the currently selected teacher) sf.Title = "New Student for Class " + teacher.Class; // Display the form and get the details of the new student if (sf.ShowDialog().Value) {

MCT USE ONLY. STUDENT USE PROHIBITED

L02-4 Programming in Visual C#

// When the user closes the form, retrieve the details of the student from the form // and use them to create a new Student object Student newStudent = new Student(); newStudent.FirstName = sf.firstName.Text; newStudent.LastName = sf.lastName.Text; newStudent.DateOfBirth = DateTime.Parse(sf.dateOfBirth.Text); // Assign the new student to the current teacher this.teacher.Students.Add(newStudent); // Add the student to the list displayed on the form this.studentsInfo.Add(newStudent); // Enable saving (changes are not made permanent until they are written back to the database) saveChanges.IsEnabled = true; }

3. 4. 5.

On the Edit menu, point to Refactor, and then click Extract Method.

In the Extract Method dialog box, in the New method name box, type addNewStudent, and then click OK. Locate the addnewStudent method and in the method, modify the sf = new StudentForm(); code to look like the following code:
StudentForm sf = new StudentForm();

6. 7.

In the Task List window, double-click the TODO: Exercise 1: Task 4b: Refactor as the removeStudent method task. In the code editor, locate the case Key.Delete block, and cut the following code to the clipboard:

// TODO: Exercise 1: Task 4b: Refactor as the removeStudent method // Prompt the user to confirm that the student should be removed MessageBoxResult response = MessageBox.Show( String.Format("Remove {0}", student.FirstName + " " + student.LastName), "Confirm", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No); // If the user clicked Yes, remove the student from the database if (response == MessageBoxResult.Yes) { this.schoolContext.Students.DeleteObject(student); // Enable saving (changes are not made permanent until they are written back to the database) saveChanges.IsEnabled = true; }

8.

In the code editor, in the case Key.Delete: block, click at the end of student = this.studentsList.SelectedItem as Student; code line, press Enter, then type the following code
removeStudent(student);

9.

Right-click the removeStudent(student); method call, point to Generate, and then click Method Stub.

10. Locate the removeStudent method below the studentsList_KeyDown method, delete all the generated code in this method, and then paste the code from the clipboard.

X Task 5: Verify that students can still be added and removed from the application
1. 2. On the Build menu, click Build Solution. On the Debug Menu, click Start Without Debugging.

MCT USE ONLY. STUDENT USE PROHIBITED


L02-5

3. 4. 5. 6. 7. 8. 9.

Click the row containing the name Kevin Liu, and then press Insert. Verify that the New Student for Class 3C window appears. In the First Name box, type Dominik. In the Last Name box, type Dubicki. In the Date of Birth box, type 02/03/2006 and then click OK. Verify that Dominik Dubicki has been added to the students list. Click the row containing the name Run Liu, and then press Delete.

10. Verify that the confirmation prompt appears. 11. Click Yes, and then verify that Run Liu is removed from the students list. 12. Close the application.

X Task 6: Debug the application and step into the new method calls
1. 2. 3. 4. 5. 6. 7. 8. 9.

In the code editor, locate the studentsList_KeyDown method, right-click on the switch (e.key) statement, point to Breakpoint, and then click Insert Breakpoint. On the Debug menu, click Start Debugging. Click the row containing the name Kevin Liu and press Enter. In the Immediate window, click the Call Stack tab. Note that the current method name is displayed in the window. In the Watch 1 window, click the Locals tab. Note the local variables this, sender, e, and student are displayed in the window. On the Debug menu, click Step Over. Repeat step 8.

10. Look at the Locals window, and note after stepping over the Student student = this.studentsList.SelectedItem as Student; code, the value for the student variable has changed from null to School.Data.Student. 11. In the Locals window, expand student and note the values for _FirstName and _LastName. 12. On the Debug menu, click Step Into.

13. Note that execution steps into the editStudent method and that this method name has been added to the Call Stack. 14. Look at the Locals window and note that the local variables have changed to this, student, and sf. 15. On the Debug menu, click Step Over. 16. Repeat step 15 five times

17. In the Locals window, expand sf and note the values for dateOfBirth, firstName, and lastName.

18. On the Debug menu, click Step Out to run the remaining code in the editStudent method and step out again to the calling method. 19. In the Edit Student Details window, click Cancel. 20. Note that execution returns to the studentsList_KeyDown method. 21. On the Debug menu, click Step Over.

MCT USE ONLY. STUDENT USE PROHIBITED

L02-6 Programming in Visual C#

22. On the Debug menu, click Continue. 23. Click the row containing the name Kevin Liu and press Insert. 24. On the Debug menu, click Step Over. 25. On the Debug menu, click Step Into. 26. Note that execution steps into the addNewStudent method.

27. On the Debug menu, click Step Out to run the remaining code in the addNewStudent method and step out again to the calling method. 28. In the New Student for Class 3C window, click Cancel. 29. Note that execution returns to the studentsList_KeyDown method. 30. On the Debug menu, click Step Over. 31. On the Debug menu, click Continue. 32. Click the row containing the name George Li and press Delete. 33. On the Debug menu, click Step Over. 34. Repeat step 33. 35. On the Debug menu, click Step Into. 36. Note that execution steps into the removeStudent method.

37. On the Debug menu, click Step Out to run the remaining code in the removeStudent method and step out again to the calling method. 38. In the Confirm message box, click No. 39. Note that execution returns to the studentList_KeyDown method. 40. On the Debug menu, click Step Over. 41. On the Debug menu, click Continue. 42. Close the application 43. In Visual Studio, on the Debug menu, click Delete All Breakpoints. 44. In the Microsoft Visual Studio message box, click Yes. 45. On the File menu, click Close Solution.

Results: After completing this exercise, you should have updated the application to refactor duplicate code into reusable methods.

MCT USE ONLY. STUDENT USE PROHIBITED


L02-7

Exercise 2: Validating Student Information

X Task 1: Run the application and observe that student details that are not valid can be entered
1. 2. 3. 4. 5. 6. 7. 8. 9. In Visual Studio, on the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click School.sln, and then click Open. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging. Click on the row containing the name Kevin Liu, and then press Insert. Leave the First Name and Last Name boxes empty. In the Date of Birth box, type 10/06/3012, and then click OK.

Verify that a new row has been added to the student list, containing a blank first name, blank last name, and a negative age. Close the application.

X Task 2: Add code to validate the first name and last name fields
1. 2.

In the Task List window, double-click the TODO: Exercise 2: Task 2a: Check that the user has provided a first name task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
if (String.IsNullOrEmpty(this.firstName.Text)) { MessageBox.Show("The student must have a first name", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; }

3. 4.

In the Task List window, double-click the TODO: Exercise 2: Task 2b: Check that the user has provided a last name task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
if (String.IsNullOrEmpty(this.lastName.Text)) { MessageBox.Show("The student must have a last name", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; }

X Task 3: Add code to validate the date of birth


1. 2.

In the Task List window, double-click the TODO: Exercise 2: Task 3a: Check that the user has entered a valid date for the date of birth task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
DateTime result;

MCT USE ONLY. STUDENT USE PROHIBITED

L02-8 Programming in Visual C#

if (!DateTime.TryParse(this.dateOfBirth.Text, out result)) { MessageBox.Show("The date of birth must be a valid date", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; }

3. 4.

In the Task List window, double-click the TODO: Exercise 2: Task 3b: Verify that the student is at least 5 years old task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
TimeSpan age = DateTime.Now.Subtract(result); if (age.Days / 365.25 < 5) { MessageBox.Show("The student must be at least 5 years old", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; }

X Task 4: Run the application and verify that student information is now validated correctly
1. 2. 3. 4. 5. 6. 7. 8. 9. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging. Click on the row containing the name Kevin Liu, and then press Insert. Leave the First Name, Last Name, and Date of Birth boxes empty and click OK. Verify that an error message appears containing the text The student must have a first name. In the Error message box, click OK. In the new student window, in the First Name box, type Darren, and then click OK. Verify that an error message appears containing the text The student must have a last name. In the Error message box, click OK.

10. In the new student window, in the Last Name box, type Parker, and then click OK.

11. Verify that an error message appears containing the text The date of birth must be a valid date. 12. In the Error message box, click OK. 13. In the new student window, in the Date of Birth box, type 10/06/3012, and then click OK.

14. Verify that an error message appears containing the text The student must be at least 5 years old. 15. In the Error message box, click OK.

16. In the new student window, in the Date of Birth box, delete the existing date, type 10/06/2006, and then click OK. 17. Verify that Darren Parker is added to the student list with an age appropriate to the current date. 18. Close the application. 19. On the File menu, click Close Solution.

MCT USE ONLY. STUDENT USE PROHIBITED


L02-9

Results: After completing this exercise, student data will be validated before it is saved.

Exercise 3: Saving Changes to the Class List


X Task 1: Verify that data changes are not persisted to the database
1. 2. 3. 4. 5. 6. 7. 8. 9. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 3, click School.sln, and then click Open. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging. Click the row containing the name Kevin Liu.

Press Enter and verify that the Edit Student Details window appears displaying the correct details. In the Last Name box, delete the existing contents, type Cook, and then click OK.

Verify that Liu has changed to Cook in the students list, and that the Save Changes button is now enabled. Click Save Changes.

10. Click the row containing the student George Li, and then press Delete. 11. Verify that the confirmation prompt appears, and then click Yes. 12. Verify that George Li is removed from the student list, and then click Save Changes. 13. Close the application 14. On the Debug menu, click Start Without Debugging. 15. Verify that the application displays the original list of students.

16. Verify that Kevin Liu appears in the list instead of Kevin Cook and George Li is back in the student list. 17. Close the application.

X Task 2: Add code to save changes back to the database


1. 2. In Visual Studio, in the Task List window, double-click the TODO: Exercise 3: Task 2a: Bring the System.Data and System.Data.Objects namespace into scope task.

In the code editor, click in the blank line above the comment, and then type the following code:
using System.Data; using System.Data.Objects;

3. 4.

In Visual Studio, in the Task List window, double-click the TODO: Exercise 3: Task 2b: Save the changes by calling the SaveChanges method of the schoolContext object task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
// Save the changes this.schoolContext.SaveChanges(); // Disable the Save button (it will be enabled if the user makes more changes) saveChanges.IsEnabled = false;

MCT USE ONLY. STUDENT USE PROHIBITED

L02-10 Programming in Visual C#

X Task 3: Add exception handling to the code to catch concurrency, update, and general exceptions
1.

In the code editor, enclose the code that you wrote in the previous task in a try block. Your code should look like the following:
try {

// Save the changes this.schoolContext.SaveChanges(); // Disable the Save button (it will be enabled if the user makes more changes) saveChanges.isEnabled = false; }

2.

In the Task List window, double-click the TODO: Exercise 3: Task 3a: If an OptimisticConcurrencyException occurs then another user has changed the same students earlier then overwrite their changes with the new data (see the lab instructions for details) task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
catch (OptimisticConcurrencyException) { // If the user has changed the same students earlier, then overwrite their changes with the new data this.schoolContext.Refresh( RefreshMode.StoreWins, schoolContext.Students); this.schoolContext.SaveChanges(); }

3.

4. 5.

In the Task List window, double-click the TODO: Exercise 3: Task 3b: If an UpdateException occurs then report the error to the user and rollback (see the lab instructions for details) task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:

catch (UpdateException uEx) { // If some sort of database exception has occurred, then display the reason for the exception and rollback MessageBox.Show(uEx.InnerException.Message, "Error saving changes"); this.schoolContext.Refresh(RefreshMode.StoreWins, schoolContext.Students); }

6.

In the Task List window, double-click the TODO: Exercise 3: Task 3c: If some other sort of error has occurs, report the error to the user and retain the data so the user can try again - the error may be transitory (see the lab instructions for details) task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
catch (Exception ex) { // If some other exception occurs, report it to the user MessageBox.Show(ex.Message, "Error saving changes"); this.schoolContext.Refresh( RefreshMode.ClientWins, schoolContext.Students); }

7.

MCT USE ONLY. STUDENT USE PROHIBITED


L02-11

X Task 4: Run the application and verify that data changes are persisted to the database
1. 2. 3. 4. 5. 6. 7. 8. 9. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging. Click the row containing the student Kevin Liu. Press Enter, in the Last Name box delete the existing contents, type Cook, and then click OK.

Verify that Liu has changed to Cook in the students list, and that the Save Changes button is now enabled. Click Save Changes and verify that the Save Changes button is now disabled. Click the row containing the student George Li and press Delete. Verify that the confirmation prompt appears, and then click Yes. Verify that the Save Changes button is now enabled

10. Click Save Changes and verify that the button is now disabled. 11. Close the application. 12. On the Debug menu, click Start Without Debugging.

13. Verify that the changes you made to the student data have been saved to the database and are reflected in the student list. 14. Close the application. 15. On the File menu, click Close Solution.

Results: After completing this exercise, modified student data will be saved to the database

MCT USE ONLY. STUDENT USE PROHIBITED

Module 3: Developing the Code for a Graphical Application

MCT USE ONLY. STUDENT USE PROHIBITED


L3-1

Lab: Writing the Code for the Grades Prototype Application


X Task 1: Examine the window and views in the application
1. 2. 3. Start the MSL-TMG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-03 virtual machine. Log on to Windows 8 as Student with the password Pa$$w0rd. Note: If necessary, click Switch User to display the list of users. 4. 5. 6. 7. 8. 9. Switch to the Windows 8 Start window. Click Visual Studio 2012. In Visual Studio, on the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click GradesPrototype.sln, and then click Open. On the Build menu, click Build Solution. In Solution Explorer, expand GradesPrototype, and then double-click MainWindow.xaml.

Exercise 1: Adding navigation logic to the Grades Prototype Application

10. Note that this is the main window for the application that will host the following views: LogonPage.xaml StudentProfile.xaml StudentsPage.xaml

11. In Solution Explorer, expand Views, and then double-click LogonPage.xaml.

12. Notice that this view contains text boxes for the username and password, a check box to identify the user as a teacher, and a button to log on to the application. 13. In Solution Explorer, double-click StudentProfile.xaml.

14. Notice that this view contains a Report Card that currently displays a list of dummy grades. The view also contains a Back button and a blank space that will display the students name. This view is displayed when a student logs on or when a teacher views a students profile. 15. In Solution Explorer, double-click StudentsPage.xaml.

16. Notice that this view contains the list of students in a particular class. This view is displayed when a teacher logs on. A teacher can click a students name and the Students Profile view will be displayed, containing the selected students data.

X Task 2: Define the LogonSuccess event and add dummy code for the Logon_Click event
1. On the View menu, click Task List.

MCT USE ONLY. STUDENT USE PROHIBITED

L3-2

Programming in Visual C#

2. 3. 4. 5. 6. 7.

In the Task List window, in the Categories list, click Comments. Double-click the TODO: Exercise 1: Task 2a: Define the LogonSuccess event handler task. In the code editor, click in the blank line below the comment, and then type the following code: public event EventHandler LogonSuccess;

In the Task List window double-click the TODO: Exercise 1: Task 2b: Implement the Logon_Click event handler for the Logon button task. In the code editor, click in the blank line below the comments, and then type the following code:

private void Logon_Click(object sender, RoutedEventArgs e) { // Save the username and role (type of user) specified on the form in the global context SessionContext.UserName = username.Text; SessionContext.UserRole = (bool)userrole.IsChecked ? Role.Teacher : Role.Student; // If the role is Student, set the CurrentStudent property in the global context to a dummy student; Eric Gruber if (SessionContext.UserRole == Role.Student) { SessionContext.CurrentStudent = "Eric Gruber"; } // Raise the LogonSuccess event if (LogonSuccess != null) { LogonSuccess(this, null); } }

8. 9.

In Solution Explorer, double-click LogonPage.xaml.

In the XAML editor, locate the task TODO: Exercise 1: Task 2c: Specify that the Logon button should raise the Logon_Click event handler in this view task.

10. In the line below the comment, modify the XAML markup <Button Grid.Row="3" Grid.ColumnSpan="2" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Log on" FontSize="24" /> to look like the following markup:
Button Grid.Row="3" Grid.ColumnSpan="2" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Log on" FontSize="24" Click="Logon_Click" />

X Task 3: Add code to display the Log On view


1. 2.

In the Task List window, double-click the TODO: Exercise 1: Task 3a: Display the logon view and hide the list of students and single student view task. In the code editor, click in the blank line in the GotoLogon method, and then type the following code:
// Display the logon view and hide the list of students and single student view logonPage.Visibility = Visibility.Visible; studentsPage.Visibility = Visibility.Collapsed;

3. 4. 5.

studentProfile.Visibility = Visibility.Collapsed;

In the Task List window, double-click the TODO: Exercise 1: Task 3b: Handle successful logon task. In the code editor, click in the blank line below the comments, and then type the following code:

MCT USE ONLY. STUDENT USE PROHIBITED


L3-3

// Handle successful logon private void Logon_Success(object sender, EventArgs e) { // Update the display and show the data for the logged on user logonPage.Visibility = Visibility.Collapsed; gridLoggedIn.Visibility = Visibility.Visible; Refresh(); }

6. 7. 8.

In Solution Explorer, double-click MainWindow.xaml.

In the XAML editor, locate the task TODO: Exercise 1: Task 3c: Catch the LogonSuccess event and call the Logon_Success event handler (to be created) task. In the line below the comment, modify the XAML markup <y:LogonPage x:Name="logonPage" Visibility="Collapsed" /> to look like the following markup:

<y:LogonPage x:Name="logonPage" LogonSuccess="Logon_Success" Visibility="Collapsed" />

X Task 4: Add code to determine the type of user


1. 2.

In the Task List window, double-click the TODO: Exercise 1: Task 4a: Update the display for the logged on user (student or teacher) task. In the code editor, click in the blank line in the Refresh method, and then type the following code:
switch (SessionContext.UserRole) { case Role.Student: // Display the student name in the banner at the top of the page txtName.Text = string.Format("Welcome {0}", SessionContext.UserName); // Display the details for the current student GotoStudentProfile(); break; case Role.Teacher: // Display the teacher name in the banner at the top of the page txtName.Text = string.Format("Welcome {0}", SessionContext.UserName); // Display the list of students for the teacher GotoStudentsPage(); break; }

3. 4.

In the Task List window, double-click the TODO: Exercise 1: Task 4b: Display the details for a single student task. In the code editor, click in the blank line in the GotoStudentProfile method, and then type the following code:
// Hide the list of students studentsPage.Visibility = Visibility.Collapsed; // Display the view for a single student studentProfile.Visibility = Visibility.Visible; studentProfile.Refresh();

5. 6.

In the Task List window, double-click the TODO: Exercise 1: Task 4c: Display the list of students task. In the code editor, click in the blank line in the GotoStudentsPage method, and then type the following code:

MCT USE ONLY. STUDENT USE PROHIBITED

L3-4

Programming in Visual C#

// Hide the view for a single student (if it is visible) studentProfile.Visibility = Visibility.Collapsed; // Display the list of students studentsPage.Visibility = Visibility.Visible; studentsPage.Refresh();

7. 8.

In the Task List window, double-click the TODO: Exercise 1: Task 4d: Display the details for the current student including the grades for the student task. In the code editor, click in the blank line in the Refresh method, and then type the following code:
// Parse the student name into the first name and last name by using a regular expression // The firstname is the initial string up to the first space character. // The lastname is the string after the space character Match matchNames = Regex.Match(SessionContext.CurrentStudent, @"([^ ]+) ([^ ]+)"); if (matchNames.Success) { string firstName = matchNames.Groups[1].Value; // Indexing in the Groups collection starts at 1, not 0 string lastName = matchNames.Groups[2].Value; // Display the first name and last name in the TextBlock controls in the studentName StackPanel ((TextBlock)studentName.Children[0]).Text = firstName; ((TextBlock)studentName.Children[1]).Text = lastName; } // If the current user is a student, hide the Back button // (only applicable to teachers who can use the Back button to return to the list of students) if (SessionContext.UserRole == Role.Student) { btnBack.Visibility = Visibility.Hidden; } else { btnBack.Visibility = Visibility.Visible; }

X Task 5: Handle the Student_Click event


1. 2.

In the Task List window, double-click the TODO: Exercise 1: Task 5a: Handle the click event for a student task. In the code editor, click in the blank line in the Student_Click method, and then type the following code:
Button itemClicked = sender as Button; if (itemClicked != null) { // Find out which student was clicked - the Tag property of the button contains the name string studentName = (string)itemClicked.Tag; if (StudentSelected != null) { // Raise the StudentSelected event (handled by MainWindow) to display the details for this student StudentSelected(sender, new StudentEventArgs(studentName)); } }

3.

In the Task List window, double-click the TODO: Exercise 1: Task 5b: Handle the StudentSelected event when the user clicks a student on the Students page task.

MCT USE ONLY. STUDENT USE PROHIBITED


L3-5

4.

In the code editor, click in the blank line in the studentsPage_StudentSelected method, and then type the following code:
SessionContext.CurrentStudent = e.Child; GotoStudentProfile();

5. 6. 7.

In Solution Explorer, double-click MainWindow.xaml.

In the XAML editor, locate the task TODO: Exercise 1: Task 5c: Catch the StudentSelected event and call the studentsPage_StudentSelected event handler task. In the line below the comment, modify the XAML markup <y:StudentsPage x:Name="studentsPage" Visibility="Collapsed" /> to look like the following markup:

<y:StudentsPage x:Name="studentsPage" StudentSelected="studentsPage_StudentSelected" Visibility="Collapsed" />

X Task 6: Build and test the application


1. 2. 3. 4. 5. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging.

When the application loads, in the Username box, type vallee, and in the Password box, type password. Select the Teacher check box, and then click Log on. Verify that the application displays the StudentPage view. The Students page should look like this:

FIGURE 3.1: THE STUDENTS PAGE 6. Click the student Kevin Liu and verify that the application displays the StudentProfile view.

MCT USE ONLY. STUDENT USE PROHIBITED

L3-6

Programming in Visual C#

The Student Profile page should look like this:

FIGURE 3.2: THE STUDENT PROFILE PAGE 7. 8. 9. Click Log off. In the Username box, delete the existing contents, and then type grubere. Clear the Teacher check box, and then click Log on.

10. Verify that the application displays the student profile page for Eric Gruber. 11. Close the application. 12. On the File menu, click Close Solution.

Results: After completing this exercise, you should have updated the Grades Prototype application to respond to user events and move among the application views appropriately.

MCT USE ONLY. STUDENT USE PROHIBITED


L3-7

Exercise 2: Creating Data Types to Store User and Grade Information


1. 2. 3. 4. 5. In Visual Studio, on the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click GradesPrototype.sln, and then click Open. On the View menu, click Task List.

X Task 1: Define basic structs for holding Grade, Student, and Teacher information

In the Task List window, double-click the TODO: Exercise 2: Task 1a: Create the Grade struct task. In the code editor, click in the blank line below the comment, and then type the following code:
public struct Grade { public int StudentID { get; set; } public string AssessmentDate { get; set; } public string SubjectName { get; set; } public string Assessment { get; set; } public string Comments { get; set; } }

6. 7.

In the Task List window, double-click the TODO: Exercise 2: Task 1b: Create the Student struct task. In the code editor, click in the blank line below the comment, and then type the following code:
public struct Student { public int StudentID { get; set; } public string UserName { get; set; } public string Password { get; set; } public int TeacherID { get; set; } public string FirstName { get; set; } public string LastName { get; set; } }

8. 9.

In the Task List window, double-click the TODO: Exercise 2: Task 1c: Create the Teacher struct task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
public struct Teacher { public int TeacherID { get; set; } public string UserName { get; set; } public string Password { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string Class { get; set; } }

X Task 2: Add unit tests to create and use the collections of structs
1. 2. 3. On the File menu, point to Add, and then click New Project.

In the Add New Project dialog box, in the Installed Templates list, click Test, and then in the Templates list, click Unit Test Project. In the Name box, type GradesTest, and then click OK.

MCT USE ONLY. STUDENT USE PROHIBITED

L3-8

Programming in Visual C#

4. 5. 6. 7. 8. 9.

In Solution Explorer, right-click GradesTest, and then click Add Reference. In the Reference Manager GradesTest dialog box, expand Solution. Select the GradesPrototype check box, and then click OK. In Solution Explorer, right-click UnitTest1.cs, and then click Rename. Type GradesUnitTests, and then press Enter. In the Microsoft Visual Studio message box, click Yes.

10. In the code editor, click at the end of the line of the code using Microsoft.VisualStudio.TestTools.UnitTesting; and then press Enter. 11. Type the following code:
using GradesPrototype.Data;

12. In the GradesUnitTests class, delete all of the existing code and then type the following code:
[TestMethod] public void StudentTest() { Student student = new Student() { FirstName = "Eric", LastName = "Gruber", UserName = "grubere", Password = "password" }; Assert.AreEqual("Eric", student.FirstName); Assert.AreEqual("Gruber", student.LastName); Assert.AreEqual("grubere", student.UserName); Assert.AreEqual("password", student.Password); } [TestMethod] public void TeacherTest() { Teacher teacher = new Teacher() { FirstName = "Esther", LastName = "Valle", UserName = "vallee", Password = "password", Class = "3A" }; Assert.AreEqual("Esther", teacher.FirstName); Assert.AreEqual("Valle", teacher.LastName); Assert.AreEqual("vallee", teacher.UserName); Assert.AreEqual("password", teacher.Password); Assert.AreEqual("3A", teacher.Class); } private Grade createGrade(string assessment, string subject, string comments) { Grade grade = new Grade(); grade.AssessmentDate = string.Format("{0:d}", DateTime.Now); grade.Assessment = assessment; grade.SubjectName = subject; grade.Comments = comments; return grade; } [TestMethod] public void GradeTest() {

Grade grade = createGrade("B+", "Math", "Good"); Assert.AreEqual(string.Format("{0:d}", DateTime.Now), grade.AssessmentDate); Assert.AreEqual("B+", grade.Assessment); Assert.AreEqual("Math", grade.SubjectName); Assert.AreEqual("Good", grade.Comments); } [TestMethod] public void GradeCollectionTest() { Grade grade1 = createGrade("B+", "Math", "Good"); Grade grade2 = createGrade("A-", "English", "Very Good"); Grade grade3 = createGrade("C-", "Geography", "Could do better"); Grade grade4 = createGrade("D-", "History", "Very poor"); System.Collections.ArrayList grades = new System.Collections.ArrayList(); grades.Add(grade1); grades.Add(grade2); grades.Add(grade3); grades.Add(grade4); Assert.AreEqual(grades.Count, 4); Grade testGrade = (Grade)grades[2]; Assert.AreEqual(string.Format("{0:d}", DateTime.Now), testGrade.AssessmentDate); Assert.AreEqual("C-", testGrade.Assessment); Assert.AreEqual("Geography", testGrade.SubjectName); Assert.AreEqual("Could do better", testGrade.Comments); }

MCT USE ONLY. STUDENT USE PROHIBITED


L3-9

13. On the Build menu, click Build Solution. 14. On the Test menu, point to Run, and then click All Tests. 15. In the Test Explorer window, verify that all the tests are passed. 16. Close Test Explorer. 17. On the File menu, click Close Solution.

Results: After completing this exercise, the application will contain structs for the teacher, student, and grade types.

MCT USE ONLY. STUDENT USE PROHIBITED

L3-10 Programming in Visual C#

Exercise 3: Displaying User and Grade Information


X Task 1: Examine the dummy data source used to populate the collections
1. 2. 3. 4. 5. 6. 7. In Visual Studio, on the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 3, click GradesPrototype.sln, and then click Open.

In Solution Explorer, expand GradesPrototype, expand Data, and then double-click DataSource.cs. In the code editor, expand the region Sample Data, and then locate the method CreateData. Note how the Teachers ArrayList is populated with Teacher data, each containing TeacherID, UserName, Password, FirstName, LastName, and Class fields.

Note how the Students ArrayList is populated with Student data, each containing a StudentID, UserName, Password, TeacherID, FirstName, and LastName fields. Note how the Grades ArrayList is populated with Grade data, each containing a StudentID, AssessmentDate, SubjectName, Assessment, and Comments fields.

X Task 2: Add the LogonFailed event


1. 2.

In the Task List window, double-click the TODO: Exercise 3: Task 2a: Define LogonFailed event task. In the code editor, click in the blank line below the comment, and then type the following code:
public event EventHandler LogonFailed;

3. 4.

In the Task List window, double-click the TODO: Exercise 3: Task 2b: Validate the username and password against the Users collection in the MainWindow window task. In the code editor, in the Logon_Click method, click in the blank line, and then type the following code:
// Find the user in the list of possible users - first check whether the Teacher var teacher = (from Teacher t in DataSource.Teachers where String.Compare(t.UserName, username.Text) == 0 && String.Compare(t.Password, password.Password) == 0 select t).FirstOrDefault(); // If the UserName of the user retrieved by using LINQ is non-empty then a teacher if (!String.IsNullOrEmpty(teacher.UserName)) { // Save the UserID and Role (teacher or student) and UserName in the context SessionContext.UserID = teacher.TeacherID; SessionContext.UserRole = Role.Teacher; SessionContext.UserName = teacher.UserName; SessionContext.CurrentTeacher = teacher; // Raise the LogonSuccess event and finish LogonSuccess(this, null); return; } // If the user is not a teacher, check whether the username and password of a student else { var student = (from Student s in DataSource.Students where String.Compare(s.UserName, username.Text) == 0 && String.Compare(s.Password, password.Password) == user is a

the user is

global

match those

select s).FirstOrDefault(); // If the UserName of the user retrieved by using LINQ is non-empty then the user is a student if (!String.IsNullOrEmpty(student.UserName)) { // Save the details of the student in the global context SessionContext.UserID = student.StudentID; SessionContext.UserRole = Role.Student; SessionContext.UserName = student.UserName; SessionContext.CurrentStudent = student; // Raise the LogonSuccess event and finish LogonSuccess(this, null); return; } } // If the credentials do not match those for a Teacher or for a Student then they must be invalid // Raise the LogonFailed event LogonFailed(this, null);

MCT USE ONLY. STUDENT USE PROHIBITED


L3-11

X Task 3: Add the Logon_Failed event handler


1. 2.

In the Task List window, double-click the TODO: Exercise 3: Task 3a: Handle logon failure task. In the code editor, click in the blank line below the comments, and then type the following code:
private void Logon_Failed(object sender, EventArgs e) { // Display an error message. The user must try again MessageBox.Show("Invalid Username or Password", "Logon Failed", MessageBoxButton.OK, MessageBoxImage.Error); }

3. 4. 5.

In Solution Explorer, double-click MainWindow.xaml.

In the XAML editor, locate the task TODO: Exercise 3: Task 3b: Connect the LogonFailed event of the logonPage view to the Logon_Failed method in MainWindow.xaml.cs task. In the line below the comment, modify the XAML markup <y:LogonPage x:Name="logonPage" LogonSuccess="Logon_Success" Visibility="Collapsed" /> to look like the following markup:
<y:LogonPage x:Name="logonPage" LogonSuccess="Logon_Success" LogonFailed="Logon_Failed" Visibility="Collapsed" />

6. 7.

In the Task List window, double-click the TODO: Exercise 3: Task 3c: Display the student name in the banner at the top of the page task. In the code editor, click in the blank line below the comment, and then type the following code:
// Display the student name in the banner at the top of the page txtName.Text = string.Format("Welcome {0} {1}", SessionContext.CurrentStudent.FirstName, SessionContext.CurrentStudent.LastName);

8. 9.

In the Task List window, double-click the TODO: Exercise 3: Task 3d: Display the teacher name in the banner at the top of the page task. In the code editor, click in the blank line below the comment, and then type the following code:
// Display the teacher name in the banner at the top of the page txtName.Text = string.Format("Welcome {0} {1}", SessionContext.CurrentTeacher.FirstName, SessionContext.CurrentTeacher.LastName);

MCT USE ONLY. STUDENT USE PROHIBITED

L3-12 Programming in Visual C#

X Task 4: Display the students for the current teacher


1. 2. In Solution Explorer, expand Views, and then double-click StudentsPage.xaml.

In the XAML editor, locate the ItemsControl named list and note how data binding is used to display the name of each student.

Note: DataBinding is also used to retrieve the StudentID of a student. This binding is used when a user clicks on a Student on the Student Page list to identify which students data to display in the Student Profile page. 3. 4.

In the Task List window, double-click the TODO: Exercise 3: Task 4a: Display students for the current teacher (held in SessionContext.CurrentTeacher) task.

In the code editor, in the Refresh method, click in the blank line, and then type the following code:
// Find students for the current teacher ArrayList students = new ArrayList(); foreach (Student student in DataSource.Students) { if (student.TeacherID == SessionContext.CurrentTeacher.TeacherID) { students.Add(student); } } // Bind the collection to the list item template list.ItemsSource = students; // Display the class name txtClass.Text = String.Format("Class {0}", SessionContext.CurrentTeacher.Class);

5. 6.

In the Task List window, double-click the TODO: Exercise 3: Task 4b: If the user clicks on a student, display the details for that student task.

In the code editor, in the Student_Click method, click in the blank line, and then type the following code:

Button itemClicked = sender as Button; if (itemClicked != null) { // Find out which student was clicked int studentID = (int)itemClicked.Tag; if (StudentSelected !=null) { // Find the details of the student by examining the DataContext of the Button Student student = (Student)itemClicked.DataContext; // Raise the StudentSelected event (handled by MainWindow to display the details for this student StudentSelected(sender, new StudentEventArgs(student)); } }

7. 8.

In the Task List window, double-click the TODO: Exercise 3: Task 4c: Set the current student in the global context to the student specified in the StudentEventArgs parameter task. In the code editor, click in the blank line below the comment, and then type the following code:
SessionContext.CurrentStudent = e.Child;

MCT USE ONLY. STUDENT USE PROHIBITED


L3-13

X Task 5: Set the DataContext for the page


1. 2.

In the Task List window, double-click the TODO: Exercise 3: Task 5a: Display the details for the current student (held in SessionContext.CurrentStudent) task. In the code editor, click in the blank line below the comment, and then type the following code:

// Bind the studentName StackPanel to display the details of the student in the TextBlocks in this panel studentName.DataContext = SessionContext.CurrentStudent; // If the current user is a student, hide the Back button // (only applicable to teachers who can use the Back button to return to the list of students) if (SessionContext.UserRole == Role.Student) { btnBack.Visibility = Visibility.Hidden; } else { btnBack.Visibility = Visibility.Visible; }

3. 4. 5.

In Solution Explorer, expand Views and then double-click StudentProfile.xaml.

In the XAML editor, locate the task TODO: Exercise 3: Task 5b: Bind the firstName TextBlock to the FirstName property of the DataContext for this control task. In the line below the comment, modify the XAML markup <TextBlock x:Name="firstName" FontSize="16" /> to look like the following markup:
<TextBlock x:Name="firstName" Text="{Binding FirstName}" FontSize="16" />

6. 7.

In the XAML editor, locate the task TODO: Exercise 3: Task 5c: Bind the lastName TextBlock to the LastName property of the DataContext for this control task. In the line below the comment, modify the XAML markup <TextBlock x:Name="lastName" FontSize="16" /> to look like the following markup:
<TextBlock x:Name="lastName" Text="{Binding LastName}" FontSize="16" />

8. 9.

In the Task List window, double-click the TODO: Exercise 3: Task 5d: Create a list of the grades for the student and display this list on the page task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
// Find all the grades for the student ArrayList grades = new ArrayList(); foreach (Grade grade in DataSource.Grades) { if (grade.StudentID == SessionContext.CurrentStudent.StudentID) { grades.Add(grade); } } // Display the grades in the studentGrades ItemsControl by using databinding studentGrades.ItemsSource = grades;

X Task 6: Build and test the application


1. 2. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging.

MCT USE ONLY. STUDENT USE PROHIBITED

L3-14 Programming in Visual C#

3. 4. 5. 6. 7. 8. 9.

When the application loads, in the Username box, type parkerd, in the Password box, type password, and then click Log on. Verify that the Logon Failed dialog box appears, and then click OK. In the Username box, delete the existing contents, type vallee, and then click Log on. Verify that the Students page appears, displaying a list of students. Click the student Kevin Liu and verify the Student Profile page for Kevin Liu is displayed. Click Log off. In the Username box, delete the existing contents, type grubere, and then click Log on.

10. Verify that the Student Profile page for Eric Gruber is displayed. 11. Close the application. 12. On the File menu, click Close Solution.

Results: After completing this exercise, only valid users will be able to log on to the application and they will see only data appropriate to their role.

MCT USE ONLY. STUDENT USE PROHIBITED


L4-1

Module 4: Creating Classes and Implementing Type-Safe Collections

Lab: Adding Data Validation and TypeSafety to the Application


Exercise 1: Implementing the Teacher, Student, and Grade Structs as Classes
X Task 1: Convert the Grades struct into a class
1. 2. 3. Start the MSL-TNG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-04 virtual machine. Log on to Windows 8 as Student with the password Pa$$w0rd. Note: If necessary, click Switch User to display the list of users. 4. 5. 6. 7. 8. 9. Switch to the Windows 8 Start window. Click Visual Studio 2012. In Visual Studio, on the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click GradesPrototype.sln, and then click Open. On the View menu, click Task List. In the Task List window, in the Categories list, click Comments.

10. Double-click the TODO: Exercise 1: Task 1a: Convert Grade into a class and define constructors task.

11. In the code editor, below the comment, modify the public struct Grade declaration, replacing struct with class.
public class Grade

12. Click at the end of the code public string Comments { get; set; }, press Enter twice, and then type the following code:

// Constructor to initialize the properties of a new Grade public Grade(int studentID, string assessmentDate, string subject, string assessment, string comments) { StudentID = studentID; AssessmentDate = assessmentDate; SubjectName = subject; Assessment = assessment; Comments = comments; } // Default constructor public Grade() { StudentID = 0;

MCT USE ONLY. STUDENT USE PROHIBITED

L4-2

Programming in Visual C#

AssessmentDate = DateTime.Now.ToString("d"); SubjectName = "Math"; Assessment = "A"; Comments = String.Empty; }

X Task 2: Convert the Students and Teachers structs into classes


1. 2. 3. In the Task List window, in the Categories list, click Comments.

Double-click the TODO: Exercise 1: Task 2a: Convert Student into a class, make the password property write-only, add the VerifyPassword method, and define constructors task. In the code editor, below the comment, modify the public struct Student declaration, replacing struct with class.
public class Student

4.

Delete the following line of code from the Student class.


public string Password {get; set;}

5.

Press Enter, and then type the following code:

private string _password = Guid.NewGuid().ToString(); // Generate a random password by default public string Password { set { _password = value; } } public bool VerifyPassword(string pass) { return (String.Compare(pass, _password) == 0); }

Note: An application should not be able to read passwords; only set them and verify that a password is correct. 6.

Click at the end of the code public string LastName { get; set; }, press Enter twice, and then type the following code:
// Constructor to initialize the properties of a new Student public Student(int studentID, string userName, string password, string firstName, string lastName, int teacherID) { StudentID = studentID; UserName = userName; Password = password; FirstName = firstName; LastName = lastName; TeacherID = teacherID; } // Default constructor public Student() { StudentID = 0; UserName = String.Empty; Password = String.Empty;

MCT USE ONLY. STUDENT USE PROHIBITED


L4-3

FirstName = String.Empty; LastName = String.Empty; TeacherID = 0; }

7. 8. 9.

In the Task List window, in the Categories list, click Comments.

Double-click the TODO: Exercise 1: Task 2b: Convert Teacher into a class, make the password property write-only, add the VerifyPassword method, and define constructors task. In the code editor, below the comment, modify the public struct Teacher declaration, replacing struct with class.
public class Teacher

10. Delete the following line of code:


public string Password {get; set;},

11. Press Enter and then type the following code:

private string _password = Guid.NewGuid().ToString(); // Generate a random password by default public string Password { set { _password = value; } } public bool VerifyPassword(string pass) { return (String.Compare(pass, _password) == 0); }

12. Click at the end of the code public string Class {get; set;}, press Enter twice, and then type the following code:
// Constructor to initialize the properties of a new Teacher public Teacher(int teacherID, string userName, string password, string firstName, string lastName, string className) { TeacherID = teacherID; UserName = userName; Password = password; FirstName = firstName; LastName = lastName; Class = className; } // Default constructor public Teacher() { TeacherID = 0; UserName = String.Empty; Password = String.Empty; FirstName = String.Empty; LastName = String.Empty; Class = String.Empty; }

MCT USE ONLY. STUDENT USE PROHIBITED

L4-4

Programming in Visual C#

X Task 3: Use the VerifyPassword method to verify the password when a user logs in
1. 2. In the Task List window, double-click the TODO: Exercise 1: Task 3a: Use the VerifyPassword method of the Teacher class to verify the teachers password task. In the code editor, below the comment, in the code for the teacher variable, modify the String.Compare(t.Password, password.Password) == 0 code to look like the following code:
t.VerifyPassword(password.Password)

3. 4.

In the Task List window, double-click the TODO: Exercise 1: Task 3b: Check whether teacher is null before examining the UserName property task. In the code editor, in the line below the comment, modify the if statement condition from !String.IsNullOrEmpty(teacher.UserName) to look like the following code:
teacher != null && !String.IsNullOrEmpty(teacher.UserName)

5. 6. 7. 8. 9.

In the Task List window, double-click the TODO: Exercise 1: Task 3c: Use the VerifyPassword method of the Student class to verify the students password task. In the code editor, below the comment, in the code for the student variable, modify the String.Compare(s.Password, password.Password) == 0 code to look like the following code: s.VerifyPassword(password.Password)

In the Task List window, double-click the TODO: Exercise 1: Task 3d: Check whether student is null before examining the UserName property task. In the code editor, in the line below the comment, modify the if statement condition from !String.IsNullOrEmpty(student.UserName) to look like the following code:
student != null && !String.IsNullOrEmpty(student.UserName)

X Task 4: Build and run the application, and verify that a teacher or student can still log on
1. 2. 3. 4. 5. 6. 7. 8. 9. On the Build menu, click Build Solution. On the Debug Menu, click Start Without Debugging. In the Username box, type vallee. In the Password box, type password, and then click Log on. Verify that the welcome screen appears, displaying the list of students Click Log off. In the Username box, delete the existing contents, type grubere, and then click Log on. Verify that the welcome screen appears, displaying the list of subjects and grades. Click Log off.

10. Close the application. 11. On the File menu, click Close Solution.

Results: After completing this exercise, the Teacher, Student, and Grade structs will be implemented as classes and the VerifyPassword method will be called when a user logs on.

MCT USE ONLY. STUDENT USE PROHIBITED


L4-5

MCT USE ONLY. STUDENT USE PROHIBITED

L4-6

Programming in Visual C#

Exercise 2: Adding Data Validation to the Grade Class


X Task 1: Create a list of valid subject names
1. 2. 3. 4. In Visual Studio, on the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click GradesPrototype.sln, and then click Open.

In the Task List window, double-click the TODO: Exercise 2: Task 1a: Define a List collection for holding the names of valid subjects task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
public static List<string> Subjects;

5. 6.

In the Task List window, double-click the TODO: Exercise 2: Task 1b: Populate the list of valid subjects with sample data task. In the code editor, in the blank line below the comment, type the following code:

Subjects = new List<string>() { "Math", "English", "History", "Geography", "Science" };

X Task 2: Add validation logic to the Grade class to check the data entered by the user
1. 2. In the Task List window, double-click the TODO: Exercise 2: Task 2a: Add validation to the AssessmentDate property task.

In the code editor under comment, delete the public string AssessmentDate { get; set; } code, and then type the following code:
private string _assessmentDate; public string AssessmentDate { get { return _assessmentDate; } set { DateTime assessmentDate; // Verify that the user has provided a valid date if (DateTime.TryParse(value, out assessmentDate)) { // Check that the date is no later than the current date if (assessmentDate > DateTime.Now) { // Throw an ArgumentOutOfRangeException if the date is after the current date throw new ArgumentOutOfRangeException("AssessmentDate", "Assessment date must be on or before the current date"); } // If the date is valid, then save it in the appropriate format _assessmentDate = assessmentDate.ToString("d"); } else { // If the date is not in a valid format then throw an ArgumentException throw new ArgumentException("AssessmentDate", "Assessment date is not recognized"); } }

MCT USE ONLY. STUDENT USE PROHIBITED


L4-7

3. 4.

In the Task List window, double-click the TODO: Exercise 2: Task 2b: Add validation to the SubjectName property task.

In the code editor, below the comment, delete the public string SubjectName { get; set; } code, and then type the following code:

private string _subjectName; public string SubjectName { get { return _subjectName; } set { // Check that the specified subject is valid if (DataSource.Subjects.Contains(value)) { // If the subject is valid store the subject name _subjectName = value; } else { // If the subject is not valid then throw an ArgumentException throw new ArgumentException("SubjectName", "Subject is not recognized"); } } }

5. 6.

In the Task List window, double-click the TODO: Exercise 2: Task 2c: Add validation to the Assessment property task. In the code editor, delete the public string Assessment { get; set; } code, and then type the following code:

private string _assessment; public string Assessment { get { return _assessment; } set { // Verify that the grade is in the range A+ to E// Use a regular expression: a single character in the range A-E at the start of the string followed by an optional + or at the end of the string Match matchGrade = Regex.Match(value, @"[A-E][+-]?$"); if (matchGrade.Success) { _assessment = value; } else { // If the grade is not valid then throw an ArgumentOutOfRangeException throw new ArgumentOutOfRangeException("Assessment", "Assessment grade must be in the range of A+ to E-"); } } }

MCT USE ONLY. STUDENT USE PROHIBITED

L4-8

Programming in Visual C#

X Task 3: Add a unit test to verify that the validations defined for the Grade class functions as expected.
1. 2. 3. 4. 5. 6. 7. On the File menu, point to Add, and then click New Project.

In the Add New Project dialog box, in the Installed templates list, expand Visual C#, click Test, and then in the Templates list, click Unit Test Project. In the Name box, type GradesTest, and then click OK. In Solution Explorer, right-click GradesTest, and then click Add Reference. In the Reference Manager GradesTest dialog box, expand Solution. Select the GradesPrototype check box, and then click OK.

In the code editor, in the UnitTest1 class, delete all of the existing code, and then type the following code:
[TestInitialize] public void Init() { // Create the data source (needed to populate the Subjects collection) GradesPrototype.Data.DataSource.CreateData(); } [TestMethod] public void TestValidGrade() { GradesPrototype.Data.Grade grade = new GradesPrototype.Data.Grade(1, "1/1/2012", "Math", "A-", "Very good"); Assert.AreEqual(grade.AssessmentDate, "1/1/2012"); Assert.AreEqual(grade.SubjectName, "Math"); Assert.AreEqual(grade.Assessment, "A-"); } [TestMethod] [ExpectedException(typeof(ArgumentOutOfRangeException))] public void TestBadDate() { // Attempt to create a grade with a date in the future GradesPrototype.Data.Grade grade = new GradesPrototype.Data.Grade(1, "1/1/2023", "Math", "A-", "Very good"); } [TestMethod] [ExpectedException(typeof(ArgumentException))] public void TestDateNotRecognized () { // Attempt to create a grade with an unrecognized date GradesPrototype.Data.Grade grade = new GradesPrototype.Data.Grade(1, "13/13/2012", "Math", "A-", "Very good"); } [TestMethod] [ExpectedException(typeof(ArgumentOutOfRangeException))] public void TestBadAssessment() { // Attempt to create a grade with an assessment outside the range A+ to EGradesPrototype.Data.Grade grade = new GradesPrototype.Data.Grade(1, "1/1/2012", "Math", "F-", "Terrible"); } [TestMethod] [ExpectedException(typeof(ArgumentException))] public void TestBadSubject() { // Attempt to create a grade with an unrecognized subject GradesPrototype.Data.Grade grade = new GradesPrototype.Data.Grade(1, "1/1/2012", "French", "B-", "OK");

MCT USE ONLY. STUDENT USE PROHIBITED


L4-9

8. 9.

On the Build menu, click Build Solution. On the Test menu, point to Run, and then click All Tests.

10. In the Test Explorer window, verify that all the tests are passed. 11. Close Test Explorer. 12. On the File menu, click Close Solution.

Results: After completing this exercise, the Grade class will contain validation logic.

MCT USE ONLY. STUDENT USE PROHIBITED

L4-10 Programming in Visual C#

Exercise 3: Displaying Students in Name Order


X Task 1: Run the application and verify that the students are not displayed in any specific order when logged on as a teacher
1. 2. 3. 4. 5. 6. 7. 8. In Visual Studio, on the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 3, click GradesPrototype.sln, and then click Open. On the Build menu, click Build Solution. On the Debug Menu, click Start Without Debugging. In the Username box, type vallee. In the Password box, type password, and then click Log on. Verify that the students are not displayed in any specific order. Close the application.

X Task 2: Implement the IComparable<Student> interface to enable comparison of students


1. 2.

In the Task List window, double-click the TODO: Exercise 3: Task 2a: Specify that the Student class implements the IComparable<Student> interface task. In the code editor, click at the end of the public class Student declaration, and then type the following code:
: IComparable<Student>

3. 4.

In the Task List window, double-click the TODO: Exercise 3: Task 2b: Compare Student objects based on their LastName and FirstName properties task. In the code editor, in the blank line below the comment, type the following code:
// Compare Student objects based on their LastName and FirstName properties public int CompareTo(Student other) { // Concatenate the LastName and FirstName of this student string thisStudentsFullName = LastName + FirstName; // Concatenate the LastName and FirstName of the "other" student string otherStudentsFullName = other.LastName + other.FirstName; // Use String.Compare to compare the concatenated names and return the result return(String.Compare(thisStudentsFullName, otherStudentsFullName)); }

X Task 3: Change the Students ArrayList collection into a List<Student> collection


1. 2. In the Task List window, double-click the TODO: Exercise 3: Task 3a: Change the Students collection into a List<Student> task.

In the code editor, below the comment, modify the public static ArrayList Students; code to look like the following code:
public static List<Student> Students;

3.

In the Task List window, double-click the TODO: Exercise 3: Task 3b: Populate the List<Student> collection task.

MCT USE ONLY. STUDENT USE PROHIBITED


L4-11

4.

In the code editor, below the comment, modify the Students = new ArrayList() code to look like the following code:
Students = new List<Student>()

X Task 4: Sort the data in the Students collection


1. 2.

In the Task List window, double-click the TODO: Exercise 3: Task 4a: Sort the data in the Students collection task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
DataSource.Students.Sort();

X Task 5: Verify that Students are retrieved and displayed in order of their first name and last name
1. 2. 3. 4. 5. 6. 7. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging. In the Username box, type vallee. In the Password box, type password, and then click Log on. Verify that the students are displayed in order of ascending last name. Log off and then close the application. On the File menu, click Close Solution.

Results: After completing this exercise, the application will display the students in alphabetical order of last name and then first name.

MCT USE ONLY. STUDENT USE PROHIBITED

L4-12 Programming in Visual C#

Exercise 4: Enabling Teachers to Modify Class and Grade Data


1. 2. 3. 4. In Visual Studio, on the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 4, click GradesPrototype.sln, and then click Open. In the Task List window, double-click the TODO: Exercise 4: Task 1a: Change the Teachers collection into a generic List task.

X Task 1: Change the Teachers and Grades collections to be generic List collections

In the code editor, below the comment, modify the code public static ArrayList Teachers; to look like the following code:
public static List<Teacher> Teachers;

5. 6.

In the Task List window, double-click the TODO: Exercise 4: Task 1b: Change the Grades collection into a generic List task. In the code editor, below the comment, modify the code public static ArrayList Grades; to look like the following code:
public static List<Grade> Grades;

7. 8.

In the Task List window, double-click the TODO: Exercise 4: Task 1c: Populate the Teachers collection task.

In the code editor, below the comment, modify the code Teachers = new ArrayList() to look like the following code:
Teachers = new List<Teacher>()

9.

In the Task List window, double-click the TODO: Exercise 4: Task 1d: Populate the Grades collection task.

10. In the code editor, below the comment, modify the code Grades = new ArrayList()to look like the following code:
Grades = new List<Grade>()

X Task 2: Add the EnrollInClass and RemoveFromClass methods for the Teacher class
1. 2.

In the Task List window, double-click the TODO: Exercise 4: Task 2a: Enroll a student in the class for this teacher task. In the code editor, click in the blank line below the comment, and then type the following code:

public void EnrollInClass(Student student) { // Verify that the student is not already enrolled in another class if (student.TeacherID ==0) { // Set the TeacherID property of the student student.TeacherID = TeacherID; } else { // If the student is already assigned to a class, throw an ArgumentException throw new ArgumentException("Student", "Student is already assigned to a class");

MCT USE ONLY. STUDENT USE PROHIBITED


L4-13

} }

3. 4.

In the Task List window, double-click the TODO: Exercise 4: Task 2b: Remove a student from the class for this teacher task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
// Remove a student from the class for this teacher public void RemoveFromClass(Student student) { // Verify that the student is actually assigned to the class for this teacher if (student.TeacherID == TeacherID) { // Reset the TeacherID property of the student student.TeacherID = 0; } else { // If the student is not assigned to the class for this teacher, throw an ArgumentException throw new ArgumentException("Student", "Student is not assigned to this class"); } }

5. 6.

In the Task List window, double-click the TODO: Exercise 4: Task 2c: Add a grade to a student (the grade is already populated) task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:

// Add a grade to a student (the grade is already populated) public void AddGrade(Grade grade) { // Verify that the grade does not belong to another student the StudentID should be zero if (grade.StudentID == 0) { // Add the grade to the students record grade.StudentID = StudentID; } else { // If the grade belongs to a different student, throw an ArgumentException throw new ArgumentException("Grade", "Grade belongs to a different student"); } }

X Task 3: Add code to enroll a student in a teachers class


1. 2. In the Task List window, double-click the TODO: Exercise 4: Task 3a: Enroll a student in the teachers class task.

In the code editor, below the comment, click in the blank line in the Student_Click method, and then type the following code:
try {

// Determine which student the user clicked // the StudentID is held in the Tag property of the Button that the user clicked Button studentClicked = sender as Button;

MCT USE ONLY. STUDENT USE PROHIBITED

L4-14 Programming in Visual C#

int studentID = (int)studentClicked.Tag; // Find this student in the Students collection Student student = (from s in DataSource.Students where s.StudentID == studentID select s).First(); // Prompt the user to confirm that they wish to add this student to their class string message = String.Format("Add {0} {1} to your class?", student.FirstName, student.LastName); MessageBoxResult reply = MessageBox.Show(message, "Confirm", MessageBoxButton.YesNo, MessageBoxImage.Question); // If the user confirms, add the student to their class if (reply == MessageBoxResult.Yes) { // Get the ID of the currently logged-on teacher int teacherID = SessionContext.CurrentTeacher.TeacherID; // Assign the student to this teachers class SessionContext.CurrentTeacher.EnrollInClass(student); // Refresh the display the new assigned student should disappear from the list of unassigned students Refresh(); } } catch (Exception ex) { MessageBox.Show(ex.Message, "Error enrolling student", MessageBoxButton.OK, MessageBoxImage.Error); }

3. 4.

In the Task List window, double-click the TODO: Exercise 4: Task 3b: Refresh the display of unassigned students task.

In the code editor, below the comment, click in the blank line in the Refresh method, and then type the following code:
// Find all unassigned students - they have a TeacherID of 0 var unassignedStudents = from s in DataSource.Students where s.TeacherID == 0 select s; // If there are no unassigned students, then display the "No unassigned students" message // and hide the list of unassigned students if (unassignedStudents.Count() == 0) { txtMessage.Visibility = Visibility.Visible; list.Visibility = Visibility.Collapsed; } else { // If there are unassigned students, hide the "No unassigned students" message // and display the list of unassigned students txtMessage.Visibility = Visibility.Collapsed; list.Visibility = Visibility.Visible; // Bind the ItemControl on the dialog to the list of unassigned students // The names of the students will appear in the ItemsControl on the dialog list.ItemsSource = unassignedStudents; }

5. 6.

In the Task List window, double-click the TODO: Exercise 4: Task 3c: Enroll a student in the teachers class task.

In the code editor, below the comment, click in the blank line in the EnrollStudent_Click method, and then type the following code:

// Use the AssignStudentDialog to display unassigned students and add them to the teachers class // All of the work is performed in the code behind the dialog AssignStudentDialog asd = new AssignStudentDialog(); asd.ShowDialog(); // Refresh the display to show any newly enrolled students Refresh();

X Task 4: Add code to enable a teacher to remove the student from the assigned class
1. 2.

In the Task List window, double-click the TODO: Exercise 4: Task 4a: Enable a teacher to remove a student from a class task.

In the code editor, below the comment, click in the blank line in the Remove_Click method, and then type the following code:
// If the user is not a teacher, do nothing (the button should not appear anyway) if (SessionContext.UserRole != Role.Teacher) { return; } try { // If the user is a teacher, ask the user to confirm that this student should be removed from their class string message = String.Format("Remove {0} {1}", SessionContext.CurrentStudent.FirstName, SessionContext.CurrentStudent.LastName); MessageBoxResult reply = MessageBox.Show(message, "Confirm", MessageBoxButton.YesNo, MessageBoxImage.Question); // If the user confirms, then call the RemoveFromClass method of the current teacher to remove this student from their class if (reply == MessageBoxResult.Yes) { SessionContext.CurrentTeacher.RemoveFromClass(SessionContext.CurrentStudent); // Go back to the previous page the student is no longer a member of the class for the current teacher if (Back != null) { Back(sender, e); } } } catch (Exception ex) { MessageBox.Show(ex.Message, "Error removing student from class", MessageBoxButton.OK, MessageBoxImage.Error); }

MCT USE ONLY. STUDENT USE PROHIBITED


L4-15

X Task 5: Add code to enable a teacher to add a grade to a student


1. 2.

In the Task List window, double-click the TODO: Exercise 4: Task 5a: Enable a teacher to add a grade to a student task.

In the code editor, below the comment, click in the blank line in the AddGrade_Click method, and then type the following code:
// If the user is not a teacher, do nothing (the button should not appear anyway) if (SessionContext.UserRole != Role.Teacher) { return; } try { // Use the GradeDialog to get the details of the assessment grade

MCT USE ONLY. STUDENT USE PROHIBITED

L4-16 Programming in Visual C#

GradeDialog gd = new GradeDialog(); // Display the form and get the details of the new grade if (gd.ShowDialog().Value) { // When the user closes the form, retrieve the details of the assessment grade from the form // and use them to create a new Grade object Grade newGrade = new Grade(); newGrade.AssessmentDate = gd.assessmentDate.SelectedDate.Value.ToString("d"); newGrade.SubjectName = gd.subject.SelectedValue.ToString(); newGrade.Assessment = gd.assessmentGrade.Text; newGrade.Comments = gd.comments.Text; // Save the grade to the list of grades DataSource.Grades.Add(newGrade); // Add the grade to the current student SessionContext.CurrentStudent.AddGrade(newGrade); // Refresh the display so that the new grade appears Refresh(); } } catch (Exception ex) { MessageBox.Show(ex.Message, "Error adding assessment grade", MessageBoxButton.OK, MessageBoxImage.Error); }

X Task 6: Run the application and verify that students can be added to and removed from classes, and that grades can be added to students
1. 2. 3. 4. 5. 6. 7. 8. 9. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging. In the Username box, type vallee. In the Password box, type password, and then click Log on. Click New Student. In the First Name box, type Darren. In the Last Name box, type Parker. In the Password box, type password, and then click OK. Click Enroll Student.

10. Verify that the Assign Student dialog box appears and that Darren Parker is in the list. 11. Click Darren Parker. 12. Verify that the Confirm message box appears, and then click Yes. 13. In the Assign Student dialog box, verify that Darren Parker disappears and that the text "No unassigned students" is displayed. 14. Click Close. 15. Verify that Darren Parker is added to the student list. 16. Click the student Kevin Liu. 17. Click Remove Student. 18. Verify that the Confirm message box appears, and then click Yes. 19. Verify that Kevin Liu is removed from the student list.

MCT USE ONLY. STUDENT USE PROHIBITED


L4-17

20. Click the student Darren Parker. 21. Click Add Grade. 22. Verify that the New Grade Details dialog box appears. 23. Verify that the Date box contains the current date. 24. In the Subject list, click English. 25. In the Assessment box, type B. 26. In the Comments box, type Good, and then click OK. 27. Verify that the grade information appears on the Report Card. 28. Click Log off. 29. In the Username box, type parkerd. 30. Click Log on.

31. Verify that the Welcome Darren Parker screen is displayed, showing the Report Card and the previously added grade. 32. Click Log off. 33. Close the application. 34. In Visual Studio, on the File menu, click Close Solution.

Results: After completing this exercise, the application will enable teachers to add and remove students from their classes, and to add grades to students.

MCT USE ONLY. STUDENT USE PROHIBITED

Module 5: Creating a Class Hierarchy by Using Inheritance

Lab: Refactoring Common Functionality into the User Class


Exercise 1: Creating and Inheriting from the User Base Class
X Task 1: Create the User abstract base class
1. 2. 3. Start the MSL-TMG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-05 virtual machine. Log on to Windows 8 as Student with password Pa$$w0rd Note: If necessary, click Switch User to display the list of users. 4. 5. 6. 7. 8. 9. Switch to the Windows 8 Start window. Click Visual Studio 2012. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click GradesPrototype.sln, and then click Open. In Visual Studio, on the View menu, click Task List. In the Task List window, in the Categories list, click Comments.

MCT USE ONLY. STUDENT USE PROHIBITED


L5-1

10. Double-click the TODO: Exercise 1: Task 1a: Create the User abstract class with the common functionality for Teachers and Students task.

11. In the code editor, click at the end of the comment, press Enter, and then type the following code:
public abstract class User {

12. Click at the end of the last comment in the block (before the Grade class declaration), press Enter, and then type the following code:
}

13. In the Task List window, double click the TODO: Exercise 1: Task 1b: Add the UserName property to the User class task. 14. In the code editor, click at the end of the comment, press Enter, and then type the following code:
public string UserName { get; set; }

15. In the Task List window, double click the TODO: Exercise 1: Task 1c: Add the Password property to the User class task. 16. In the code editor, click at the end of the comment, press Enter, and then type the following code:
private string _password = Guid.NewGuid().ToString(); // Generate a random password by default public string Password {

MCT USE ONLY. STUDENT USE PROHIBITED

L5-2

Programming in Visual C#

set { _password = value; } }

17. In the Task List window, double click the TODO: Exercise 1: Task 1d: Add the VerifyPassword method to the User class task. 18. In the code editor, click at the end of the comment, press Enter, and then type the following code:
public bool VerifyPassword(string pass) { return (String.Compare(pass, _password) == 0); }

X Task 2: Modify the Student and Teacher classes to inherit from the User class
1. 2. In the code editor, modify the statement below this comment as shown below in bold:
public class Student: User, IComparable<Student>

In the Task List window, double-click the TODO: Exercise 1: Task 2a: Inherit from the User class task.

3. 4.

In the Task List window, double-click the TODO: Exercise 1: Task 2b: Remove the UserName property (now inherited from User) task. In the code editor, delete the following statement from below the comment:
public string UserName { get; set; }

5. 6.

In the Task List window, double-click the TODO: Exercise 1: Task 2c: Remove the Password property (now inherited from User) task. In the code editor, delete the following block of code from below the comment:

private string _password = Guid.NewGuid().ToString(); // Generate a random password by default public string Password { set { _password = value; } }

7. 8.

In the Task List window, double-click the TODO: Exercise 1: Task 2d Remove the VerifyPassword method (now inherited from User) task. In the code editor, delete the following method from below the comment:
public bool VerifyPassword(string pass) { return (String.Compare(pass, _password) == 0); }

9.

In the Task List window, double-click the TODO: Exercise 1: Task 2e: Inherit from the User class task.

10. In the code editor, modify the statement below this comment as shown below in bold:
public class Teacher: User

11. In the Task List window, double-click the TODO: Exercise 1: Task 2f: Remove the UserName property (now inherited from User) task. 12. In the code editor, delete the following statement from below the comment:
public string UserName { get; set; }

13. In the Task List window, double-click the TODO: Exercise 1: Task 2g: Remove the Password property (now inherited from User) task. 14. In the code editor, delete the following block of code from below the comment:

private string _password = Guid.NewGuid().ToString(); // Generate a random password by default public string Password { set { _password = value; } }

15. In the Task List window, double-click the TODO: Exercise 1: Task 2h Remove the VerifyPassword method (now inherited from User) task. 16. In the code editor, delete the following method from below the comment:
public bool VerifyPassword(string pass) { return (String.Compare(pass, _password) == 0); }

MCT USE ONLY. STUDENT USE PROHIBITED


L5-3

X Task 3: Run the application and test the log on functionality


1. 2. 3. 4. 5. 6. 7. 8. 9. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging.

When the application starts, in the Username box, type vallee, in the Password box, type password, and then click Log on. Verify that the list of students for teacher Esther Valle is displayed.

Click Kevin Liu, and verify that the report card displaying the grades for Kevin Liu is displayed. Click Log off. In the Username box, type liuk, in the Password box, type password, and then click Log on. Verify that the report card showing the grades for Kevin Liu is displayed again. Click Log off.

10. Close the application. 11. In Visual Studio, on the File menu, click Close Solution.

Results: After completing this exercise, you should have removed the duplicated code from the Student and Teacher classes, and moved the code to an abstract base class called User.

MCT USE ONLY. STUDENT USE PROHIBITED

L5-4

Programming in Visual C#

Exercise 2: Implementing Password Complexity by Using an Abstract Method


X Task 1: Define the SetPassword abstract method
1. 2. 3. 4. 5. 6. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click GradesPrototype.sln, and then click Open. In Visual Studio, on the View menu, click Task List. In the Task List window, in the Categories list, click Comments.

Double-click the TODO: Exercise 2: Task 1a: Define an abstract method for setting the password task. In the code editor, review the comment below this line, click at the end of the comment, press Enter, and then type the following code:
public abstract bool SetPassword(string pwd);

7. 8.

In the Task List window, double-click the TODO: Exercise 2: Task 1b: Use the SetPassword method to set the password task. In the code editor, delete the following statement:
_password = value;

9.

Add the following block of code in the place of the statement that you just deleted:
if (!SetPassword(value)) { throw new ArgumentException("Password not complex enough", "Password"); }

X Task 2: Implement the SetPassword method in the Student and Teacher classes
1. 2.

In the Task List window, double-click the TODO: Exercise 2: Task 2a: Make _password a protected field rather than private task. In the code editor, modify the statement below the comment as shown below in bold:

protected string _password = Guid.NewGuid().ToString(); // Generate a random password by default

3. 4.

In the Task List window, double-click the TODO: Exercise 2: Task 2b: Implement SetPassword to set the password for the student task.

In the code editor, review the comment below this line, click at the end of the comment, press Enter, and then type the following code:
public override bool SetPassword(string pwd) { // If the password provided as the parameter is at least 6 characters long then save it and return true if (pwd.Length >= 6) { _password = pwd; return true; } // If the password is not long enough, then do not save it and return false return false; }

MCT USE ONLY. STUDENT USE PROHIBITED


L5-5

5. 6.

In the Task List window, double-click the TODO: Exercise 2: Task 2c: Implement SetPassword to set the password for the teacher task. In the code editor, review the comment below this line, click at the end of the comment, press Enter, and then type the following code:
public override bool SetPassword(string pwd) { // Use a regular expression to check that the password contains at least two numeric characters Match numericMatch = Regex.Match(pwd, @".*[0-9]+.*[0-9]+.*"); // If the password provided as the parameter is at least 8 characters long and contains at least two numeric characters then save it and return true if (pwd.Length >= 8 && numericMatch.Success) { _password = pwd; return true; } // If the password is not complex enough, then do not save it and return false return false; }

X Task 3: Set the password for a new student


1. 2.

In the Task List window, double-click the TODO: Exercise 2: Task 3a: Use the SetPassword method to set the password. task.

In the code editor, delete the statement below this comment and replace it with the following block of code:
if (!newStudent.SetPassword(sd.password.Text)) { throw new Exception("Password must be at least 6 characters long. Student not created"); }

X Task 4: Change the password for an existing user


1. 2. 3. On the Build menu, click Build Solution. In Solution Explorer, expand the GradesPrototype project, and then double-click MainWindow.xaml. In the XAML pane, scroll down to line 27 and review the following block of XAML code:
<Button Grid.Column="2" Margin="5" HorizontalAlignment="Right" Click="ChangePassword_Click"> <TextBlock Text="Change Password" FontSize="24"/> </Button>

4. 5. 6.

In Solution Explorer, expand MainWindow.xaml and then double-click MainWindow.xaml.cs. In the code editor, expand the Event Handlers region, and locate the ChangePassword_Click method. Review the code in this method:
private void ChangePassword_Click(object sender, EventArgs e) { // Use the ChangePasswordDialog to change the user's password ChangePasswordDialog cpd = new ChangePasswordDialog(); // Display the dialog if (cpd.ShowDialog().Value) {

MCT USE ONLY. STUDENT USE PROHIBITED

L5-6

Programming in Visual C#

// When the user closes the dialog by using the OK button, the password should have been changed // Display a message to confirm MessageBox.Show("Password changed", "Password", MessageBoxButton.OK, MessageBoxImage.Information); } }

7. 8. 9.

In Solution Explorer, expand Controls, and then double-click ChangePasswordDialog.xaml. In Solution Explorer, expand ChangePasswordDialog.xaml and then double-click ChangePasswordDialog.xaml.cs. Review the code in the ok_Click method:
// If the user clicks OK to change the password, validate the information that the user has provided private void ok_Click(object sender, RoutedEventArgs e) { // TODO: Exercise 2: Task 4a: Get the details of the current user // TODO: Exercise 2: Task 4b: Check that the old password is correct for the current user // TODO: Exercise 2: Task 4c: Check that the new password and confirm password fields are the same // TODO: Exercise 2: Task 4d: Attempt to change the password // If the password is not sufficiently complex, display an error message // Indicate that the data is valid this.DialogResult = true; }

10. In the Task List window, double-click the TODO: Exercise 2: Task 4a: Get the details of the current user task. 11. In the code editor, in the blank line below this comment, type the following code:
User currentUser; if (SessionContext.UserRole == Role.Teacher) { currentUser = SessionContext.CurrentTeacher; } else { currentUser = SessionContext.CurrentStudent; }

12. In the Task List window, double-click the TODO: Exercise 2: Task 4b: Check that the old password is correct for the current user task. 13. In the code editor, in the blank line below this comment, type the following code:
string oldPwd = oldPassword.Password; if (!currentUser.VerifyPassword(oldPwd)) { MessageBox.Show("Old password is incorrect", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; }

14. In the Task List window, double-click the TODO: Exercise 2: Task 4c: Check that the new password and confirm password fields are the same task. 15. In the code editor, in the blank line below this comment, type the following code:
string newPwd = newPassword.Password;

string confirmPwd = confirm.Password; if (String.Compare(newPwd, confirmPwd) != 0) { MessageBox.Show("The new password and confirm password fields are different", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; }

16. In the Task List window, double-click the TODO: Exercise 2: Task 4d: Attempt to change the password task. 17. In the code editor, review the comment below this line, click at the end of the comment, press Enter, and then type the following code:
if (!currentUser.SetPassword(newPwd)) { MessageBox.Show("The new password is not sufficiently complex", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; }

MCT USE ONLY. STUDENT USE PROHIBITED


L5-7

X Task 5: Run the application and test the change password functionality
1. 2. 3. 4. 5. 6. 7. 8. 9. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging. When the application starts, in the Username box, type vallee, in the Password box, type password99, and then click Log on. In The School of Fine Arts window, click Change Password.

In the Change Password Dialog window, in the Old Password box, type password99, in the New Password box, type pwd101, in the Confirm box, type pwd101, and then click OK.

Verify that the message The password is not sufficiently complex is displayed, and then click OK. In the New Password box, type password101, in the Confirm box, type password101, and then click OK. Verify that the message Password changed is displayed, and then click OK. Click Log off.

10. In the Username box, type vallee, in the Password box, type password101, and then click Log on. 11. Click New Student.

12. In the New Student Details window, in the First Name box, type Luka, in the Last Name box, type Abrus, in the Password box, type 1234, and then click OK. 13. Verify that the message Password must be at least 6 characters long. Student not created appears, and then click OK. 14. Click New Student.

15. In the New Student Details window, in the First Name box, type Luka, in the Last Name box, type Abrus, in the Password box, type abcdef, and then click OK. 16. Click Enroll Student. 17. In the Assign Student window, verify that the student Luka Abrus appears. 18. Click Close. 19. Click Log off.

MCT USE ONLY. STUDENT USE PROHIBITED

L5-8

Programming in Visual C#

20. Close the application. 21. In Visual Studio, on the File menu, click Close Solution.

Results: After completing this exercise, you should have implemented a polymorphic method named SetPassword that exhibits different behavior for students and teachers. You will also have modified the application to enable users to change their passwords.

MCT USE ONLY. STUDENT USE PROHIBITED


L5-9

Exercise 3: Creating the ClassFullException Custom Exception


X Task 1: Implement the ClassFullException class
1. 2. 3. 4. 5. 6. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 3, click GradesPrototype.sln, and then click Open. In Visual Studio, on the View menu, click Task List. In the Task List window, in the Categories list, click Comments.

Double-click the TODO: Exercise 3: Task 1a: Add custom data: the name of the class that is full task.

In the code editor, review the comment below this task, click at the end of the comment, press Enter, and then type the following code:
private string _className; public virtual string ClassName { get { return _className; } }

7. 8.

In the Task List window, double-click the TODO: Exercise 3: Task 1b: Delegate functionality for the common constructors directly to the Exception class task.

In the code editor, click at the end of the comment, press Enter, and then type the following code:
public ClassFullException() { } public ClassFullException(string message) : base(message) { } public ClassFullException(string message, Exception inner) : base(message, inner) { }

9.

In the Task List window, double-click the TODO: Exercise 3: Task 1c: Add custom constructors that populate the _className field. task.

10. In the code editor, review the comment below this task, click at the end of the comment, press Enter, and then type the following code:
public ClassFullException(string message, string cls) : base(message) { _className = cls; } public ClassFullException(string message, string cls, Exception inner) : base(message, inner) { _className = cls; }

X Task 2: Throw and catch the ClassFullException


1.

In the Task List window, double-click the TODO: Exercise 3: Task 2a: Set the maximum class size for any teacher task.

MCT USE ONLY. STUDENT USE PROHIBITED

L5-10 Programming in Visual C#

2.

In the code editor, click at the end of the comment, press Enter, and then type the following code:
private const int MAX_CLASS_SIZE = 8;

3. 4.

In the Task List window, double-click the TODO: Exercise 3: Task 2b: If the class is already full, then another student cannot be enrolled task.

In the code editor, review the comment below this task, click at the end of the comment, press Enter, and then type the following code:
if (numStudents == MAX_CLASS_SIZE) { // Throw a ClassFullException and specify the class that is full throw new ClassFullException("Class full: Unable to enroll student", Class); }

5. 6.

In the Task List window, double-click the TODO: Exercise 3: Task 2c: Catch and handle the ClassFullException task.

In the code editor, click at the end of the comment, press Enter, and then type the following code:
catch (ClassFullException cfe) { MessageBox.Show(String.Format("{0}. Class: {1}", cfe.Message, cfe.ClassName), "Error enrolling student", MessageBoxButton.OK, MessageBoxImage.Error); }

X Task 3: Build and test the solution


1. 2. 3. 4. 5. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging. When the application starts, in the Username box, type vallee, in the Password box, type password99, and then click Log on. In The School of Fine Arts window, click New Student. In the New Student Details window, enter the following details, and then click OK. Value Walter Harp abcdef

Field First Name Last Name Password

Note: New students will not be listed in the main application window because this displays students in the users class, and the new students have yet to be assigned to a class. 6. 7. In The School of Fine Arts window, click New Student. In the New Student Details window, enter the following details, and then click OK.

MCT USE ONLY. STUDENT USE PROHIBITED


L5-11

Field First Name Last Name Password 8. 9.

Value Andrew Harris abcdef

In The School of Fine Arts window, click New Student. In the New Student Details window, enter the following details, and then click OK. Value Toni Poe abcdef

Field First Name Last Name Password

10. In The School of Fine Arts window, click New Student. 11. In the New Student Details window, enter the following details, and then click OK. Field First Name Last Name Password Value Ben Andrews abcdef

12. In The School of Fine Arts window, click Enroll Student. 13. In the Assign Student window, click Walter Harp. 14. In the Confirm message box, click Yes. 15. In the Assign Student window, click Andrew Harris. 16. In the Confirm message box, click Yes. 17. In the Assign Student window, click Toni Poe. 18. In the Confirm message box, click Yes. 19. In the Assign Student window, click Ben Andrews. 20. In the Confirm message box, click Yes.

21. Verify that the message Class full: Unable to enroll student: Class: 3C is displayed, and then click OK. 22. In the Assign Student window, click Close. 23. Click Log off. 24. Close the application.

MCT USE ONLY. STUDENT USE PROHIBITED

L5-12 Programming in Visual C#

25. In Visual Studio, on the File menu, click Close Solution.

Results: After completing this exercise, you should have created a new custom exception class and used it to report when too many students are enrolled in a class.

MCT USE ONLY. STUDENT USE PROHIBITED


L06-1

Module 06: Reading and Writing Local Data

Lab: Generating the Grades Report


Exercise 1: Serializing Data for the Grades Report as XML
X Task 1: Prompt the user for a filename and retrieve the grade data
1. 2. 3. Start the MSL-TMG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-06 virtual machine. Log on to Window 8 as Student with the password Pa$$w0rd. Note: If necessary, click Switch User to display the list of users. 4. 5. 6. 7. 8. 9. Switch to the Windows 8 Start window. Click Visual Studio 2012. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click GradesPrototype.sln, and then click Open. In Solution Explorer, expand GradesPrototype, expand Views, and then double-click StudentProfile.xaml.

Note that this view displays and enables users to add grades for a student. The solution has been updated to include a Save Report button that users will click to generate and save the Grades Report.

10. On the View menu, click Task List. 11. In the Task List window, in the Categories list, click Comments.

12. Double-click the TODO: Exercise 1: Task 1a: Use a SaveFileDialog to prompt the user for a filename to save the report as (must be an XML file) task. 13. In the code editor, click in the blank line below the comment, and then type the following code:
SaveFileDialog dialog = new SaveFileDialog(); dialog.Filter = "XML documents|*.xml"; dialog.FileName = "Grades"; dialog.DefaultExt = ".xml"; Nullable<bool> result = dialog.ShowDialog(); if (result.HasValue && result.Value) {

14. Click at the end of the last comment in this method, press Enter, and then type the following code:
}

15. In the Task List window, double-click the TODO: Exercise 1: Task 1b: Get the grades for the currently selected student task. 16. In the code editor, click in the blank line below the comment, and then type the following code:
List<Grade> grades = (from g in DataSource.Grades where g.StudentID == SessionContext.CurrentStudent.StudentID

MCT USE ONLY. STUDENT USE PROHIBITED

L06-2 Programming in Visual C#

select g).ToList();

17. In the Task List window, double-click the TODO: Exercise 1: Task 1c: Serialize the grades to a MemoryStream task.

18. In the code editor, click at the end of the comment, press Enter, and then type the following code:
MemoryStream ms = FormatAsXMLStream(grades);

X Task 2: Serialize the grade data to a memory stream


1. 2.

In the Task List window, double-click the TODO: Exercise 1: Task 2a: Save the XML document to a MemoryStream by using an XmlWriter task. In the code editor, click in the blank line below the comment, and then type the following code:
MemoryStream ms = new MemoryStream(); XmlWriter writer = XmlWriter.Create(ms);

3. 4.

In the Task List window, double-click the TODO: Exercise 1: Task 2b: Create the root node of the XML document. task. In the code editor, click in the blank line below this and the next comment, and then type the following code:
writer.WriteStartDocument(); writer.WriteStartElement("Grades"); writer.WriteAttributeString("Student", String.Format("{0} {1}", SessionContext.CurrentStudent.FirstName, SessionContext.CurrentStudent.LastName));

5. 6.

In the Task List window, double-click the TODO: Exercise 1: Task 2c: Format the grades for the student and add them as child elements of the root node task. In the code editor, click in the blank line below this and the next comment, and then type the following code:
foreach (Grade grade in grades) { writer.WriteStartElement("Grade"); writer.WriteAttributeString("Date", grade.AssessmentDate); writer.WriteAttributeString("Subject", grade.SubjectName); writer.WriteAttributeString("Assessment", grade.Assessment); writer.WriteAttributeString("Comments", grade.Comments); writer.WriteEndElement(); }

7. 8.

In the Task List window, double-click the TODO: Exercise 1: Task 2d: Finish the XML document with the appropriate end elements task. In the code editor, click in the blank line below the comment, and then type the following code:
writer.WriteEndElement(); writer.WriteEndDocument();

9.

In the Task List window, double-click the TODO: Exercise 1: Task 2e: Flush the XmlWriter and close it to ensure that all the data is written to the MemoryStream task.

10. In the code editor, click in the blank line below the comment, and then type the following code:
writer.Flush(); writer.Close();

11. In the Task List window, double-click the TODO: Exercise 1: Task 2f: Reset the MemoryStream so it can be read from the start and then return it task. 12. In the code editor, click in the blank line below the comment, and then type the following code:
ms.Seek(0, SeekOrigin.Begin); return ms;

MCT USE ONLY. STUDENT USE PROHIBITED


L06-3

13. Delete the following line of code from the end of the method:
throw new NotImplementedException();

X Task 3: Debug the application


1. 2. 3. On the Build menu, click Build Solution. In the Task List window, double-click the TODO: Exercise 1: Task 1c: Serialize the grades to a MemoryStream task. In the code editor, select the closing brace immediately below the following line of code:
MemoryStream ms = FormatAsXMLStream(grades);

4. 5. 6. 7. 8. 9.

On the Debug menu, click Toggle Breakpoint. On the Debug menu, click Start Debugging. In the Username box, type vallee. In the Password box, type password99, and then click Log on. In the main application window, click Kevin Liu. In the Report Card view, click Save Report.

10. In the Save As dialog box, click Save. Note: You will write the code to actually save the report to disk in Exercise 3 of this lab.

11. When you enter Break Mode, in the Immediate Window, type the following code, and then press Enter.
?(new StreamReader(ms)).ReadToEnd()

12. Review the grade data formatted as XML that is returned to the Immediate Window. 13. On the Debug menu, click Stop Debugging. 14. On the Debug menu, click Delete All Breakpoints 15. In the confirmation message box, click Yes. 16. On the File menu, click Close Solution.

Results: After completing this exercise, users will be able to specify the location for the Grades Report file.

MCT USE ONLY. STUDENT USE PROHIBITED

L06-4 Programming in Visual C#

Exercise 2: Previewing the Grades Report


X Task 1: Display the string to the user in a message box
1. 2. 3. 4. 5. 6. 7. 8. 9. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click GradesPrototype.sln, and then click Open. On the View menu, click Task List. In the Task List window, in the Categories list, click Comments.

Double-click the TODO: Exercise 2: Task 1a: Generate a string representation of the report data task. In the code editor, click in the blank line below the comment, and then type the following code: string formattedReportData = FormatXMLData(ms);

In the Task List window, double-click the TODO: Exercise 2: Task 1b: Preview the string version of the report data in a MessageBox task. In the code editor, click in the blank line below the comment, and then type the following code:
MessageBox.Show(formattedReportData, "Preview Report", MessageBoxButton.OK, MessageBoxImage.Information);

X Task 2: Build a string representation of the XML document


1. 2.

In the Task List window, double-click the TODO: Exercise 2: Task 2a: Use a StringBuilder to construct the string task. In the code editor, click in the blank line below the comment, and then type the following code: StringBuilder builder = new StringBuilder();

3. 4.

In the Task List window, double-click the TODO: Exercise 2: Task 2b: Use an XmlTextReader to read the XML data from the stream task. In the code editor, click in the blank line below the comment, and then type the following code:
XmlTextReader reader = new XmlTextReader(stream);

5. 6.

In the Task List window, double-click the TODO: Exercise 2: Task 2c: Read and process the XML data a node at a time task. In the code editor, click in the blank line below the comment, and then type the following code:
while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.XmlDeclaration: // The node is an XML declaration such as <?xml version='1.0'> builder.Append(String.Format("<?{0} {1}>\n", reader.Name, reader.Value)); break; case XmlNodeType.Element: // The node is an element (enclosed between '<' and '/>') builder.Append(String.Format("<{0}", reader.Name)); if (reader.HasAttributes) { // Output each of the attributes of the element in the form "name='value'"

MCT USE ONLY. STUDENT USE PROHIBITED


L06-5

while (reader.MoveToNextAttribute()) { builder.Append(String.Format(" {0}='{1}'", reader.Name, reader.Value)); } } builder.Append(">\n"); break; case XmlNodeType.EndElement: // The node is the closing tag at the end of an element builder.Append(String.Format("</{0}>", reader.Name)); break; } }

7. 8.

In the Task List window, double-click the TODO: Exercise 2: Task 2d: Reset the stream and return the string containing the formatted data task. In the code editor, click in the blank line below the comment, and then type the following code:
stream.Seek(0, SeekOrigin.Begin); return builder.ToString();

9.

Delete the following line of code from the end of the method:
throw new NotImplementedException();

X Task 3: Run the application and preview the data.


1. 2. 3. 4. 5. 6. 7. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging. In the Username box, type vallee. In the Password box, type password99, and then click Log on. In the main application window, click Kevin Liu. In the Report Card view, click Save Report. In the Save As dialog box, click Save. Note: You will write the code to actually save the report to disk in the next exercise of this lab. 8. 9. Review the XML data displayed in the message box, and then click OK. Close the application.

10. In Visual Studio, on the File menu, click Close Solution.

Results: After completing this exercise, users will be able to preview a report before saving it.

MCT USE ONLY. STUDENT USE PROHIBITED

L06-6 Programming in Visual C#

Exercise 3: Persisting the Serialized Grade Data to a File


X Task 1: Save the XML document to disk
1. 2. 3. 4. 5. 6. 7. 8. 9. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 3, click GradesPrototype.sln, and then click Open. On the View menu, click Task List. In the Task List window, in the Categories list, click Comments.

Double-click the TODO: Exercise 3: Task 1a: Modify the message box and ask the user whether they wish to save the report task. In the code editor, delete the line of code below the comment, and then type the following code: MessageBoxResult reply = MessageBox.Show(formattedReportData, "Save Report?", MessageBoxButton.YesNo, MessageBoxImage.Question);

In the Task List window, double-click the TODO: Exercise 3: Task 1b: If the user says yes, then save the data to the file that the user specified earlier task. In the code editor, click at the end of the comment, press Enter, and then type the following code:

if (reply == MessageBoxResult.Yes) { // If the user says yes, then save the data to the file that the user specified earlier // If the file already exists it will be overwritten (the SaveFileDialog box will already have asked the user whether this is OK) FileStream file = new FileStream(dialog.FileName, FileMode.Create, FileAccess.Write); ms.CopyTo(file); file.Close(); }

X Task 2: Run the application and verify that the XML document is saved correctly
1. 2. 3. 4. 5. 6. 7. 8. 9. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging. In the Username box, type vallee. In the Password box, type password99, and then click Log on. In the main application window, click Kevin Liu. In the Report Card view, click Save Report. In the Save As dialog box, browse to the Documents folder, and then click Save. Review the XML data displayed in the message box, and then click Yes. Close the application.

10. Open Internet Explorer. 11. Press the Alt key, and then on the File menu, click Open. 12. In the Open dialog box, click Browse.

13. In the Windows Internet Explorer dialog box, browse to the Documents folder, click Grades.xml, and then click Open.

MCT USE ONLY. STUDENT USE PROHIBITED


L06-7

14. In the Open dialog box, click OK. 15. Verify that the file contains the expected grade data, and then close Internet Explorer. 16. In Visual Studio, on the File menu, click Close Solution.

Results: After completing this exercise, users will be able to save student reports to the local hard disk in XML format.

MCT USE ONLY. STUDENT USE PROHIBITED

MCT USE ONLY. STUDENT USE PROHIBITED


L7-1

Module 7: Accessing a Database

Lab: Retrieving and Modifying Grade Data


Exercise 1: Creating an Entity Data Model from The School of Fine Arts Database
X Task 1: Build and generate an EDM by using a table from the SchoolGradesDB database
1. 2. 3. Start the MSL-TMG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-07 virtual machine. Log on to Windows 8 as Student with the password Pa$$w0rd.

Note: If necessary, click Switch User to display a list of users in the Windows 8 logon screen. 4. 5. 6. 7. 8. 9. Switch to the Windows 8 Start window. Click Visual Studio 2012. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click GradesPrototype.sln, and then click Open. On the File menu, point to Add, and then click New Project.

In the Add New Project dialog box, in the templates list, click Class Library, in the Name box, type Grades.DataModel, and then click OK.

10. On the Project menu, click Add New Item.

11. In the Add New Item Grades.DataModel dialog box, in the templates list, click ADO.NET Entity Data Model, in the Name box, type GradesModel, and then click Add. 12. In the Entity Data Model Wizard, on the Choose Model Contents page, click Generate from database, and then click Next. 13. On the Choose Your Data Connection page, click New Connection.

14. If the Choose Data Source dialog box appears, in the Data source list, click Microsoft SQL Server, and then click Continue.

15. In the Connection Properties dialog box, in the Server name box, type (localdb)\v11.0, in the Select or enter a database name list, click SchoolGradesDB, and then click OK. 16. In the Entity Data Model Wizard, on the Choose Your Data Connection page, click Next.

17. On the Choose Your Database Objects and Settings page, expand Tables, expand dbo, select the following tables, and then click Finish: Grades Students Subjects

MCT USE ONLY. STUDENT USE PROHIBITED

L7-2

Programming with Visual C#

Teachers Users

18. If the Security Warning dialog box appears, click Do not show this message again, and then click OK. 19. On the Build menu, click Build Solution.

X Task 2: Review the generated code


1. 2. 3. 4. 5. 6. 7. 8. 9. In the designer window, review the entities that have been generated. Review the properties and navigation properties of the Grade entity. Right-click the heading of the Grade entity, and then click Table Mapping.

In the Mapping Details Grade pane, review the mappings between the columns in the database table and the properties of the entity. In Solution Explorer, expand GradesModel.edmx, expand GradesModel.Context.tt, and then double-click GradesModel.Context.cs. In the code window, note that the wizard has created a DbContext object named SchoolGradesDBEntities. In Solution Explorer, expand GradesModel.tt, and then double-click Grade.cs. Note that the wizard has created one property for each column in the Grades database table. On the File menu, click Save All.

10. On the File menu, click Close Solution.

Results: After completing this exercise, the prototype application should include an EDM that you can use to access The School of Fine Arts database.

MCT USE ONLY. STUDENT USE PROHIBITED


L7-3

Exercise 2: Updating Student and Grade Data by Using the Entity Framework
X Task 1: Display grades for the current student
1. 2. 3. 4. 5. 6. 7. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click GradesPrototype.sln, and then click Open. In Solution Explorer, right-click GradesPrototype, and then click Set as StartUp Project. On the View menu, click Task List. In the Task List window, in the Categories List, click Comments. Double-click the TODO: Exercise 2: Task 1a: Find all the grades for the student. task.

In the code editor, click in the blank line below the comment, and then type the following code:
List<Grades.DataModel.Grade> grades = new List<Grades.DataModel.Grade>(); foreach (Grades.DataModel.Grade grade in SessionContext.DBContext.Grades) { if (grade.StudentUserId == SessionContext.CurrentStudent.UserId) { grades.Add(grade); } }

8. 9.

In the Task List window, double-click the TODO: Exercise 2: Task 1b: Display the grades in the studentGrades ItemsControl by using databinding. task.

In the code editor, click in the blank line below the comment, and then type the following code:
studentGrades.ItemsSource = grades;

10. On the Build menu, click Build Solution. 11. On the Debug menu, click Start Without Debugging.

12. When the application loads, in the Username box, type vallee, and in the Password box, type password99, and then click Log on. 13. In the Class 3C view, click Kevin Liu. 14. Verify that Kevin Lius grades are listed.

15. Note that the subject column uses the subject ID rather than the subject name, and then close the application.

X Task 2: Display the subject name in the UI


1. 2.

In Visual Studio, in the Task List window, double-click the TODO: Exercise 2: Task 2a: Convert the subject ID provided in the value parameter. task. In the code editor, click in the blank line below the comment, and then type the following code:
int subjectId = (int)value; var subject = SessionContext.DBContext.Subjects.FirstOrDefault(s => s.Id == subjectId);

3.

In the Task List window, double-click the TODO: Exercise 2: Task 2b: Return the subject name or the string N/A. task.

MCT USE ONLY. STUDENT USE PROHIBITED

L7-4

Programming with Visual C#

4.

In the code editor, delete the following line of code:


return value;

5.

In the code editor, click in the blank line below the comment, and then type the following code:
return subject.Name != string.Empty ? subject.Name : "N/A";

X Task 3: Display the GradeDialog view and use the input to add a new grade
1. 2.

In the Task List window, double-click the TODO: Exercise 2: Task 3a: Use the GradeDialog to get the details of the new grade. task. In the code editor, click in the blank line below the comment, and then type the following code:
GradeDialog gd = new GradeDialog();

3. 4.

In the Task List window, double-click the TODO: Exercise 2: Task 3b: Display the form and get the details of the new grade. task. In the code editor, click in the blank line below the comment, and then type the following code:
if (gd.ShowDialog().Value) {

5.

Click in the blank line below the final TODO comment in this try block, and then type the following code:
}

6.

In the Task List window, double-click the TODO: Exercise 2: Task 3c: When the user closes the form, retrieve the details of the assessment grade from the form and use them to create a new Grade object. task. In the code editor, click in the blank line below the comment, and then type the following code:
Grades.DataModel.Grade newGrade = new Grades.DataModel.Grade(); newGrade.AssessmentDate = gd.assessmentDate.SelectedDate.Value; newGrade.SubjectId = gd.subject.SelectedIndex; newGrade.Assessment = gd.assessmentGrade.Text; newGrade.Comments = gd.comments.Text; newGrade.StudentUserId = SessionContext.CurrentStudent.UserId;

7.

8. 9.

In the Task List window, double-click the TODO: Exercise 2: Task 3d: Save the grade. task. In the code editor, click in the blank line below the comment, and then type the following code:
SessionContext.DBContext.Grades.Add(newGrade); SessionContext.Save();

10. In the Task List window, double-click the TODO: Exercise 2: Task 3e: Refresh the display so that the new grade appears. task. 11. In the code editor, click at the end of the comment, press Enter, and then type the following code:
Refresh();

X Task 4: Run the application and test the grade-adding functionality


1. On the Build menu, click Build Solution.

MCT USE ONLY. STUDENT USE PROHIBITED


L7-5

2. 3. 4. 5. 6. 7. 8. 9.

On the Debug menu, click Start Without Debugging.

When the application loads, in the Username box, type vallee, and in the Password box, type password99, and then click Log on. In the Class 3C view, click Kevin Liu. Verify that the list of grades now displays the subject name, not the subject ID. In the Report Card view, click Add Grade.

In the New Grade Details dialog box, in the Subject list, click Geography, in the Assessment box, type A+, in the Comments box, type Well done!, and then click OK. Verify that the new grade is added to the list, and then close the application. In Visual Studio, on the File menu, click Close Solution.

Results: After completing this exercise, users will be see the grades for the current student and add new grades.

MCT USE ONLY. STUDENT USE PROHIBITED

L7-6

Programming with Visual C#

Exercise 3: Extending the Entity Data Model to Validate Data


X Task 1: Throw the ClassFullException exception
1. 2. 3. 4. 5. 6. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 3, click GradesPrototype.sln, and then click Open. In Solution Explorer, right-click GradesPrototype, and then click Set as StartUp Project. In Solution Explorer, right-click Grades.DataModel, point to Add, and then click Class.

In the Add New Item Grades.DataModel dialog box, in the Name box, type customTeacher.cs, and then click Add. In the code editor, modify the class declaration as shown in the following code:
public partial class Teacher

7.

In the code editor, in the Teacher class, type the following code:
private const int MAX_CLASS_SIZE = 8;

8.

In the code editor, in the Teacher class, type the following code:

public void EnrollInClass(Student student) { // Verify that this teacher's class is not already full. // Determine how many students are currently in the class. int numStudents = (from s in Students where s.TeacherUserId == UserId select s).Count(); // If the class is already full, another student cannot be enrolled. if (numStudents >= MAX_CLASS_SIZE) { // So throw a ClassFullException and specify the class that is full. throw new ClassFullException("Class full: Unable to enroll student", Class); } // Verify that the student is not already enrolled in another class. if (student.TeacherUserId == null) { // Set the TeacherID property of the student. student.TeacherUserId = UserId; } else { // If the student is already assigned to a class, throw an ArgumentException. throw new ArgumentException("Student", "Student is already assigned to a class"); } }

9.

In the Task List window, double-click the TODO: Exercise 3: Task 1a: Call the EnrollInClass method to assign the student to this teachers class. task.

10. In the code editor, click in the blank line below the comment, and then type the following code:
SessionContext.CurrentTeacher.EnrollInClass(student);

11. In the Task List window, double-click the TODO: Exercise 3: Task 1b: Save the updated student/class information back to the database. task.

12. In the code editor, click in the blank line below the comment, and then type the following code:
SessionContext.Save();

X Task 2: Add validation logic for the Assessment and AssessmentDate properties
1. 2. 3. In Solution Explorer, right-click Grades.DataModel, point to Add, and then click Class.

In the Add New Item Grades.DataModel dialog box, in the Name box, type customGrade.cs, and then click Add. In the code editor, modify the class declaration as shown in the following code:
public partial class Grade

MCT USE ONLY. STUDENT USE PROHIBITED


L7-7

4.

In the code editor, in the Grade class, type the following code:
public { // // if { date. bool ValidateAssessmentDate(DateTime assessmentDate) Verify that the user has provided a valid date. Check that the date is no later than the current date. (assessmentDate > DateTime.Now) // Throw an ArgumentOutOfRangeException if the date is after the current

throw new ArgumentOutOfRangeException("Assessment Date", "Assessment date must be on or before the current date"); } else { return true; } }

5.

In the code editor, below the existing using directives, type the following code:
using System.Text.RegularExpressions;

6.

In the code editor, in the Grade class, type the following code:

public bool ValidateAssessmentGrade(string assessment) { // Verify that the grade is in the range A+ to E-. // Use a regular expression: A single character in the range A-E at the start of the string followed by an optional + or - at the end of the string. Match matchGrade = Regex.Match(assessment, @"^[A-E][+-]?$"); if (!matchGrade.Success) { // If the grade is not valid, throw an ArgumentOutOfRangeException. throw new ArgumentOutOfRangeException("Assessment", "Assessment grade must be in the range A+ to E-"); } else { return true; } }

7. 8.

In the Task List window, double-click the TODO: Exercise 3: Task 2a: Create a Grade object. task.

In the code editor, click in the blank line below the comment, and then type the following code:
Grades.DataModel.Grade testGrade = new Grades.DataModel.Grade();

MCT USE ONLY. STUDENT USE PROHIBITED

L7-8

Programming with Visual C#

9.

In the Task List window, double-click the TODO: Exercise 3: Task 2b: Call the ValidateAssessmentDate method. task.

10. In the code editor, click in the blank line below the comment, and then type the following code:
testGrade.ValidateAssessmentDate(assessmentDate.SelectedDate.Value);

11. In the Task List window, double-click the TODO: Exercise 3: Task 2c: Call the ValidateAssessmentGrade. task. 12. In the code editor, click in the blank line below the comment, and then type the following code:
testGrade.ValidateAssessmentGrade(assessmentGrade.Text);

X Task 3: Run the application and test the validation logic


1. 2. 3. 4. 5. 6. 7. 8. 9. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging. When the application loads, in the Username box, type vallee, and in the Password box, type password99, and then click Log on. When the application loads, click Enroll Student.

In the Assign Student dialog box, click Eric Gruber, in the Confirm message box, click Yes, and then in the Error enrolling student message box, click OK. In the Assign Student dialog box, click Close. In the Class 3C view, click Kevin Liu, and then click Add Grade.

In the New Grade Details dialog box, in the Date box, type tomorrows date, and then click OK. In the Error creating assessment message box, click OK.

10. In the New Grade Details dialog box, in the Date box, type 8/19/2012, in the Assessment box, type F+, and then click OK. 11. In the Error creating assessment message box, click OK.

12. In the New Grade Details dialog box, in the Assessment box, type A+, in the Comments box, type Well done!, and then click OK. 13. Verify that the new grade is added to the list, and then close the application. 14. In Visual Studio, on the File menu, click Close Solution.

Results: After completing this exercise, the application will raise and handle exceptions when invalid data is entered.

MCT USE ONLY. STUDENT USE PROHIBITED


L08-1

Module 08: Accessing Remote Data

Lab: Retrieving and Modifying Grade Data in the Cloud


Exercise 1: Creating a WCF Data Service for the SchoolGrades Database
X Task 1: Create the Grades.Web project
1. 2. Start the 20483A-SEA-DEV11-08 virtual machine. Log on to Windows 8 as Student with the password Pa$$w0rd.

Note: If necessary, click Switch User to display a list of users in the Windows 8 logon screen. 3. 4. 5. 6. 7. 8. 9. Switch to the Windows 8 Start window. Click Visual Studio 2012.

In Microsoft Visual Studio, on the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click GradesPrototype.sln, and then click Open.

In Solution Explorer, right-click the GradesPrototype solution, point to Add, and then click New Project. In the Add New Project dialog box, in the left pane expand Visual C#, and then click Web. In the templates list, click ASP.NET Empty Web Application.

10. In the Name box, type Grades.Web, and then click OK. 11. In Solution Explorer, right-click the Grades.Web project, and then click Properties.

12. On the Web tab, in the Start Action section, click Dont open a page. Wait for a request from an external application. 13. In the Servers section, ensure that Use Local IIS Web server is selected. 14. In the Project Url box, type http://localhost:1650/, and then click Create Virtual Directory. 15. In the Microsoft Visual Studio dialog box, click OK.

16. In Solution Explorer, right-click the GradesPrototype solution, and then click Set StartUp Projects. 17. In the Solution 'GradesPrototype' Property Pages dialog box, click Multiple startup projects. 18. In the Action column for Grades.Web and GradesPrototype, click Start, and then click OK. 19. On the File menu, click Save All.

X Task 2: Add a data service to the Grades.Web project


1. 2. 3. 4. Delete the existing folder name, type Services, and then press Enter. Right-click Services, point to Add, and then click New Item. In the templates list, click WCF Data Service.

In Solution Explorer, right-click the Grades.Web project, point to Add, and then click New Folder.

MCT USE ONLY. STUDENT USE PROHIBITED

L08-2 Programming in Visual C#

5. 6. 7. 8. 9.

In the Name box, type GradesWebDataService, and then click Add. Right-click Grades.Web, and then click Add Reference. In the Reference Manager Grades.Web dialog box, expand Solution, and then select Grades.DataModel. Click Browse.

In the Select the files to reference dialog box, browse to the E:\Labfiles\Starter\Exercise 1\packages\EntityFramework.5.0.0\lib\net45 folder, click EntityFramework.dll, and then click Add.

10. In the Reference Manager Grades.Web dialog box, click OK. 11. In Solution Explorer, expand the GradesPrototype project, and then double-click App.config. 12. In the code editor, copy the following XML to the clipboard:

<connectionStrings> <add name="GradesDBEntities" connectionString="metadata=res://*/GradesModel.csdl|res://*/GradesModel.ssdl|res://*/ GradesModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=(localdb)\v11.0;initial catalog=SchoolGradesDB;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" /> </connectionStrings>

13. In Solution Explorer, in the Grades.Web project, double-click Web.config.

14. Click at the end of the opening <configuration> element, press Enter, and then paste the contents of the clipboard.

X Task 3: Specify the GradesDBEntities data context for the data service
1. 2. In Solution Explorer, in Grades.Web, expand Services, and then double-click GradesWebDataService.svc.

In the code editor, click at the end of the using System.Web; code, press Enter, and then type the following code:
using Grades.DataModel;

3. 4. 5. 6.

On the View menu, click Task List. In the Task List window, in the Categories list, click Comments. Double-click the TODO: put your data source class name here task.

In the code editor, delete the code /* TODO: put your data source class name here */, and then type the following code:
SchoolGradesDBEntities

7. 8.

In the Task List window, double-click the TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc. task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
// Configure all entity sets to permit read and write access. config.SetEntitySetAccessRule("Grades", EntitySetRights.All); config.SetEntitySetAccessRule("Teachers", EntitySetRights.All); config.SetEntitySetAccessRule("Students", EntitySetRights.All); config.SetEntitySetAccessRule("Subjects", EntitySetRights.All);

MCT USE ONLY. STUDENT USE PROHIBITED


L08-3

config.SetEntitySetAccessRule("Users", EntitySetRights.All);

X Task 4: Add an operation to retrieve all of the students in a specified class


1.

Click after the closing brace for the InitializeService method, press Enter twice, and then type the following code:
// Find all students in a specified class. [WebGet] public IEnumerable<Student> StudentsInClass(string className) { var students = from Student s in this.CurrentDataSource.Students where String.Equals(s.Teacher.Class, className) select s; return students; }

2. 3.

In the Task List window, double-click the TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc. task. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
// Configure the StudentsInClass operation as read-only. config.SetServiceOperationAccessRule("StudentsInClass", ServiceOperationRights.AllRead);

X Task 5: Build and test the data service


1. 2. 3. 4. 5. 6. On the Build menu, click Build Solution. In Solution Explorer, in the Grades.Web project, in the Services folder, right-click GradesWebDataService.svc, and then click View in Browser (Internet Explorer).

In Internet Explorer, if the message Intranet settings are turned off by default, click Don't show this message again. Verify that Internet Explorer displays an XML description of the entities that the data service exposes. Close Internet Explorer. In Visual Studio, on the File menu, click Close Solution.

Results: After completing this exercise, you should have added a WCF Data Service to the application to provide remote access to the SchoolGrades database.

MCT USE ONLY. STUDENT USE PROHIBITED

L08-4 Programming in Visual C#

Exercise 2: Integrating the Data Service into the Application

X Task 1: Add a service reference for the WCF Data Service to the GradesPrototype application
1. 2. 3. 4. 5. 6. 7. 8. 9. In Visual Studio, on the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click GradesPrototype.sln, and then click Open.

In Solution Explorer, expand GradesPrototype, expand References, right-click Grades.DataModel, and then click Remove. Right-click References, and then click Add Service Reference.

In the Add Service Reference dialog box, in the Address box, type http://localhost:1650, and then click Discover. In the Namespace box, type Grades.DataModel, and then click OK. In the Solution Explorer toolbar, click Show All Files. In Solution Explorer, in the GradesPrototype project, in the Service References folder, expand Grades.DataModel, expand Reference.datasvcmap, and then double-click Reference.cs.

In the code editor, modify the namespace GradesPrototype.Grades.DataModel code to look like the following code:
namespace Grades.DataModel

10. In Solution Explorer, right-click the GradesPrototype project, point to Add, and then click New Folder. 11. Delete the existing name, type DataModel, and then press Enter.

12. In Solution Explorer, expand the Grades.DataModel project, right-click Classes.cs, and then click Copy. 13. In GradesPrototype, right-click DataModel, and then click Paste. 14. In Grades.DataModel, right-click customGrade.cs, and then click Copy. 15. In GradesPrototype, right-click DataModel, and then click Paste. 16. In Grades.DataModel, right-click customTeacher.cs, and then click Copy. 17. In GradesPrototype, right-click DataModel, and then click Paste.

X Task 2: Modify the code that accesses the EDM to use the WCF Data Service
1. 2. In the Task List window, double-click the TODO: Exercise 2: Task 2a: Specify the URL of the GradesWebDataService task.

In the code editor, below the comment, click inside the parentheses, and then type the following code:
new Uri("http://localhost:1650/Services/GradesWebDataService.svc")

3.

Add the following code to the SessionContext class, after the Save method:

static SessionContext() { DBContext.MergeOption = System.Data.Services.Client.MergeOption.PreserveChanges; }

MCT USE ONLY. STUDENT USE PROHIBITED


L08-5

4. 5.

In the Task List window, double-click the TODO: Exercise 2: Task 2b: Load User and Grades data with Students task. In the code editor, at the end of the comment, press Enter, and then type the following code:
SessionContext.DBContext.LoadProperty(student, "User"); SessionContext.DBContext.LoadProperty(student, "Grades");

6. 7.

In the Task List window, double-click the TODO: Exercise 2: Task 2c: Load User and Students data with Teachers task.

In the code editor, below the comment, click at the end of the SessionContext.DBContext.Teachers code, and then type the following code:
.Expand("User, Students")

8. 9.

In the Task List window, double-click the TODO: Exercise 2: Task 2d: Load User and Grades data with Students task.

In the code editor, below the comment, click at the end of the SessionContext.DBContext.Students code, and then type the following code:
.Expand("User, Grades")

10. In Solution Explorer, in the GradesPrototype project, expand DataModel, and then double-click customTeacher.cs. 11. Click at the end of the using System.Threading.Tasks; code, press Enter, and then type the following code:
using GradesPrototype.Services;

12. In the code editor, locate the TODO: Exercise 2: Task 2e: Refer to the Students collection in the SessionContext.DBContext object comment in the customTeacher.cs file. Note: There are two comments with this text. This is because the comment is located in the customTeacher.cs file that you copied from the Grades.DataModel project. Make sure that you modify the customTeacher.cs file in the GradesPrototype project. 13. In the line below the comment, delete the word Students, and then type the following code: 14. SessionContext.DBContext.Students 15. In the Task List window, double-click the TODO: Exercise 2: Task 2f: Reference the SessionContext.DBContext.Students collection.

16. In the code editor, below the comment, change SessionContext.DBContext.Students.Local to the following code:
SessionContext.DBContext.Students.Expand("User, Grades")

17. In the Task List window, double-click the TODO: Exercise 2: Task 2g: Use the AddToGrades method to add a new grade. 18. In the code editor, below the comment, change SessionContext.DBContext.Grades.Add(newGrade); to the following code:
SessionContext.DBContext.AddToGrades(newGrade);

MCT USE ONLY. STUDENT USE PROHIBITED

L08-6 Programming in Visual C#

19. In the Task List window, double-click the TODO: Exercise 2: Task 2h: Load Subject data with Grades.

20. In the code editor, below the comment, change SessionContext.DBContext.Grades to the following code:
SessionContext.DBContext.Grades.Expand("Subject")

21. In the Task List window, double-click the TODO: Exercise 2: Task 2i: Use the AddToStudents method to add a new student. 22. In the code editor, below the comment, change SessionContext.DBContext.Students.Add(newStudent); to the following code:
SessionContext.DBContext.AddToStudents (newStudent);

X Task 3: Modify the code that saves changes back to the database to use the WCF Data Service
1. 2. 3. 4. 5.

In the Task List window, double-click the TODO: Exercise 2: Task 3a: Specify that the selected student has been changed task. In the code editor, click in the blank space below the comment, and then type the following code: SessionContext.DBContext.UpdateObject(student);

In the Task List window, double-click the TODO: Exercise 2: Task 3b: Specify that the current student has been changed task. In the code editor, click in the blank space below the comment, and then type the following code:
SessionContext.DBContext.UpdateObject(SessionContext.CurrentStudent);

6. 7.

In the Task List window, double-click the TODO: Exercise 2: Task 3c: Specify that the current user has been changed task. Click in the blank space below the comment, and then type the following code:
SessionContext.DBContext.UpdateObject(currentUser);

X Task 4: Build and test the application to verify that the application still functions correctly
1. 2. 3. 4. 5. 6. 7. 8. 9. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging. In the Username box, type vallee. In the Password box, type password99, and then click Log on.

In the students list, click Eric Gruber, click Remove Student, and then in the Confirm dialog box, click Yes. Verify that Eric Gruber is removed from the student list. Click Enroll Student, click Jon Orton, and then in the Confirm dialog box, click Yes. Click Close, and then verify that Jon Orton is added to the student list. Click Change Password.

10. In the Old Password box, type password99. 11. In the New Password box, type password88.

MCT USE ONLY. STUDENT USE PROHIBITED


L08-7

12. In the Confirm box, type password88, and then click OK. 13. In the Password dialog box, click OK, and then click Log off. 14. Click Log on, verify that the Logon Failed dialog box appears, and then click OK. 15. In the password box, type password88, and then click Log on. 16. Verify that the student list is displayed. 17. Click Log off, and then in the Username box, type grubere. 18. In the Password box, type password, and then click Log on. 19. Verify that the student profile for Eric Gruber appears, and then click Log off. 20. Close the application. 21. In Visual Studio, on the File menu, click Close Solution.

Results: After completing this exercise, you should have updated the Grades Prototype application to use the WCF Data Service.

MCT USE ONLY. STUDENT USE PROHIBITED

L08-8 Programming in Visual C#

Exercise 3: Retrieving Student Photographs Over the Web


X Task 1: Create the ImageNameConverter value converter class
1. 2. 3. In Visual Studio, on the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 3, click GradesPrototype.sln, and then click Open.

In the Task List window, double-click the TODO: Exercise 3: Task 1: Create the ImageNameConverter value converter to convert the image name of a student photograph into the URL of the image on the Web server task.

4.

Click at the end of the // Converter class for transforming an image name for a photograph into a URL comment, press Enter, and then type the following code:
public class ImageNameConverter : IValueConverter { }

5.

In the ImageNameConverter class, type the following code:


const string webFolder = "http://localhost:1650/Images/Portraits/";

6. 7.

Right-click the IValueConverter keyword, point to Implement Interface, and then click Implement Interface. In the Convert method, delete the existing statement that throws a NotImplementedException, and then type the following code:
string fileName = value as string; if (fileName != null) { return string.Format("{0}{1}", webFolder, fileName); } else { return string.Empty; }

8.

On the Build menu, click Build Solution.

X Task 2: Add an Image control to the StudentsPage view and bind it to the ImageName property
1. 2. In Solution Explorer, in the GradesPrototype project, expand Views, and then double-click StudentsPage.xaml.

In the XAML editor, in the UserControl element at the top of the markup, click after the xmlns:d=http://schemas.microsoft.com/expression/blend/2008 line, press Enter, and then type the following markup:
xmlns:local="clr-namespace:GradesPrototype.Views"

3.

Locate the TODO: Exercise 3: Task 2a. Add an instance of the ImageNameConverter class as a resource to the view comment, click at the end of the comment, press Enter, and then type the following markup:
<UserControl.Resources> <local:ImageNameConverter x:Key="ImageNameConverter"/> </UserControl.Resources>

MCT USE ONLY. STUDENT USE PROHIBITED


L08-9

4.

Locate the TODO: Exercise 3: Task 2b. Add an Image control to display the photo of the student comment, click at the end of the comment, press Enter, and then type the following markup:
<Image Height="100" />

5. 6.

Locate the Exercise 3: Task 2c. Bind the Image control to the ImageName property and use the ImageNameConverter to convert the image name into a URL comment.

In the line above the comment, modify the <Image Height="100" /> markup to look like the following markup:
<Image Height="100" Source="{Binding ImageName, Converter={StaticResource ImageNameConverter}}" />

X Task 3: Add an Image control to the StudentProfile view and bind it to the ImageName property
1. 2. 3. In Solution Explorer, double-click StudentProfile.xaml. Locate the TODO: Exercise 3: Task 3a. Add an instance of the ImageNameConverter class as a resource to the view comment. Click at the end of the comment, press Enter, and then type the following markup:
<app:ImageNameConverter x:Key="ImageNameConverter"/>

4.

Locate the TODO: Exercise 3: Task 3b. Add an Image control to display the photo of the student and bind the Image control to the ImageName property and use the ImageNameConverter to convert the image name into a URL comment. Click at the end of the comment, press Enter, and then type the following markup:
<Image Height="150" Source="{Binding ImageName, Converter={StaticResource ImageNameConverter}}" />

5.

X Task 4: Add an Image control to the AssignStudentDialog control and bind it to the ImageName property
1. 2. In Solution Explorer, expand Controls, and then double-click AssignStudentDialog.xaml. In the XAML editor, at the top of the markup, click at the end of the xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml line, press Enter, and then type the following markup:
xmlns:local="clr-namespace:GradesPrototype.Views"

3. 4.

Locate the TODO: Exercise 3: Task 4a. Add an instance of the ImageNameConverter class as a resource to the view comment. Click at the end of the comment, press Enter, and then type the following markup:
<Window.Resources> <local:ImageNameConverter x:Key="ImageNameConverter"/> </Window.Resources>

5.

Locate the TODO: Exercise 3: Task 4b. Add an Image control to display the photo of the student and bind the control to the ImageName property and use the ImageNameConverter to convert the image name into a URL comment. Click at the end of the comment, press Enter, and then type the following markup:

6.

MCT USE ONLY. STUDENT USE PROHIBITED

L08-10 Programming in Visual C#

<Image Height="100" Source="{Binding ImageName, Converter={StaticResource ImageNameConverter}}" />

X Task 5: Build and test the application, verifying that students photographs appear in the list of students for the teacher
1. 2. 3. 4. 5. 6. 7. 8. 9. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging. In the Username box, type vallee. In the Password box, type password88, and then click Log on. Verify that the students list now includes images. Click George Li, and then verify that the student profile appears with an image. Click Remove Student, and then in the Confirm dialog box, click Yes.

Click Enroll Student, and then verify that in the Assign Student dialog box, the unassigned students each have an image. Click George Li, in the Confirm dialog box, click Yes, and then verify that George Li is added to the students list with an image.

10. Close the application. 11. On the File menu, click Close Solution.

Results: After completing this exercise, the students list, student profile, and unassigned student dialog box will display the images of students that were retrieved across the web.

MCT USE ONLY. STUDENT USE PROHIBITED


L9-1

Module 9: Designing the User Interface for a Graphical Application

Lab: Customizing Student Photographs and Styling the Application


Exercise 1: Customizing the Appearance of Student Photographs
X Task 1: Create the StudentPhoto user control
1. 2. 3. Start the MSL-TMG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-09 virtual machine. Log on to Windows 8 as Student with the password Pa$$w0rd.

Note: If necessary, click Switch User to display a list of users in the Windows 8 log on screen. 4. 5. 6. 7. 8. 9. Switch to the Windows 8 Start window. Click Visual Studio 2012. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click Grades.sln, and then click Open. In Solution Explorer, right-click Solution Grades, and then click Properties.

On the Startup Project page, click Multiple startup projects. Set Grades.Web and Grades.WPF to Start without debugging, and then click OK.

10. In Solution Explorer, expand Grades.WPF, and then expand Controls. 11. Right-click Controls, point to Add, and then click New Item.

12. In the Add New Item Grades.WPF dialog box, in the template list, click User Control (WPF). 13. In the Name box, type StudentPhoto, and then click Add. 14. In the XAML editor, modify the markup to look like the following markup (the changes are highlighted as bold text):

<UserControl x:Class="Grades.WPF.StudentPhoto" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> <Grid> <Image Stretch="UniformToFill" Source="{Binding File}" Margin="8" /> <Image Margin="0" Source="../Images/Image_Frame.png" Stretch="Fill" /> <TextBlock Text="{Binding Name}" Style="{StaticResource LabelCenter}" FontSize="16" VerticalAlignment="Bottom" Margin="8,0,14.583,8" /> </Grid> </UserControl>

MCT USE ONLY. STUDENT USE PROHIBITED

L9-2

Programming in Visual C#

15. In Solution Explorer, expand StudentPhoto.xaml, and then double-click StudentPhoto.xaml.cs. 16. In the code editor, delete all of the using directives, and then type the following code:
using System.Windows.Controls; using System.Windows.Media.Animation;

17. Modify the namespace Grades.WPF.Controls code to look like the following code:
namespace Grades.WPF

X Task 2: Display the students photographs in the StudentsPage view


1. 2. 3. In Solution Explorer, expand Views, and then double-click StudentsPage.xaml. In the XAML editor, locate the <!-- TODO: Exercise 1: Task 2a: Define the "list" ItemsControl containing a horizontal WrapPanel for displaying photographs of students --> comment. Click at the end of the comment, press Enter, and then type the following markup:
<ItemsControl x:Name="list"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <WrapPanel Margin="0" Orientation="Horizontal" HorizontalAlignment="Center" /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel>

Note: When you type an opening tag for an element, such as <ItemsControl>, the XAML editor automatically creates a corresponding closing tag, such as </ItemsControl>. For the purposes of these instructions, and to ensure that code appears in the correctly commented place, delete any closing tags that are generated automatically; you will add them in at the appropriate point in the XAML markup in later steps. 4.

Locate the <!-- TODO: Exercise 1: Task 2b: Define the DataTemplate for the "list" ItemsControl including the StudentPhoto user control --> comment, click at the end of the comment, press Enter, and then type the following markup:
<ItemsControl.ItemTemplate> <DataTemplate> <Grid Margin="8"> <local:StudentPhoto Height="150" Width="127.5" Cursor="Hand"

Note: At the end of this task, the XAML markup is incomplete and will display errors in the XAML pane. In the next task, you will add closing tags and make the markup complete.

X Task 3: Enable the user to display the details for a student


1. 2. 3. 4. On the View menu, click Task List. In the Task List window, in the Categories list, click Comments.

In Solution Explorer, expand StudentsPage.xaml, and then double-click StudentsPage.xaml.cs.

Double-click the TODO: Exercise 1: Task 3a: If the user clicks a photo, raise the StudentSelected event to display the details of the student task.

MCT USE ONLY. STUDENT USE PROHIBITED


L9-3

5.

In the code editor, click in the blank line below the comment, and then type the following code:
private void Student_Click(object sender, MouseButtonEventArgs e) { if (StudentSelected != null) StudentSelected(sender, new StudentEventArgs((sender as StudentPhoto).DataContext as LocalStudent)); }

6. 7. 8.

In Solution Explorer, double-click StudentsPage.xaml.

Locate the <!-- TODO: Exercise 1: Task 3b: Set the handler for the click event for the StudentPhoto control --> comment, and above the comment, click at the end of the Cursor="Hand" markup. Press Spacebar, and then type the following markup:
MouseLeftButtonUp="Student_Click" />

X Task 4: Add a Remove button to the StudentsPage view


1.

In StudentsPage.xaml, Locate the <!-- TODO: Exercise 1: Task 4a: Add the "Remove" button to the DataTemplate --> comment, click at the end of the comment, press Enter, and then type the following markup:
<Grid VerticalAlignment="Top" HorizontalAlignment="Right" Background="#00000000" Opacity="0.3" Width="20" Height="20" ToolTipService.ToolTip="Remove from class" Tag="{Binding}" > <Image Source="../Images/delete.png" Stretch="Uniform" /> </Grid>

2. 3.

In the Task List window, double-click the TODO: Exercise 1: Task 4b: Animate the photo as the user moves the mouse over the "delete" image task.

In the code editor, click in the blank line below the comment, press Enter, and then type the following code:
private void RemoveStudent_MouseEnter(object sender, MouseEventArgs e) { Grid grid = (Grid)sender; grid.Opacity = 1.0; StudentPhoto photo = ((Grid)grid.Parent).Children[0] as StudentPhoto; photo.Opacity = 0.6; }

4. 5.

In the Task List window, double-click the TODO: Exercise 1: Task 4c: Animate the photo as the user moves the mouse away from the "delete" image task. In the code editor, click in the blank line below the comment, then type the following code:
private void RemoveStudent_MouseLeave(object sender, MouseEventArgs e) { Grid grid = (Grid)sender; grid.Opacity = 0.3; StudentPhoto photo = ((Grid)grid.Parent).Children[0] as StudentPhoto; photo.Opacity = 1.0; }

6. 7.

In Solution Explorer, double-click StudentsPage.xaml.

In the XAML editor, locate the <!-- TODO: Exercise 1: Task 4d: Add event handlers to highlight the "Remove" button as the mouse enters and exits this control --> comment, and above the comment,

MCT USE ONLY. STUDENT USE PROHIBITED

L9-4

Programming in Visual C#

click at the end of the Tag="{Binding}" code (before the closing > tag), press Enter, and then type the following markup:
MouseEnter="RemoveStudent_MouseEnter" MouseLeave="RemoveStudent_MouseLeave" MouseLeftButtonUp="RemoveStudent_Click"

8.

Click at the end of the <Image Source="../Images/delete.png" Stretch="Uniform" /></Grid> markup, press Enter, and then type the following code:
</Grid> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>

X Task 5: Display all students for the current teacher


1. 2. 3. In Solution Explorer, double-click StudentsPage.xaml.cs.

In the Task List window, double-click the TODO: Exercise 1: Task 5a: Find all students for the current teacher task. In the code editor, click in the blank line below the comment, and then type the following code:
ServiceUtils utils = new ServiceUtils(); var students = utils.GetStudentsByTeacher(SessionContext.UserName);

4. 5.

In the Task List window, double-click the TODO: Exercise 1: Task 5b: Iterate through the returned set of students, construct a local student object list task. In the code editor, click in the blank line below the comment, and then type the following code:
List<LocalStudent> resultData = new List<LocalStudent>(); foreach (Student s in students) { LocalStudent student = new LocalStudent() { Record = s }; resultData.Add(student); }

6. 7.

In the Task List window, double-click the TODO: Exercise 1: Task 5c: Bind the list of students to the "list" ItemsControl task. In the code editor, click in the blank line below the comment, and then type the following code:
list.ItemsSource = resultData;

X Task 6: Build and test the application


1. 2. 3. 4. 5. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging. When the application starts, in the Username box, type vallee, in the Password box, type password99, and then click Log on. Verify that the students list appears with photographs. In the student list, hover over the red x for the student Martin Weber.

MCT USE ONLY. STUDENT USE PROHIBITED


L9-5

6. 7. 8. 9.

Verify that the student photograph for Martin Weber becomes transparent and that the red x becomes opaque.

Move the cursor away from the red x and verify that the student photograph becomes opaque and that the red x becomes transparent. Click the red x for Martin Weber, verify that the Student message box appears, and then click Yes. Verify that Martin Weber is removed from the student list.

10. Close the application.

Results: After completing this exercise, the application will display the photographs of each student on the Student List page.

MCT USE ONLY. STUDENT USE PROHIBITED

L9-6

Programming in Visual C#

Exercise 2: Styling the Logon View and the StudentPhoto Control


X Task 1: Define and apply styles for the LogonPage view
1. 2. 3. 4. 5. 6. 7. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click Grades.sln, and then click Open. In Solution Explorer, right-click Solutions Grades, and then click Properties.

On the Startup Project page, click Multiple startup projects. Set Grades.Web and Grades.WPF to Start without debugging, and then click OK. In Solution Explorer, expand Grades.WPF, expand Views, and then double-click LogonPage.xaml. In the XAML editor, locate the <!-- TODO: Exercise 2: Task 1a: Define the LoginTextBoxStyle --> comment. Click at the end of the comment, press Enter, and then type the following markup:
<UserControl.Resources> <Style x:Key="LoginTextBoxStyle" BasedOn="{StaticResource TextBoxStyle}" TargetType="{x:Type TextBox}"> <Setter Property="Margin" Value="5" /> <Setter Property="FontSize" Value="24"/> <Setter Property="MaxLength" Value="16" /> </Style>

8. 9.

Locate the <!-- TODO: Exercise 2: Task 1b: Apply the LoginTextBoxStyle to the "username" TextBox -> comment.

In the line of markup below the comment, delete the FontSize property, and then modify the markup as shown in bold below:
<TextBox x:Name="username" Grid.Row="1" Grid.Column="1" Style="{StaticResource LoginTextBoxStyle}" />

10. Locate the <!-- TODO: Exercise 2: Task 1c: Define the PasswordBoxStyle --> comment. 11. Click at the end of the comment, press Enter, and then type the following markup:
<Style x:Key="PasswordBoxStyle" TargetType="{x:Type PasswordBox}"> <Setter Property="Margin" Value="5" /> <Setter Property="FontSize" Value="24"/> <Setter Property="MaxLength" Value="16" /> </Style> </UserControl.Resources>

12. Locate the TODO: Exercise 2: Task 1d: Apply the PasswordBoxStyle to the "password" TextBox comment.

13. In the line of markup below the comment, delete the FontSize property, and then modify the markup as shown in bold below:
<PasswordBox x:Name="password" Grid.Row="2" Grid.Column="1" Style="{StaticResource PasswordBoxStyle}" />

X Task 2: Define global styles for the application


1. In Solution Explorer, expand Themes, and then double-click Generic.xaml.

MCT USE ONLY. STUDENT USE PROHIBITED


L9-7

2. 3.

In the XAML editor, locate the <!-- TODO: Exercise 2: Task 2a: Define the label styling used throughout the application --> comment near the end of the file. Click in the blank line below the comment, and type the following markup:
<Setter <Setter <Setter <Setter Property="TextWrapping" Value="NoWrap"/> Property="FontFamily" Value="../Assets/#Buxton Sketch"/> Property="FontSize" Value="19"/> Property="Foreground" Value="#FF303030" />

4. 5.

Locate the <!-- TODO: Exercise 2: Task 2b: Define the text styling used throughout the application --> comment. Click in the blank line below the comment, then type the following markup:
<Setter <Setter <Setter <Setter <Setter Property="TextWrapping" Value="NoWrap"/> Property="FontFamily" Value="../Assets/#Buxton Sketch"/> Property="FontSize" Value="12"/> Property="TextAlignment" Value="Left" /> Property="Foreground" Value="#FF303030" />

X Task 3: Define animations for the StudentPhoto control


1. 2. 3. In Solution Explorer, expand Controls, and then double-click StudentPhoto.xaml.

In the XAML editor, locate the <!-- TODO: Exercise 2: Task 3a: Define a ScaleTransform called "scale" -> comment. Click in the blank line below the comment, then type the following markup:
<UserControl.RenderTransform> <ScaleTransform x:Name="scale" /> </UserControl.RenderTransform>

4. 5.

In the XAML editor, locate the <!-- TODO: Exercise 2: Task 3b: Define animations for the "scale" transform--> comment. Click in the blank line below the comment, then type the following markup:
<UserControl.Resources> <Storyboard x:Key="sbMouseEnter"> <DoubleAnimation To="1.1" BeginTime="00:00:00" Duration="00:00:00.05" Storyboard.TargetName="scale" Storyboard.TargetProperty="ScaleX" /> <DoubleAnimation To="1.1" BeginTime="00:00:00" Duration="00:00:00.15" Storyboard.TargetName="scale" Storyboard.TargetProperty="ScaleY" /> </Storyboard> <Storyboard x:Key="sbMouseLeave"> <DoubleAnimation To="1" BeginTime="00:00:00" Duration="00:00:00.05" Storyboard.TargetName="scale" Storyboard.TargetProperty="ScaleX" /> <DoubleAnimation To="1" BeginTime="00:00:00" Duration="00:00:00.15" Storyboard.TargetName="scale" Storyboard.TargetProperty="ScaleY" /> </Storyboard> </UserControl.Resources>

X Task 4: Add event handlers to trigger the animations


1. 2. 3.

In Solution Explorer, expand StudentPhoto.xaml, and then double-click StudentPhoto.xaml.cs.

In the Task List window, double-click the TODO: Exercise 2: Task 4a: Handle mouse events to trigger the storyboards that animate the photograph task. In the code editor, click in the blank line below the comment, and then type the following code:

MCT USE ONLY. STUDENT USE PROHIBITED

L9-8

Programming in Visual C#

public void OnMouseEnter() { // Trigger the mouse enter animation to grow the size of the photograph currently under the mouse pointer (this.Resources["sbMouseEnter"] as Storyboard).Begin(); } public void OnMouseLeave() { // Trigger the mouse leave animation to shrink the size of the photograph currently under the mouse pointer to return it to its original size (this.Resources["sbMouseLeave"] as Storyboard).Begin(); }

4. 5. 6.

In Solution Explorer, in Views, expand StudentsPage.xaml, and then double-click StudentsPage.xaml.cs.

In the Task List window, double-click the TODO: Exercise 2: Task 4b: Forward the MouseEnter and MouseLeave events to the photograph control task.

In the code editor, click in the blank space below the comment, and then type the following code:

private void Student_MouseEnter(object sender, MouseEventArgs e) { // Call the OnMouseEnter event handler on the specific photograph currently under the mouse pointer ((StudentPhoto)sender).OnMouseEnter(); } private void Student_MouseLeave(object sender, MouseEventArgs e) { // Call the OnMouseLeave event handler on the specific photograph currently under the mouse pointer ((StudentPhoto)sender).OnMouseLeave(); }

7. 8. 9.

In Solution Explorer, double-click StudentsPage.xaml. In the XAML editor, locate the <!-- TODO: Exercise 2: Task 4c: Specify the handlers for the MouseEnter and MouseLeave events --> comment.

Below the comment, click at the end of the MouseLeftButtonUp="Student_Click" markup, press Spacebar, and then type the following markup:
MouseEnter="Student_MouseEnter" MouseLeave="Student_MouseLeave"

X Task 5: Build and test the application


1. 2. 3. 4. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging. When the application starts, in the Username box, type vallee, and in the Password box, type password99, and then click Log on.

In The School of Fine Arts window, verify that the styling of the text elements of the application has changed.

MCT USE ONLY. STUDENT USE PROHIBITED


L9-9

Comparison of the Logon views:

FIGURE 9.1: UPPER: OLD STYLE LOGON VIEW. LOWER: NEW STYLE LOGON VIEW 5. 6. 7.

Hover over one of the students in the student list and verify that the photograph animatesit should expand and contract as the mouse passes over it. Close the application. On the File menu, click Close Solution.

Results: After completing this exercise, the Logon view and the Photograph control will be styled with a consistent look and feel.

MCT USE ONLY. STUDENT USE PROHIBITED

MCT USE ONLY. STUDENT USE PROHIBITED


L10-1

Module 10: Improving Application Performance and Responsiveness

Lab: Improving the Responsiveness and Performance of the Application


Exercise 1: Ensuring That the UI Remains Responsive When Retrieving Teacher Data
X Task 1: Build and run the application
1. 2. 3. Start the MSL-TMG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-10 virtual machine. Log on to Windows 8 as Student with the password Pa$$w0rd. Note: If necessary, click Switch User to display the list of users. 4. 5. 6. 7. 8. 9. Switch to the Windows 8 Start window. Click Visual Studio 2012.

In Microsoft Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click Grades.sln, and then click Open. In Solution Explorer, right-click Solutions Grades, and then click Properties.

On the Startup Project page, click Multiple startup projects. Set Grades.Web and Grades.WPF to Start without debugging, and then click OK.

10. On the Build menu, click Build Solution. 11. On the Debug menu, click Start Without Debugging.

12. When the application loads, in the Username box, type vallee, and in the Password box, type password99, and then click Log on.

13. Notice that the UI briefly freezes while fetching the list of students for Esther Valle (try moving the application window after logging on but before the list of students appears). 14. Close the application window.

X Task 2: Modify the code that retrieves teacher data to run asynchronously
1. 2. 3. 4. On the View menu, click Task List. In the Task List window, in the Categories list, select Comments.

Double-click the TODO: Exercise 1: Task 2a: Convert GetTeacher into an async method that returns a Task<Teacher> task. In the code editor, delete the following line of code:
public Teacher GetTeacher(string userName)

MCT USE ONLY. STUDENT USE PROHIBITED

L10-2 Programming in Visual C#

5.

In the blank line below the comment, type the following code:
public async Task<Teacher> GetTeacher(string userName)

6. 7.

In the Task List window, double-click the TODO: Exercise 1: Task 2b: Perform the LINQ query to fetch Teacher information asynchronously task. In the code editor, modify the statement below the comment as shown in bold below:
var teacher = await Task.Run(() => (from t in DBContext.Teachers where t.User.UserName == username select t).FirstOrDefault());

8. 9.

In the Task List window, double-click the TODO: Exercise 1: Task 2c: Mark MainWindow.Refresh as an asynchronous method task. In the code editor, modify the statement below the comment as shown in bold below:
public async void Refresh()

10. In the Task List window, double-click the TODO: Exercise 1: Task 2d: Call GetTeacher asynchronously task. 11. In the code editor, modify the statement below the comment as shown in bold below:
var teacher = await utils.GetTeacher(SessionContext.UserName);

X Task 3: Modify the code that retrieves and displays the list of students for a teacher to run asynchronously
1. 2.

In the Task List window, double-click the TODO: Exercise 1: Task 3a: Mark StudentsPage.Refresh as an asynchronous method task. In the code editor, modify the statement below the comment as shown in bold below:
public async void Refresh()

3. 4.

In the Task List window, double-click the TODO: Exercise 1: Task 3b: Implement the OnGetStudentsByTeacherComplete callback to display the students for a teacher here task. In the blank line below the comment, type the following code:
private void OnGetStudentsByTeacherComplete(IEnumerable<Student> students) { }

5.

In the Task List window, double-click the Exercise 1: Task 3b: Relocate the remaining code in this method to create the OnGetStudentsByTeacherComplete callback (in the Callbacks region) task. In the code editor, move all of the code between the comment and the end of the Refresh method to the Clipboard. In the Task List window, double-click the TODO: Exercise 1: Task 3b: Implement the OnGetStudentsByTeacherComplete callback to display the students for a teacher here task. Click in the blank line between the curly braces and paste the code from the Clipboard.

6. 7. 8.

MCT USE ONLY. STUDENT USE PROHIBITED


L10-3

9.

In the Task List window, double-click the TODO: Exercise 1: Task 3c: Use a Dispatcher object to update the UI task.

10. In the code editor, click at the end of the comment line, press Enter, and then type the following code:
this.Dispatcher.Invoke(() => {

11. Immediately after the last line of code in the method, type the following code: }); 12. In the Task List window, double-click the TODO: Exercise 1: Task 3d: Convert GetStudentsByTeacher into an async method that invokes a callback task. 13. In the code editor, delete the following line of code:
public List<Student> GetStudentsByTeacher(string teacherName)

14. In the blank line below the comment, type the following code:
public async Task GetStudentsByTeacher(string teacherName, Action<IEnumerable<Student>> callback)

15. In the code editor, modify the return statement below the if(!IsConnected()) line to return without passing a value to the caller:
return;

16. In the Task List window, double-click the TODO: Exercise 1: Task 3e: Perform the LINQ query to fetch Student data asynchronously task. 17. In the code editor, modify the statement below the comment as shown in bold below:
var students = await Task.Run(() => (from s in DBContext.Students where s.Teacher.User.UserName == teacherName select s).OrderBy(s => s.LastName).ToList());

18. In the Task List window, double-click the TODO: Exercise 1: Task 3f: Run the callback by using a new task rather than returning a list of students task. 19. In the code editor, delete the following code:
return students;

20. In the blank line below the comment, type the following code:
await Task.Run(() => callback(students));

21. In the Task List window, double-click the TODO: Exercise 1: Task 3g: Invoke GetStudentsByTeacher asynchronously and pass the OnGetStudentsByTeacherComplete callback as the second argument task. 22. In the code editor, modify the statement below the comment as shown in bold below:
await utils.GetStudentsByTeacher(SessionContext.UserName, OnGetStudentsByTeacherComplete);

MCT USE ONLY. STUDENT USE PROHIBITED

L10-4 Programming in Visual C#

X Task 4: Build and test the application


1. 2. 3. 4. 5. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging. When the application loads, in the Username box, type vallee, and in the Password box, type password99, and then click Log on.

Verify that the application is more responsive than before while fetching the list of students for Esther Valle, and then close the application window. On the File menu, click Close Solution.

Results: After completing this exercise, you should have updated the Grades application to retrieve data asynchronously.

Exercise 2: Providing Visual Feedback During Long-Running Operations


X Task 1: Create the BusyIndicator user control
1. 2. 3. Start the MSL-TMG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-10 virtual machine. Log on to Windows 8 as Student with the password Pa$$w0rd. Note: If necessary, click Switch User to display the list of users. 4. 5. 6. 7. 8. 9. Switch to the Windows 8 Start window. Click Visual Studio 2012.

In Microsoft Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click Grades.sln, and then click Open. In Solution Explorer, right-click Solutions Grades, and then click Properties.

On the Startup Project page, click Multiple startup projects. Set Grades.Web and Grades.WPF to Start without debugging, and then click OK.

MCT USE ONLY. STUDENT USE PROHIBITED


L10-5

10. On the Build menu, click Build Solution. 11. In Solution Explorer, right-click Grades.WPF, point to Add, and then click User Control. 12. In the Name box, type BusyIndicator.xaml, and then click Add.

13. In Solution Explorer, expand Grades.WPF, and then drag BusyIndicator.xaml into the Controls folder. Note: It is better to create the user control at the project level and then move it into the Controls folder when it is created. This ensures that the user control is created in the same namespace as other project resources. 14. In the BusyIndicator.xaml file, in the UserControl element, delete the following attributes:
d:DesignWidth="300" d:DesignHeight="300"

15. Modify the Grid element to include a Background attribute, as the following markup shows:
<Grid Background="#99000000"> </Grid>

16. Type the following markup between the opening and closing Grid tags:
<Border CornerRadius="6" HorizontalAlignment="Center" VerticalAlignment="Center"> <Border.Background> <LinearGradientBrush> <GradientStop Color="LightGray" Offset="0" /> <GradientStop

MCT USE ONLY. STUDENT USE PROHIBITED

L10-6 Programming in Visual C#

Color="DarkGray" Offset="1" /> </LinearGradientBrush> </Border.Background> <Border.Effect> <DropShadowEffect Opacity="0.75" /> </Border.Effect> </Border>

17. On the blank line before the closing Border tag, type the following code:
<Grid Margin="10"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> </Grid>

18. On the blank line before the closing Grid tag, type the following code:
<ProgressBar x:Name="progress" IsIndeterminate="True" Width="200" Height="25" Margin="20" />

19. Click after the end of the ProgressBar element, and then press Enter. 20. In the new line, type the following code:
<TextBlock x:Name="txtMessage" Grid.Row="1" FontSize="14" FontFamily="Verdana" Text="Please Wait..." TextAlignment="Center" />

21. On the File menu, click Save All. 22. In Solution Explorer, expand Grades.WPF, and then double-click MainWindow.xaml.

23. Towards the bottom of the MainWindow.xaml file, locate the TODO: Exercise 2: Task 1b: Add the BusyIndicator control to MainWindow comment. 24. Click at the end of the comment, press Enter, and then type the following code:
<y:BusyIndicator x:Name="busyIndicator" Margin="0" Visibility="Collapsed" />

25. On the Build menu, click Build Solution.

X Task 2: Add StartBusy and EndBusy event handler methods


1. 2.

In the Task List window, double-click the TODO: Exercise 2: Task 2a: Implement the StartBusy event handler task. In the blank line below the comment, type the following code:
private void StartBusy(object sender, EventArgs e) { busyIndicator.Visibility = Visibility.Visible;

MCT USE ONLY. STUDENT USE PROHIBITED


L10-7

3. 4.

In the Task List window, double-click the TODO: Exercise 2: Task 2b: Implement the EndBusy event handler task. In the blank line below the comment, type the following code:
private void EndBusy(object sender, EventArgs e) { busyIndicator.Visibility = Visibility.Hidden; }

X Task 3: Raise the StartBusy and EndBusy events


1. 2.

In the Task List window, double-click the TODO: Exercise 2: Task 3a: Add the StartBusy public event task. In the blank line below the comment, type the following code:
public event EventHandler StartBusy;

3. 4.

In the Task List window, double-click the TODO: Exercise 2: Task 3b: Add the EndBusy public event task. In the blank line below the comment, type the following code:
public event EventHandler EndBusy;

5. 6.

In the Task List window, double-click the TODO: Exercise 2: Task 3c: Implement the StartBusyEvent method to raise the StartBusy event task. In the blank line below the comment, type the following code:
private void StartBusyEvent() { if (StartBusy != null) StartBusy(this, new EventArgs()); }

7. 8.

In the Task List window, double-click the TODO: Exercise 2: Task 3d: Implement the EndBusyEvent method to raise the EndBusy event task. In the blank line below the comment, type the following code:
private void EndBusyEvent() { if (EndBusy != null) EndBusy(this, new EventArgs()); }

9.

In Solution Explorer, double-click MainWindow.xaml.

10. In the MainWindow.xaml file, locate the TODO: Exercise 2: Task 3e: Wire up the StartBusy and EndBusy event handlers for the StudentsPage view comment. 11. Immediately below the comment, modify the StudentsPage element to include StartBusy and EndBusy attributes, as the following code shows:
<y:StudentsPage x:Name="studentsPage" StartBusy="StartBusy" EndBusy="EndBusy" StudentSelected="studentsPage_StudentSelected" Visibility="Collapsed" />

MCT USE ONLY. STUDENT USE PROHIBITED

L10-8 Programming in Visual C#

12. In the Task List window, double-click the TODO: Exercise 2: Task 3f: Raise the StartBusy event task. 13. In the blank line below the comment, type the following code:
StartBusyEvent();

14. In the Task List window, double-click the TODO: Exercise 2: Task 3g: Raise the EndBusy event task. 15. In the blank line below the comment, type the following code:
EndBusyEvent();

X Task 4: Build and test the application


1. 2. 3. 4. 5. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging. When the application loads, in the Username box, type vallee, and in the Password box, type password99, and then click Log on.

Verify that the application displays the busy indicator while waiting for the list of students to load, and then close the application window. On the File menu, click Close Solution.

Results: After completing this exercise, you should have updated the Grades application to display a progress indicator while the application is retrieving data.

MCT USE ONLY. STUDENT USE PROHIBITED


L11-1

Module 11: Integrating with Unmanaged Code

Lab: Upgrading the Grades Report


Exercise 1: Generating the Grades Report by Using Word

X Task 1: Examine the WordWrapper class that provides a functional wrapper around the dynamic (COM) API for Word
1. 2. 3. Start the MSL-TMG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-11 virtual machine. Log on to Windows 8 as Student with the password Pa$$w0rd.

Note: If necessary, click Switch User to display a list of users in the Windows 8 logon screen. 4. 5. 6. 7. 8. 9. Switch to the Windows 8 Start window. Click Visual Studio 2012. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click Grades.sln, and then click Open. In Solution Explorer, right-click Solutions Grades, and then click Properties.

On the Startup Project page, click Multiple startup projects. Set Grades.Web and Grades.WPF to Start without debugging, and then click OK.

10. In Solution Explorer, expand Grades.Utilities, and then double-click WordWrapper.cs. 11. Examine the code that is currently contained within this class. 12. On the View menu, click Task List. 13. In the Task List window, in the Categories list, click Comments.

14. Double-click the TODO: Exercise 1: Task 1a: Create a dynamic variable called _word for activating Word task. 15. In the code editor, click in the blank line below the comment, and then type the following code: 16. dynamic _word = null;

17. In the Task List window, double-click the TODO: Exercise 1: Task 1b: Instantiate _word as a new Word Application object task. 18. In the code editor, click in the blank line below the comment, and then type the following code:
this._word = new Application { Visible = false };

19. In the Task List window, double-click the TODO: Exercise 1: Task 1c: Create a new Word document task. 20. In the code editor, click in the blank line below the comment, and then type the following code:
var doc = this._word.Documents.Add();

MCT USE ONLY. STUDENT USE PROHIBITED

L11-2 Programming in Visual C#

doc.Activate();

21. In the Task List window, double-click TODO: Exercise 1: Task 1d: Save the document using the specified filename. task. 22. In the code editor, click in the blank line below the comment, and then type the following code:
var currentDocument = this._word.ActiveDocument; currentDocument.SaveAs(filePath);

23. In the Task List window, double-click the TODO: Exercise 1: Task 1e: Close the document task. 24. In the code editor, click in the blank line below the comment, and then type the following code:
currentDocument.Close();

25. In the Task List window, double-click the TODO: Exercise 1: Task 1f: Find the end of the document task.

26. In the code editor, delete the existing code below the comment, and then type the following code:
return this._word.ActiveDocument.Range(this._word.ActiveDocument.Content.End - 1);

X Task 2: Add code to the GeneratedStudentReport method to generate a Word document


1. 2.

In the Task List window, double-click the TODO: Exercise 1: Task 2a: Generate a student grade report as a Word document. task.

In the code editor, in the GenerateStudentReport method, click in the blank line, and then type the following code:
WordWrapper wrapper = new WordWrapper(); // Create a new Word document in memory wrapper.CreateBlankDocument(); // Add a heading to the document wrapper.AppendHeading(String.Format("Grade Report: {0} {1}", studentData.FirstName, studentData.LastName)); wrapper.InsertCarriageReturn(); wrapper.InsertCarriageReturn(); // Output the details of each grade for the student foreach (var grade in SessionContext.CurrentGrades) { wrapper.AppendText(grade.SubjectName, true, true); wrapper.InsertCarriageReturn(); wrapper.AppendText("Assessment: " + grade.Assessment, false, false); wrapper.InsertCarriageReturn(); wrapper.AppendText("Date: " + grade.AssessmentDateString, false, false); wrapper.InsertCarriageReturn(); wrapper.AppendText("Comment: " + grade.Comments, false, false); wrapper.InsertCarriageReturn(); wrapper.InsertCarriageReturn(); } // Save the Word document wrapper.SaveAs(reportPath);

3. 4.

In the Task List window, double-click the TODO: Exercise 1: Task 2b: Generate the report by using a separate task task. In the code editor, click in the blank line below the comment, and then type the following code:

MCT USE ONLY. STUDENT USE PROHIBITED


L11-3

Task.Run(() => GenerateStudentReport(SessionContext.CurrentStudent, dialog.FileName));

X Task 3: Build and test the application


1. 2. 3. 4. 5. 6. 7. 8. 9. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging.

When the application loads, in the Username box, type vallee, and in the Password box, type password99, and then click Log on. Click Kevin Liu, and then click save report. In the Save As dialog box, browse to E:\Labfiles\Starter\Exercise 1.

In the File name box, delete the existing contents, type Kevin Liu Grades Report, and then click Save.

Close the application, and then in Microsoft Visual Studio, on the File menu, click Close Solution. Open File Explorer, browse to the E:\Labfiles\Starter\Exercise 1 folder, and then verify that the report has been generated. Double-click Kevin Liu Grades Report.docx.

10. Review the grade report, and then in Word, on the File menu, click Exit.

Results: After completing this exercise, the application will generate grade reports in Word format.

MCT USE ONLY. STUDENT USE PROHIBITED

L11-4 Programming in Visual C#

Exercise 2: Controlling the Lifetime of Word Objects by Implementing the Dispose Pattern
X Task 1: Run the application to generate a grades report and view the Word task in Task Manager
1. 2. 3. 4. 5. 6. 7. 8. 9. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click Grades.sln, and then click Open. In Solution Explorer, right-click Solutions Grades, and then click Properties.

On the Startup Project page, click Multiple startup projects. Set Grades.Web and Grades.WPF to Start without debugging, and then click OK. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging. When the application loads, in the Username box, type vallee, and in the Password box, type password99, and then click Log on. Click Kevin Liu, and then click save report. In the Save As dialog box, browse to E:\Labfiles\Starter\Exercise 2.

10. In the File name box, delete the existing contents, type Kevin Liu Grades Report, and then click Save. 11. Close the application. 12. Open File Explorer, browse to the E:\Labfiles\Starter\Exercise 2 folder, and then verify that the report has been generated. 13. Right-click the taskbar, and then click Task Manager. 14. In the Task Manager window, click More details.

15. In the Name column, in the Background processes group, verify that Microsoft Word (32 bit) is still running. 16. Click Microsoft Word (32 bit), and then click End task. 17. Close Task Manager.

X Task 2: Update the WordWrapper class to terminate Word correctly


1. 2.

In Visual Studio, in the Task List window, double-click the TODO: Exercise 2: Task 2a: Specify that the WordWrapper class implements the IDisposable interface task. In the code editor, on the line below the comment, click at the end of the public class WordWrapper code, and then type the following code:
:IDisposable

3. 4.

In the Task List window, double-click the TODO: Exercise 2: Task 2b: Create the protected Dispose(bool) method task. In the code editor, click in the blank line below the comment, and then type the following code:
protected virtual void Dispose(bool isDisposing) {

MCT USE ONLY. STUDENT USE PROHIBITED


L11-5

if (!this.isDisposed) { if (isDisposing) { // Release managed resources here if (this._word != null) { this._word.Quit(); } } // Release unmanaged resources here if (this._word != null) { System.Runtime.InteropServices.Marshal.ReleaseComObject(this._word); } this.isDisposed = true; } }

5. 6.

In the Task List window, double-click the TODO: Exercise 2: Task 2c: Create the public Dispose method task. In the code editor, click at the end of the comment, press Enter, and then type the following code:
public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); }

7. 8.

In the Task List window, double-click the TODO: Exercise 2: Task 2d: Create a finalizer that calls the Dispose method task. In the code editor, click in the blank line below the comment, and then type the following code:
private bool isDisposed = false;

X Task 3: Wrap the object that generates the Word doc in a using statement
1. 2.

In the Task List window, double-click the TODO: Exercise 2: Task 3: Ensure that the WordWrapper is disposed when the method finishes task.

Below the comment, modify the WordWrapper wrapper = new WordWrapper(); code to look like the following:
using (var wrapper = new WordWrapper()) {

3. 4.

At the end of the method, after the wrapper.SaveAs(reportPath); line of code, add a closing brace to end the using block. Your code should look like the following:

public void GenerateStudentReport(LocalStudent studentData, string reportPath) { // TODO: Exercise 2: Task 3: Ensure that the WordWrapper is disposed when the method finishes using (var wrapper = new WordWrapper()) { // Create a new Word document in memory wrapper.CreateBlankDocument();

MCT USE ONLY. STUDENT USE PROHIBITED

L11-6 Programming in Visual C#

// Add a heading to the document wrapper.AppendHeading(String.Format("Grade Report: {0} {1}", studentData.FirstName, studentData.LastName)); wrapper.InsertCarriageReturn(); wrapper.InsertCarriageReturn(); // Output the details of each grade for the student foreach (var grade in SessionContext.CurrentGrades) { wrapper.AppendText(grade.SubjectName, true, true); wrapper.InsertCarriageReturn(); wrapper.AppendText("Assessment: " + grade.Assessment, false, false); wrapper.InsertCarriageReturn(); wrapper.AppendText("Date: " + grade.AssessmentDateString, false, false); wrapper.InsertCarriageReturn(); wrapper.AppendText("Comment: " + grade.Comments, false, false); wrapper.InsertCarriageReturn(); wrapper.InsertCarriageReturn(); } // Save the Word document wrapper.SaveAs(reportPath); } }

X Task 4: Use Task Manager to observe that Word terminates correctly after generating a report
1. 2. 3. 4. 5. 6. 7. 8. 9. On the Build menu, click Build Solution. Right-click the taskbar, and then click Task Manager. In Visual Studio, on the Debug menu, click Start Without Debugging. When the application loads, in the Username box, type vallee, and in the Password box, type password99, and then click Log on. Click George Li, and then click save report. In the Save As dialog box, browse to E:\Labfiles\Starter\Exercise 2. In the File name box, delete the existing contents, and then type George Li Grades Report.

As you click Save, in the Task Manager window, watch the Background processes and verify that Microsoft Word (32 bit) appears and then disappears from the list. Close Task Manager, and then close the application.

10. In Visual Studio, on the File menu, click Close Solution.

Results: After completing this exercise, the application will terminate Word correctly after it has generated a grades report.

MCT USE ONLY. STUDENT USE PROHIBITED


L12-1

Module 12: Creating Reusable Types and Assemblies

Lab: Specifying the Data to Include in the Grades Report


Exercise 1: Creating and Applying the IncludeInReport attribute
X Task 1: Write the code for the IncludeInReportAttribute class
1. 2. Start the 20483A-SEA-DEV11-12 virtual machine. Log on to Windows 8 as Student with the password Pa$$w0rd. Note: If necessary, click Switch User to display the list of users. 3. 4. 5. 6. 7. 8. 9. Switch to the Windows 8 Start window. Click Visual Studio 2012. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click Grades.sln, and then click Open. In Solution Explorer, right-click Solutions Grades, and then click Properties.

On the Startup Project page, click Multiple startup projects. Set Grades.Web and Grades.WPF to Start without debugging, and then click OK. In Solution Explorer, expand Grades.Utilities, and then double-click IncludeInReport.cs.

10. On the View menu, click Task List. 11. In the Task List window, in the Categories list, click Comments.

12. Double-click the TODO: Exercise 1: Task 1a: Specify that IncludeInReportAttribute is an attribute class task. 13. In the code editor, below the comment, click at the end of the public public class IncludeInReportAttribute code, and then type the following code:
: Attribute

14. In the Task List window, double-click the TODO: Exercise 1: Task 1b: Specify the possible targets to which the IncludeInReport attribute can be applied task. 15. In the code editor, click in the blank line below the comment, and then type the following code:

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]

16. In the Task List window, double-click the TODO: Exercise 1: Task 1c: Define a private field to hold the value of the attribute task. 17. In the code editor, click in the blank line below the comment, and then type the following code:
private bool _include;

MCT USE ONLY. STUDENT USE PROHIBITED

L12-2 Programming in Visual C#

18. In the Task List window, double-click the TODO: Exercise 1: Task 1d: Add public properties that specify how an included item should be formatted task. 19. In the code editor, click in the blank line below the comment, and then type the following code:
public bool Underline { get; set; } public bool Bold { get; set; }

20. In the Task List window, double-click the TODO: Exercise 1: Task 1e: Add a public property that specifies a label (if any) for the item task. 21. In the code editor, click in the blank line below the comment, and then type the following code:
public string Label { get; set; }

22. In the Task List window, double-click the TODO: Exercise 1: Task 1f: Define constructors task.

23. In the code editor, click at the end of the comment, press Enter, and then type the following code:
public IncludeInReportAttribute() { this._include = true; this.Underline = false; this.Bold = false; this.Label = string.Empty; } public IncludeInReportAttribute(bool includeInReport) { this._include = includeInReport; this.Underline = false; this.Bold = false; this.Label = string.Empty; }

X Task 2: Apply the IncludeInReportAttribute attribute to the appropriate properties


1. 2. 3. 4. In Solution Explorer, expand Grades.WPF, and then double-click Data.cs.

In the Task List window, double-click the TODO: Exercise 1: Task 2: Add the IncludeInReport attribute to the appropriate properties in the LocalGrade class task. In the LocalGrade method, expand the Properties region, and then expand the Readonly Properties region. Above the public string SubjectName code, click in the blank line, and then type the following code:
[IncludeInReport(Label="Subject Name", Bold=true, Underline=true)]

5.

Above the public string AssessmentDateString code, click in the blank line, press Enter, and then type the following code:
[IncludeInReport (Label="Date")]

6. 7.

Expand the Form Properties region.

Above the public string Assessment code, click in the blank line, press Enter, and then type the following code:
[IncludeInReport(Label = "Grade")]

MCT USE ONLY. STUDENT USE PROHIBITED


L12-3

8.

Above the public string Comments code, click in the blank space, press Enter, and then type the following code:
[IncludeInReport(Label = "Comments")]

X Task 3: Build the application and review the metadata for the LocalGrades class
1. 2. 3. 4. 5. 6. 7. On the Build menu, click Build Solution. Open File Explorer and browse to the C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools folder. Right-click ildasm.exe, and then click Open. In the IL DASM window, on the File menu, click Open. In the Open dialog box, browse to E:\Labfiles\Starter\Exercise 1\Grades.WPF\bin\Debug, click Grades.WPF.exe, and then click Open.

In the IL DASM application window, expand Grades.WPF, expand Grades.WPF.LocalGrade, and then double-click Assessment : instance string();.

In the Grades.WPF.LocalGrade::Assessment : instance string() window, in the Assessment method, verify that the .custom instance void [Grades.Utilities]Grades.Utilities.IncludeInReportAttribute::.ctor() code is present, and then close the window. In the IL DASM application window, double-click AssessmentDateString : instance string();.

8. 9.

In the Grades.WPF.LocalGrade::AssessmentDateString : instance string() window, in the AssessmentDateString method, verify that the .custom instance void [Grades.Utilities]Grades.Utilities.IncludeInReportAttribute::.ctor() code is present, and then close the window.

10. In the IL DASM application window, double-click Comments : instance string();.

11. In the Grades.WPF.LocalGrade::Comments : instance string() window, in the Comments method, verify that the .custom instance void [Grades.Utilities]Grades.Utilities.IncludeInReportAttribute::.ctor() code is present, and then close the window. 12. In the IL DASM application window, double-click SubjectName : instance string();.

13. In the Grades.WPF.LocalGrade::SubjectName : instance string() window, in the SubjectName method, verify that the .custom instance void [Grades.Utilities]Grades.Utilities.IncludeInReportAttribute::.ctor() code is present, and then close the window. 14. Close the IL DASM application. 15. Close File Explorer. 16. In Visual Studio, on the File menu, click Close Solution.

Results: After completing this exercise, the Grades.Utilities assembly will contain an IncludeInReport custom attribute and the Grades class will contain fields and properties that are tagged with that attribute.

MCT USE ONLY. STUDENT USE PROHIBITED

L12-4 Programming in Visual C#

Exercise 2: Updating the Report


X Task 1: Implement a static helper class called IncludeProcessor
1. 2. 3. 4. 5. 6. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click Grades.sln, and then click Open. In Solution Explorer, expand Grades.Utilities, and then double-click IncludeInReport.cs. Below the Output window, click Task List.

In the Task List window, double-click the TODO: Exercise 2: Task 1a: Define a struct that specifies the formatting to apply to an item task.

In the code editor, click in the blank line in the FormatField struct, and then type the following code:
public public public public string Value; string Label; bool IsBold; bool IsUnderlined;

7. 8.

In the Task List window, double-click the TODO: Exercise 2: Task 1b: Find all the public fields and properties in the dataForReport object task. In the code editor, click in the blank line below the comment, and then type the following code:
Type dataForReportType = dataForReport.GetType(); fieldsAndProperties.AddRange(dataForReportType.GetFields()); fieldsAndProperties.AddRange(dataForReportType.GetProperties());

9.

In the Task List window, double-click the TODO: Exercise 2: Task 1c: Iterate through all public fields and properties, and process each item that is tagged with the IncludeInReport attribute task.

10. In the code editor, click in the blank line below the comment, and then type the following code:
foreach (MemberInfo member in fieldsAndProperties) {

11. In the Task List window, double-click the TODO: Exercise 2: Task 1d: Determine whether the current member is tagged with the IncludeInReport attribute task. 12. In the code editor, click in the blank line below the comment, and then type the following code:

object[] attributes = member.GetCustomAttributes(false); IncludeInReportAttribute attributeFound = Array.Find(attributes, a => a.GetType() == typeof(IncludeInReportAttribute)) as IncludeInReportAttribute;

13. In the Task List window, double-click the TODO: Exercise 2: Task 1e: If the member is tagged with the IncludeInReport attribute, construct a FormatField item task. 14. In the code editor, click in the blank line below the comment, and then type the following code:
if (attributeFound != null) { // Find the value of the item tagged with the IncludeInReport attribute string itemValue; if (member is FieldInfo) { itemValue = (member as FieldInfo).GetValue(dataForReport).ToString(); } else {

MCT USE ONLY. STUDENT USE PROHIBITED


L12-5

itemValue = (member as PropertyInfo).GetValue(dataForReport).ToString(); }

15. In the Task List window, double-click the TODO: Exercise 2: Task 1f: Construct a FormatField item with this data task. 16. In the code editor, click in the blank line below the comment, and then type the following code:
FormatField item = new FormatField() { Value = itemValue, Label = attributeFound.Label, IsBold = attributeFound.Bold, IsUnderlined = attributeFound.Underline };

17. In the Task List window, double-click the TODO: Exercise 2: Task 1g: Add the FormatField item to the collection to be returned task. 18. In the code editor, click in the blank line below the comment, and then type the following code:
items.Add(item); } }

X Task 2: Update the report functionality for the StudentProfile view


1. 2. 3.

In Solution Explorer, expand Grades.WPF, expand Views, expand StudentProfile.xaml, and then double-click StudentProfile.xaml.cs. In the Task List window, double-click the TODO: Exercise 2: Task 2a: Use the IncludeProcessor to determine which fields in the Grade object are tagged task.

In the code editor, click in the blank line below the comment, and then type the following code:
List<FormatField> itemsToReport = IncludeProcessor.GetItemsToInclude(grade);

4. 5.

In the Task List window, double-click the TODO: Exercise 2: Task 2b: Output each tagged item, using the format specified by the properties of the IncludeInReport attribute for each item task. In the code editor, click in the blank line below the comment, and then type the following code:
foreach (FormatField item in itemsToReport) { wrapper.AppendText(item.Label == string.Empty ? item.Value : item.Label + ": " + item.Value, item.IsBold, item.IsUnderlined); wrapper.InsertCarriageReturn(); }

6. 7.

On the Build menu, click Build Solution. On the File menu, click Close Solution.

Results: After completing this exercise, the application will be updated to use reflection to include only the tagged fields and properties in the grades report.

MCT USE ONLY. STUDENT USE PROHIBITED

L12-6 Programming in Visual C#

Exercise 3: Storing the Grades.Utilities Assembly Centrally


X Task 1: Sign the Grades.Utilities assembly and deploy it to the GAC
1. 2. 3. 4. 5. 6. 7. 8. 9. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 3, click Grades.sln, and then click Open. In Solution Explorer, right-click Solutions Grades, and then click Properties.

On the Startup Project page, click Multiple startup projects. Set Grades.Web and Grades.WPF to Start without debugging, and then click OK. Switch to the Windows 8 Start window. In the Start window, right-click the background to display the taskbar. On the taskbar, click All apps. In the Start window, right-click the VS2012 x86 Native Tools Command icon. On the taskbar, click Run as administrator.

10. In the User Account Control dialog box, in the Password box, type Pa$$w0rd, and then click Yes. 11. At the command prompt, type the following code, and then press Enter:
E:

12. At the command prompt, type the following code, and then press Enter:
cd E:\Labfiles\Starter

13. At the command prompt, type the following code, and then press Enter:
sn -k GradesKey.snk

14. Verify that the text Key pair written to GradesKey.snk is displayed. 15. In Visual Studio, in Solution Explorer, right-click Grades.Utilities, and then click Properties. 16. On the Signing tab, select Sign the assembly. 17. In the Choose a strong name key file list, click Browse.

18. In the Select File dialog box, browse to E:\Labfiles\Starter, click GradesKey.snk, and then click Open. 19. On the Build menu, click Build Solution. 20. Switch to the command prompt, type the following code, and then press Enter:
cd E:\Labfiles\Starter\Exercise 3\Grades.Utilities\bin\Debug

21. At the command prompt, type the following code, and then press Enter:
gacutil -i Grades.Utilities.dll

22. Verify that the text Assembly successfully added to the cache is displayed, and then close the Command Prompt window.

X Task 2: Reference the Grades.Utilities assembly in the GAC from the application
1. 2. 3. 4. 5. 6. 7. 8. 9. In Visual Studio, in Solution Explorer, expand Grades.WPF, expand References, right-click Grades.Utilities, and then click Remove. Right-click References, and then click Add Reference. In the Reference Manager Grades.WPF dialog box, click the Browse button. In the Select the files to reference dialog box, browse to E:\Labfiles\Starter\Exercise 3\Grades.Utilities\bin\Debug, click Grades.Utilities.dll, and then click Add. In the Reference Manager Grades.WPF dialog box, click OK. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging.

In the Username box, type vallee, and in the Password box, type password99, and then click Log on. In the Class 3C view, click Kevin Liu.

MCT USE ONLY. STUDENT USE PROHIBITED


L12-7

10. Verify that the student report for Kevin Liu appears, and then click save report. 11. In the Save As dialog box, browse to the E:\Labfiles\Starter\Exercise 3 folder. 12. In the File name box, type KevinLiuGradesReport, and then click Save. 13. Close the application. 14. In Visual Studio, on the File menu, click Close Solution. 15. Open File Explorer, browse to E:\Labfiles\Starter\Exercise 3, and then verify that KevinLiuGradesReport.docx has been generated. 16. Right-click KevinLiuGradesReport.docx, and then click Open.

17. Verify that the document contains the grade report for Kevin Liu and that it is correctly formatted, and then close Word.

Results: After completing this exercise, you will have a signed version of the Grades.Utilities assembly deployed to the GAC.

MCT USE ONLY. STUDENT USE PROHIBITED

MCT USE ONLY. STUDENT USE PROHIBITED


L13-1

Module 13: Encrypting and Decrypting Data

Lab: Encrypting and Decrypting the Grades Report


Exercise 1: Encrypting the Grades Report
X Task 1: Create an asymmetric certificate
1. 2. 3. Start the MSL-TMG1 virtual machine if it is not already running. Start the 20483A-SEA-DEV11-13 virtual machine. Log on to Windows 8 as Student with the password Pa$$w0rd. Note: If necessary, click Switch User to display the list of users. 4. 5. 6. 7. 8. 9. Switch to the Windows 8 Start window. Click Visual Studio 2012.

In Microsoft Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click Grades.sln, and then click Open. In Solution Explorer, right-click Solutions Grades, and then click Properties.

On the Startup Project page, click Multiple startup projects. Set Grades.Web and Grades.WPF to Start without debugging, and then click OK.

10. In Solution Explorer, expand the Grades.Utilities node, and then double-click the CreateCertificate.cmd file. 11. Review the contents of this file. 12. Switch to the Windows 8 Start window. 13. In the Start window, right-click the background to display the task bar. 14. On the task bar, click All apps. 15. In the Start window, right-click the VS2012 x86 Native Tools Command icon. 16. On the task bar, click Run as administrator.

17. In the User Account Control dialog box, in the Password box, type Pa$$w0rd, and then click Yes. 18. At the command prompt, type the following, and then press Enter.
E:

19. At the command prompt, type the following, and then press Enter.
cd E:\Labfiles\Starter\Exercise 1\Grades.Utilities

20. At the command prompt, type the following, and then press Enter.
CreateCertificate.cmd

MCT USE ONLY. STUDENT USE PROHIBITED

L13-2 Programming in C#

21. Verify that the command returns a success message, and then close the command window.

X Task 2: Retrieve the Grade certificate


1. 2. 3. 4. In Visual Studio, on the View menu, click Task List. In the Task List window, in the Categories list, click Comments.

Double-click the TODO: Exercise 1: Task 2a: Loop through the certificates in the X509 store to return the one matching _certificateSubjectName. task. In the code editor, click in the blank line below the comment, and then type the following code:
foreach (var cert in store.Certificates) if (cert.SubjectName.Name.Equals(this._certificateSubjectName, StringComparison.InvariantCultureIgnoreCase)) return cert;

X Task 3: Encrypt the data


1. 2.

In the Task List window, double-click the TODO: Exercise 1: Task 3a: Get the public key from the X509 certificate. task. In the code editor, delete the following line of code:
throw new NotImplementedException();

3. 4. 5. 6.

In the blank line below the comment, type the following code: var provider = (RSACryptoServiceProvider)this._certificate.PublicKey.Key;

In the Task List window, double-click the TODO: Exercise 1: Task 3b: Create an instance of the AesManaged algorithm. task. In the code editor, click in the blank line below the comment, and then type the following code:
using (var algorithm = new AesManaged()) {

7. 8.

In the Task List window, double-click the TODO: Exercise 1: Task 3c: Create an underlying stream for the unencrypted data. task. In the code editor, click in the blank line below the comment, and then type the following code:
using (var outStream = new MemoryStream()) {

9.

In the Task List window, double-click the TODO: Exercise 1: Task 3d: Create an AES encryptor based on the key and IV. task.

10. In the code editor, click in the blank line below the comment, and then type the following code:
using (var encryptor = algorithm.CreateEncryptor()) { var keyFormatter = new RSAPKCS1KeyExchangeFormatter(provider); var encryptedKey = keyFormatter.CreateKeyExchange(algorithm.Key, algorithm.GetType());

11. In the Task List window, double-click the TODO: Exercise 1: Task 3e: Create byte arrays to get the length of the encryption key and IV. task. 12. In the code editor, click in the blank line below the comment, and then type the following code:

MCT USE ONLY. STUDENT USE PROHIBITED


L13-3

var keyLength = BitConverter.GetBytes(encryptedKey.Length); var ivLength = BitConverter.GetBytes(algorithm.IV.Length);

13. In the Task List window, double-click the TODO: Exercise 1: Task 3f: Write the following to the out stream: task.

14. In the code editor, click in the blank line below the comment block, and then type the following code:
outStream.Write(keyLength, 0, keyLength.Length); outStream.Write(ivLength, 0, ivLength.Length); outStream.Write(encryptedKey, 0, encryptedKey.Length); outStream.Write(algorithm.IV, 0, algorithm.IV.Length);

15. In the Task List window, double-click the TODO: Exercise 1: Task 3g: Create a CryptoStream that will write the encrypted data to the underlying buffer. task. 16. In the code editor, click in the blank line below the comment, and then type the following code:

using (var encrypt = new CryptoStream(outStream, encryptor, CryptoStreamMode.Write)) {

17. In the Task List window, double-click the TODO: Exercise 1: Task 3h: Write all the data to the stream. task. 18. In the code editor, click in the blank line below the comment, and then type the following code:
encrypt.Write(bytesToEncrypt, 0, bytesToEncrypt.Length); encrypt.FlushFinalBlock();

19. In the Task List window, double-click the TODO: Exercise 1: Task 3i: Return the encrypted buffered data as a byte. task.

20. In the code editor, click in the blank line below the comment, and then type the following code:
return outStream.ToArray(); } } } }

X Task 4: Write the encrypted data to disk


1. 2.

In the Task List window, double-click the TODO: Exercise 1: Task 4a: Write the encrypted bytes to disk. task. In the code editor, click in the blank line below the comment, and then type the following code:
File.WriteAllBytes(filePath, encryptedBytes);

X Task 5: Build and test the application


1. 2. 3. 4. 5. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging.

When the application loads, in the Username box, type vallee, and in the Password box, type password99, and then click Log on. In the Class 3C view, click George Li. In the Report Card view, click save report.

MCT USE ONLY. STUDENT USE PROHIBITED

L13-4 Programming in C#

6. 7. 8. 9.

In the Save As dialog box, browse to the E:\Labfiles\Reports folder, in the File name box, type GeorgeLi, and then click Save. In the Report Card view, click Back. In the Class 3C view, click Kevin Liu. In the Report Card view, click save report.

10. In the Save As dialog box, browse to the E:\Labfiles\Reports folder, in the File name box, type KevinLiu, and then click Save. 11. In the Report Card view, click Log off, and then close the application. 12. On the File menu, click Close Solution.

13. Open Windows Internet Explorer, and in the address bar, type E:\Labfiles\Reports\KevinLiu.xml, and then press Enter. 14. Note the page is blank because the file is encrypted, and then close Internet Explorer. 15. Open File Explorer, and then browse to the E:\Labfiles\Reports folder. 16. Right-click KevinLiu.xml, and then click Edit. 17. Review the encrypted data, close Notepad, and then close File Explorer.

Results: After completing this exercise, you should have updated the Grades application to encrypt generated reports.

MCT USE ONLY. STUDENT USE PROHIBITED


L13-5

Exercise 2: Decrypting the Grades Report


X Task 1: Decrypt the data
1. 2. 3. 4. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click School-Reports.sln, and then click Open. In the Task List window, double-click the TODO: Exercise 2: Task 1a: Get the private key from the X509 certificate. task. In the code editor, delete the following line of code:
throw new NotImplementedException();

5.

In the blank line below the comment, type the following code:
var provider = (RSACryptoServiceProvider)this._certificate.PrivateKey;

6. 7.

In the Task List window, double-click the TODO: Exercise 2: Task 1b: Create an instance of the AESManaged algorithm which the data is encrypted with. task. In the blank line below the comment, type the following code:
using (var algorithm = new AesManaged()) {

8. 9.

In the Task List window, double-click the TODO: Exercise 2: Task 1c: Create a stream to process the bytes. task. In the blank line below the comment, type the following code:
using (var inStream = new MemoryStream(bytesToDecrypt)) {

10. In the Task List window, double-click the TODO: Exercise 2: Task 1d: Create byte arrays to get the length of the encryption key and IV. task. 11. In the blank line below the comment, type the following code:
var keyLength = new byte[4]; var ivLength = new byte[4];

12. In the Task List window, double-click the TODO: Exercise 2: Task 1e: Read the key and IV lengths starting from index 0 in the in stream. task. 13. In the blank line below the comment, type the following code:
inStream.Seek(0, SeekOrigin.Begin); inStream.Read(keyLength, 0, keyLength.Length); inStream.Read(ivLength, 0, ivLength.Length);

14. In the Task List window, double-click the TODO: Exercise 2: Task 1f: Convert the lengths to ints for later use. task. 15. In the blank line below the comment, type the following code:
var convertedKeyLength = BitConverter.ToInt32(keyLength, 0); var convertedIvLength = BitConverter.ToInt32(ivLength, 0);

MCT USE ONLY. STUDENT USE PROHIBITED

L13-6 Programming in C#

16. In the Task List window, double-click the TODO: Exercise 2: Task 1g: Determine the starting position and length of data. task. 17. In the blank line below the comment, type the following code:
var dataStartPos = convertedKeyLength + convertedIvLength + keyLength.Length + ivLength.Length; var dataLength = (int)inStream.Length - dataStartPos;

18. In the Task List window, double-click the TODO: Exercise 2: Task 1h: Create the byte arrays for the encrypted key, the IV, and the encrypted data. task. 19. In the blank line below the comment, type the following code:
var encryptionKey = new byte[convertedKeyLength]; var iv = new byte[convertedIvLength]; var encryptedData = new byte[dataLength];

20. In the Task List window, double-click the TODO: Exercise 2: Task 1i: Read the key, IV, and encrypted data from the in stream. task. 21. In the blank line below the comment, type the following code:
inStream.Read(encryptionKey, 0, convertedKeyLength); inStream.Read(iv, 0, convertedIvLength); inStream.Read(encryptedData, 0, dataLength);

22. In the Task List window, double-click the TODO: Exercise 2: Task 1j: Decrypt the encrypted AesManaged encryption key. task. 23. In the blank line below the comment, type the following code:
var decryptedKey = provider.Decrypt(encryptionKey, false);

24. In the Task List window, double-click the TODO: Exercise 2: Task 1k: Create an underlying stream for the decrypted data. task. 25. In the blank line below the comment, type the following code:
using (var outStream = new MemoryStream()) {

26. In the Task List window, double-click the TODO: Exercise 2: Task 1l: Create an AES decryptor based on the key and IV. task. 27. In the blank line below the comment, type the following code:
using (var decryptor = algorithm.CreateDecryptor(decryptedKey, iv)) {

28. In the Task List window, double-click the TODO: Exercise 2: Task 1m: Create a CryptoStream that will write the decrypted data to the underlying buffer. task. 29. In the blank line below the comment, type the following code:

using (var decrypt = new CryptoStream(outStream, decryptor, CryptoStreamMode.Write)) {

30. In the Task List window, double-click the TODO: Exercise 2: Task 1n: Write all the data to the stream. task.

MCT USE ONLY. STUDENT USE PROHIBITED


L13-7

31. In the blank line below the comment, type the following code:
decrypt.Write(encryptedData, 0, dataLength); decrypt.FlushFinalBlock();

32. In the Task List window, double-click the TODO: Exercise 2: Task 1o: Return the decrypted buffered data as a byte[]. task. 33. In the blank line below the comment, type the following code:
return outStream.ToArray(); } } } } }

X Task 2: Build and test the solution


1. 2. 3. 4. 5. 6. 7. 8. 9. On the Build menu, click Build Solution. On the Debug menu, click Start Without Debugging. When the application loads, click Browse.

In the Browse For Folder dialog box, browse to the E:\Labfiles\Reports folder, and then click OK. Click Print.

In the Save Print Output As dialog box, browse to the E:\Labfiles\Reports\ClassReport folder, in the File name box, type 3CReport, and then click Save. In the The School of Fine Arts dialog box, click OK, and then close the application. Open File Explorer, and browse to the E:\Labfiles\Reports\ClassReport folder. Right-click 3CReport.oxps, and then click Open.

10. Review the unencrypted report, and then close the XPS Reader.

Results: After completing this exercise, you should have a composite unencrypted report that was generated from the encrypted reports.

Das könnte Ihnen auch gefallen