Download as pdf or txt
Download as pdf or txt
You are on page 1of 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 instructor-
led 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,
MCT USE ONLY. STUDENT USE PROHIBITED
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
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.

8. 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.

9. SUPPORT SERVICES. Because the Licensed Content is as is, we may not provide support services for it.

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.

12. ENTIRE AGREEMENT. This agreement, and the terms for supplements, updates and support services are
the entire agreement for the Licensed Content.

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#
x
MCT USE ONLY. STUDENT USE PROHIBITED
Programming in Visual C# xi

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# page 3
Lesson 2: Data Types, Operators, and Expressions page 11
Lesson 3: Visual C# Programming Language Constructs page 25
Lab: Developing the Class Enrollment Application page 38

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


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

Module 3: Developing the Code for a Graphical Application


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

Module 4: Creating Classes and Implementing Type-Safe Collections


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

Module 5: Creating a Class Hierarchy by Using Inheritance


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

Module 6: Reading and Writing Local Data


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

Module 7: Accessing a Database


Lesson 1: Creating and Using Entity Data Models page 3
Lesson 2: Querying Data by Using LINQ page 16
MCT USE ONLY. STUDENT USE PROHIBITED
Programming in Visual C# xiii

Lab: Retrieving and Modifying Grade Data page 28

Module 8: Accessing Remote Data


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

Module 9: Designing the User Interface for a Graphical Application


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

Module 10: Improving Application Performance and Responsiveness


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

Module 11: Integrating with Unmanaged Code


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

Module 12: Creating Reusable Types and Assemblies


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

Module 13: Encrypting and Decrypting Data


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

Lab Answer Keys


Module 1 Lab: Developing the Class Enrollment Application page 1
Module 2 Lab: Extending the Class Enrollment Application page 1
Module 3 Lab: Writing the Code for the Grades Prototype
Application 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 page 1
Module 5 Lab: Refactoring Common Functionality into the User
Class page 1
Module 6 Lab: Generating the Grades Report page 1
Module 7 Lab: Retrieving and Modifying Grade Data page 1
Module 8 Lab: Retrieving and Modifying Grade Data in the Cloud page 1
Module 9 Lab: Customizing Student Photographs and Styling
the Application page 1
Module 10 Lab: Improving the Responsiveness and Performance of
the Application page 1
Module 11 Lab: Upgrading the Grades Report page 1
Module 12 Lab: Specifying the Data to Include in the Grades Report page 1
Module 13 Lab: Encrypting and Decrypting the Grades Report page 1
MCT USE ONLY. STUDENT USE PROHIBITED
About This Course i

About This Course


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

Course Description

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, copy-
edited 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 Arithmetic operators to perform arithmetic calculations involving one or more variables.

o Relational operators to test the relationship between two variables or expressions.

o 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
About This Course iii

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
About This Course v

Virtual Machine Environment


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

Virtual Machine Configuration


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 Role


MSL-TMG1 Gateway computer for Internet access

20483A-SEA-DEV11-<Module 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 1-2

Lesson 1: Overview of Writing Application by Using Visual C# 1-3

Lesson 2: Data Types, Operators, and Expressions 1-11


Lesson 3: Visual C# Programming Language Constructs 1-25

Lab: Developing the Class Enrollment Application 1-38

Module Review and Takeaways 1-50


1-2 Review off Visual C# Syntax

Modu
ule Ove
erview

The Microsoft .NET Framew work version 44.5 provides a comprehensiive development platform that you
can use to buildd, deploy, and manage app plications and services. By using the .NET
T Framework, yyou can
cre
eate visually ccompelling appplications, enable seamlesss communicattion across tecchnology bouundaries,
and provide sup pport for a wid
de range of bbusiness proceesses.
In this module, yyou will learn about some of the core fe eatures provid
ded by the .NEET Frameworkk and
Miicrosoft Visual Studio. Yo ou will also leaarn about som
me of the core Visual C# cconstructs thaat enable
you to start devveloping .NET Framework aapplications.

Ob
bjectives
e, you will be able to:
Aftter completing this module

Describe the architecture


e of .NET Fram
mework appliccations and th
he features thaat Visual Stud
dio 2012
and Visual C#
C provide.

Use basic Visual


V C# data types, operattors, and exprressions.

Use standarrd Visual C# constructs.


c
Programmingg in Visual C# 1-3
3

Lesson 1
Overrview of Writin
ng App
plication
n by Ussing Vissual C#

The .NET Fram


T mework 4.5 an
nd Visual Stud
dio provide many features that
t you can use
u when devveloping your
a
applications.

IIn this lesson, you will learn


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 oown applicatioons.

L
Lesson Ob
bjectives
A
After completting this lesson, you will be able to:

Describe the purpose o


of the .NET Frramework.
Describe the key features of Visual SStudio 2012.

emplates provvided in Visual Studio 2012.


Describe the project te

Create a ..NET Framewo


ork applicatio
on.
1-4 Review off Visual C# Syntax

W
What Is the
e .NET Framework?

The .NET Frame ework 4.5 provvides a comprrehensive devvelopment plaatform that offfers a fast and
d efficient
waay to build applications and
d services. By using Visual SStudio 2012, you
y can use thhe .NET Frame ework 4.5
to create a widee range of solu
utions that op
perate across a broad range e of computin
ng devices.
The .NET Frame
ework 4.5 provvides three prrincipal eleme
ents:

The Commo
on Language Runtime (CLR
R).

The .NET Frramework classs 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 thhe CLR. The CLLR manages the execution of code
and simplifies th
he developme execution environment
ent process byy providing a robust and hiighly secure e
tha
at includes:

Memory maanagement.

Transaction
ns.

Multithread
ding.

Th
he .NET Fra
amework Cllass Library
y
The .NET Frame ework provide es a library of reusable classses that you caan use to builld application
ns. The
cla
asses provide a foundation of common ffunctionality and a constructss that help to simplify application
deevelopment byy, in part, elim
minating the n need to constaantly reinvent logic. For exaample, the
Sy
ystem.IO.File class containss functionalityy that enabless you to manip pulate files on
n the Window ws file
sysstem. In addittion to using tthe classes in tthe .NET Fram
mework class library, you caan extend thesse classes
byy creating your own librariees 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 Pressentation Foundation (WPFF).
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 off Visual C# Syntax

Ke
ey Feature
es of Visuaal Studio 2012

Vissual Studio 20
012 provides a single development envirronment that enables you tto rapidly design,
implement, build, test, and deploy various types of applications and components by using a rannge of
proogramming laanguages.
Some of the keyy features of V
Visual Studio 2
2012 are:

Intuitive inttegrated deve elopment enviironment (IDE E). The Visual Studio 2012 IDE provides aall of the
features and d tools that are necessary tto design, imp
plement, buildd, test, and de
eploy applicattions and
componentts.

Rapid application develo opment. Visuaal Studio 2012 2 provides dessign views for graphical com
mponents
that enablee you to easilyy build comple
ex user interfaaces. Alternatively, you can use the Codee Editor
views, which provide mo ore control but are not as eaasy to use. Vissual Studio 20
012 also proviides wizards
that help sp
peed up the d development o of particular components.
c

Server and data access. Visual


V Studio 2
2012 providess the Server Exxplorer, which h enables you to log on
to servers and explore th
heir databasess and system sservices. It also
o provides a ffamiliar way to
o create,
access, and modify databbases that youur application uses by using g the new tab
ble designer.

Internet Infformation Servvices (IIS) Express. Visual Studio 2012 pro weight version of IIS as
ovides a lightw
the default web server fo
or debugging your web app plications.

Debugging features. Visuual Studio 20112 provides a debugger tha at enables you
u to step thro
ough local
or remote ccode, pause att breakpoints,, and follow e
execution path
hs.

Error handling. Visual Stu


udio 2012 pro
ovides the Error List windo plays any errors,
ow, which disp
warnings, o
or messages th hat are produced as you ed
dit and build yyour code.

Help and do ocumentationn. Visual Studiio 2012 provid


des help and guidance thro
ough Microso
oft
IntelliSense, code snipp
pets, and the integrated heelp system, wh
hich contains documentatio
on and
samples.

Additiona
al Reading: FFor more inforrmation about what is new in Visual Studdio 2012, see
the
e What's New
w in Visual Sttudio 2012 p
page at http:///go.microsoft..com/fwlink/??LinkID=26776 68.
Programmingg in Visual C# 1-7
7

T
Templates
s in Visual Studio 2
2012

Visual Studio 2012 supportts the develop


V pment of diffeerent types of applications such as Windows-based
c
client applicattions, web-based applicatioons, services, and
a libraries. T g started, Visual Studio
To help you get
2
2012 providess application ttemplates tha
at provide a sttructure for th
he different tyypes 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 thaat are relevantt to the projecct type.
Configure
e the Visual Sttudio 2012 ID
DE to the type of application that you are
e developing.

Add referrences to any initial assemb


blies that this type of appliccation usuallyy requires.

T
Types of Te
emplates
The following table describ
T bes some of th
he common application tem mplates that yyou might use
e when you
d
develop .NET Framework applications byy using Visuall Studio 2012..

Template Descripttion

Console Application Providess the environmment settings,, tools, projecct references, aand starter co
ode
to devellop an applicaation that runs in a commaand-line interfface. This type e of
applicattion is conside
ered lightweig
ght because th here is no graphical user
interface
e.

Windows Fo orms Providess the environm


ment settings,, tools, projecct references, aand starter co
ode
Application to build a graphical W
Windows Formms application n.

WPF Appliccation Providess the environm


ment settings,, tools, projecct references, aand starter co
ode
to build a rich graphical Windows application. A WPF applicaation enables you
e the next generation of W
to create Windows applications, with much more
control over user inte
erface design.

Windows Sttore Providess the environm


ment settings,, tools, projecct references, aand starter co
ode
to build a rich graphical application targeted at the Windowss 8 operating
system. Windows Store application ns enable you to reuse skillss obtained fro om
WPF devvelopment byy using XAML and Visual C# #, but also fro
om web
developpment by using HTML 5, CSSS 3.0, and JavvaScript.
1-8 Review of Visual C# Syntax

Template Description

Class Library 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.

ASP.NET Web Application Provides the environment settings, tools, project references, and starter code
to create a server-side, compiled ASP.NET web application.

ASP.NET MVC 4 Provides the environment settings, tools, project references, and starter code
Application 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.

WCF Service Application Provides the environment settings, tools, project references, and starter code
to build Service Orientated Architecture (SOA) services.
Programmingg in Visual C# 1-9
9

C
Creating a .NET Fraamework A
Applicatio
on

The applicatio
T on templates provided in Visual
V 2012 enable you to start cre
Studio 2 eating an app
plication with
m
minimal effort. You can the
en add your code and custoomize the pro
oject to meet your own req quirements.

T following steps describ


The be how to crea
ate a console application:

1
1. Open Visual Studio 2012.

2
2. In Visual Studio, on the
e File menu, p
point to New,, and then clicck Project.

3
3. In the Ne
ew Project dia
alog box, do the
t following::

a. Expand Template
es, Visual C#, and then clickk Windows.

b. Click the Console Application template.

c. In the
e Name box, specify a nam
me for the pro
oject.
d. In the
e Location bo
ox, specify the
e path where you want to ssave the proje
ect.

4
4. Click OK.

5
5. The Codee Editor window now show
ws the default Program class, which contains the entrry point
method ffor the applicaation.

The following code example shows the d


T o provides when you use
default Progrram class thatt Visual Studio
t Console A
the Application ttemplate.

P
Program Classs
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 Exprressions

All application
A ns use data. This data mighht be suppliedd by the user tthrough a use
er interface, fro
om a
d
database, from
m a network sservice, or from some otherr source. To sttore and use data
d in your applications,
a
y must fam
you miliarize yourseelf with how tto define and use variables and how to create
c and use e expressions
w the varie
with ety of operators that Visual C# provides.

IIn this lesson, you will learn


n how to use some
s of the fu
undamental constructs
c Visual C#, such as variables,
in V
t
type memberrs, casting, and d string manip
pulation.

L
Lesson Ob
bjectives
A
After completting this lesson, you will be able to:

Describe the data type


es provided byy Visual C#.

Create an
nd use expresssions.
Declare aand assign varriables.

Access type members.

pe to another.
Cast dataa from one typ
Concaten
nate and validate strings.
1-12 Review of Visual C# Syntaxx

W
What are Data
D Typess?

A variable
v holdss data of a spe
ecific type. When you declaare a variable to store data in an applicaation, you
ne
eed to choose an appropriaate data type forf that data. Visual C# is a type-safe lan nguage, which h means
tha
at the compileer guaranteess that values stored in variaables are alwayys of the apprropriate type.

Co
ommonly Used
U Data T
Types
The following taable shows the commonly u
used data typ
pes in Visual C#,
C and their characteristics
c .

T
Type Desccription Size (b
bytes) Range

i
int Who
ole numbers 4 2,147,483,648 to 2,147
7,483,647

l
long Who ole numbers 8 9,223,372,036,854,775
5,808 to
(bigger range) 9,223,372,036,854,775,807

f
float Floaating-point 4 +/3.4 1
10^38
nummbers

d
double Douuble precision 8 +/1.7 1
10^308
(more accurate)
floatting-point
nummbers

d
decimal Mon
netary values 16 28 significcant figures

c
char Sing
gle character 2 N/A

b
bool Boolean 1 True or false

D
DateTime Mom
ments in time 8 0:00:00 on
n 01/01/2001 to
23:59:59 o
on 12/31/9999

s
string Sequuence of 2 per character N/A
charracters
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# Syntaxx

Exxpressionss and Ope


erators in V
Visual C#

Expressions are a central com


mponent of prractically everyy Visual C# ap
pplication, beccause expresssions are
the
e fundamentaal constructs tthat you use to evaluate annd manipulate e data. Expresssions are colle
ections of
op
perands and ooperators, whicch you can deefine as follow
ws:
Operands aare values, for example, num mbers and strrings. They can
n be constantt (literal) value
es,
variables, properties, or rreturn values from method calls.

Operators ddefine operatiions to perforrm on operand ds, for exampple, addition oor multiplicatioon.
Operators eexist for all of the basic matthematical op
perations, as wwell as for more advanced o operations
such as logical compariso on or the mannipulation of tthe bits of datta that constittute a value.

Alll expressions are


a evaluated to a single vaalue when you ur application pe of value that an
n runs. The typ
expression prod duces depends on the typess of the operaands that you use and the o operators thatt you use.
There is no limitt to the length
h of expressio
ons in Visual C
C# applicationns, although in
n practice, you u are
lim
mited by the mmemory of your computer and a your patience when tyyping. Howeve er, it is usuallyy advisable
to use shorter expressions an nd assemble thhe results of expression-pro
e ocessing piece emeal. This mmakes it
easier for you too see what your code is doing, as well ass making it easier to debug g your code.

Op
perators in Visual C#
Opperators comb bine operandss together into expressionss. Visual C# prrovides a wide
e range of opeerators that
you can use to pperform mostt fundamental mathematica al and logical operations. O
Operators fall into the
folllowing three categories:
Unary. This type of operaator operates on a single operand. For e c use the - operator as
example, you can
a unary ope e it immediately before a numeric
erator. To do this, you place n operaand, and it converts the
value of the
e operand to its current vallue multiplied
d by 1.
Binary. Thiss type of operaand operates on two valuees. This is the m n type of operator, for
most common
example, *, which multip plies the value
e of two opera
ands.

Ternary. There is only on


ne ternary ope
erator in Visuaal C#. This is the ? : operato
or that is used
d in
conditional expressions.

The following taable shows the operators th


hat you can use in Visual C#
#, grouped byy type.

T
Type Operators
Programming in Visual C# 1-15

Type Operators

Arithmetic +, -, *, /, %

Increment, decrement ++, --

Comparison ==, !=, <, >, <=, >=, is

String concatenation +

Logical/bitwise operations &, |, ^, !, ~, &&, ||

Indexing (counting starts from element 0) []

Casting ( ), as

Assignment =, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, ??

Bit shift <<, >>

Type information sizeof, typeof

Delegate concatenation and removal +, -

Overflow exception control checked, unchecked

Indirection and Address (unsafe code only) *, ->, [ ], &

Conditional (ternary operator) ?:

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 Varriables

Before you caan use a variab


B ble, you must declare it so that you can specify its nam me and characteristics. Thee
n
name dentifier. Visuaal C# has speccific rules concerning the id
of a varriable is referrred to as an id dentifiers thatt
y can use:
you
An identifier can only contain
c letters, digits, and underscore
u ch
haracters.

An identifier must startt with a letterr or an undersscore.

An identifier for a variaable should no


ot be one of the
t keywords that Visual C#
# reserves forr its own use.
Visual C# is caase sensitive. If you use the
V e name MyDa ata as the iden
ntifier of a varriable, this is not
n the same
a myData. You can declarre two variables at the same time called MyData and myData and Visual C#
as
w not confu
will use them, altho ough this is not good coding practice.

When declarin
W ng variables yyou should use
e meaningful names for yo
our variables, because
b this ccan make
y
your code eassier to understand. You sho
ould also adop
pt a naming cconvention annd use it!

D
Declaring a
and Assigniing Variable
When you declare a variable, you reservve some storag
W ge space for tthat variable in
n memory and the type of
d
data that it wiill hold. You ccan declare multiple variablles in a single declaration by
b using the comma
s
separator; all vvariables decllared in this w
way have the ssame type.

T following example sho


The ows how to de
eclare a new vvariable.

D
Declaring aV
Variable
// DataTypee variableNa
ame;
int price;
// OR
// DataTypee variableNa
ame1, variableName2;
int price, tax;

After you declare a variable


A e, you can asssign a value too it by using aan assignmentt statement. YYou can
c
change the vaalue in a variable as many ttimes as you w want during th he running off 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

member of an instance of a type, use the name of the instance, follo


To access a m
T owed by a perriod, followed
d
b the name of
by o the membeer. This is know
wn as dot nottation. Consid
der the followiing rules and guidelines
w
when you acccess a member of an instance:
To accesss a method, usse parenthese es after the na
ame of the me
ethod. In the parentheses,
p p
pass the
values forr any parametters that the m
method requires. If the metthod does nott take any parrameters, the
parenthesses are still required.

To accesss a public prop perty, use the


e property nam
me. You can then get the value of that p
property or
set the vaalue of that prroperty.

The following code example shows how to invoke the


T e members th
hat the Service
eConfiguratiion 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 prooperty.
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 infformation aboout using prop
perties, see th
he Propertiess (C#
Programming Guide) pag
P ge at http://go
o.microsoft.co
om/fwlink/?Lin
nkID=267773.
Additio
onal Reading: For more infformation aboout using metthods, 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# Syntaxx

Caasting Bettween Datta Types

Whhen you are d developing an n application, yyou will often


n need to convvert data fromm one type to another
typ
pe, for examp ple, when a value of one typ pe is assigned to a variable of a differentt type. Consid
der the
enario where a user enters a number into a text box. T
sce umber in a numerical calculation, you
To use this nu
will need to connvert the string value 99 thaat you have re ead from the text box into the integer vaalue 99 so
tha
at you can stoore it in an intteger variable. The process of converting g a value of onne data type to
t another
typ
pe is called type conversion n or casting.
There are two tyypes of conve
ersions in the ..NET Framewo
ork:

Implicit con
nversion, whicch is automatically performed by the CLR
R on operations that are gu
uaranteed
to succeed without losing g information
n.
Explicit conversion, which
h requires you
u to write cod
de to perform a conversion that otherwisse could
lose information or produce an error.

Explicit conversiion reduces th


he possibility of bugs in your code and m
makes your co
ode more efficcient. Visual
C#
# prohibits implicit conversiions that lose precision. Ho
owever, be aw
ware that some
e explicit convversions
can yield unexppected results.

Im
mplicit Conv
versions
An
n implicit convversion occurss when a value is converted d automatically from one d data type to an
nother. The
conversion doess not require aany special syyntax in the so
ource code. Viisual C# only allows safe im
mplicit
conversions, succh as the wide
ening of an integer.

The following co
ode example shows how daata is converted implicitly from
f an integer to a long, which
w is
terrmed 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 vvalue 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 shoows the implicit type conve
ersions that
are
e supported in
n Visual C#.
Programming in Visual C# 1-21

From To

sbyte short, int, long, float, double, decimal

byte short, ushort, int, uint, long, ulong, float, double,


decimal

short int, long, float, double, decimal

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

int long, float, double, decimal

uint long, ulong, float, double, decimal

long, ulong float, double, decimal

float double

char 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 vvery useful daata type that enable
e you to capture and store alphanu
umeric data.

C
Concatenat
ting Stringss
Concatenating
C g multiple strings in Visual C# is simple tto achieve byy using the + ooperator. How
wever, this is
c
considered baad coding praactice becausee strings are im
mmutable. This means thatt every time yo ou
c
concatenate a string, you ccreate a new sstring in memory and the o old string is discarded.

T following code example creates five


The e string valuess as it runs.

C
Concatenatio
on by Using tthe + Operattor
string addr
ress = "23";
address = a
address + ", Main Street";
address = a
address + ", Buffalo";

An alternative
A e approach is to use the StrringBuilder 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 SttringBuilder class.


The c

C
Concatenatio
on by Using tthe 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.ToStringg();

V
Validating Strings
When acquiring input from
W m the user inte erface of an application, daata is often pro
ovided as strin
ngs that you
n
need to validaate and then convert
c into a format that yyour applicatiion logic expe ects. For exam
mple, a text
b control in
box n a WPF appliccation will retturn its conten
nts as a string er specified an integer
g, even if a use
v
value. It is imp
portant that yyou validate suuch input so tthat you minim mize the risk of
o errors, suchh as
I
InvalidCastEx xceptions.

Regular expre
R essions provide a mechanism that enable
es you to valid
date input. Th
he .NET Frameework
p
provides System.Text.RegularExprressions name
the S espace that in
ncludes the Reegex 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# Prrogram
mming LLanguage Con
nstructss

When develop
W ping an appliccation, you will often need to execute loogic based on a condition, o
or to
r
repeatedly execute a sectioon of logic until a conditionn is met. You may
m also want to store a co ollection of
r
related data in
n a single variiable. Visual C
C# provides a number of coonstructs than
n enable you mmodel
c
complex behaavior in your aapplications.

IIn this lesson, you will learn


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 byy using
n
namespaces, a how to use some of th
and he debugging features that Visual Studioo provides.

L
Lesson Ob
bjectives
A
After completting this lesson, you will be able to:

Use conditional statem


ments.
Use iterattion statemen
nts.

Create an
nd use arrays.

Describe the purpose o


of namespace
es.
Describe some of the ffeatures provided by the Viisual Studio debugger.
1-26 Review of Visual C# Syntaxx

Im
mplementing Condiitional Log
gic

Appplication logiic often needss to run differrent sections o


of code depennding on the sstate of data iin the
ap
pplication. For example, if a user requestss to close a file, they may b
be asked whetther they wish h to save
any changes. If tthey do, the aapplication must execute co ode to save th
he file. If they dont, the ap
pplication
log
gic can simplyy close the file
e. Visual C# usses conditionaal statements to determine which code ssection to
run
n.

The primary connditional 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
Statementss
Yo
ou use if statements to test the truth of a statement. Iff the statemennt is true, the
e block of code
asssociated with the if statement is execute ement is false, control passes over the block.
ed, if the state

The following co
ode shows ho
ow to use an if statement to
o determine iff a string con
ntains the valu
ue
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 associiated else clau
uses. The else
e block executtes when the if statement is false.

The following co
ode example shows how to
o use an if elsse statement tto execute cod
de when a condition is
fallse.

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 if the value of response is "connection_failed".
break;
case "connection_success":
// Block of code executes if the value of response is "connection_success".
break;
case "connection_error":
// Block of code executes if the value of response is "connection_error".
break;
default:
// Block executes if none of the above conditions are met.
break;
}

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 Logiic

IIteration provvides a convennient way to execute


e a blocck of code mu
ultiple times. FFor example, iiterating over
a collection off items in an aarray or just e
executing a function multip
ple times. Visual C# providees a number
o standard co
of onstructs know wn as loops that you can u use to implemment iteration logic.

F Loops
For
The for loop e
T executes a blo
ock of code re ed expression evaluates to ffalse. You can
epeatedly unttil the specifie
d
define a for lo
oop as followss.
f ([initializerrs]; [expression]; [iterators])
for

[body]
}

When using a for loop, you


W e a value as a counter. On each loop, yo
u first initialize ou check that tthe value of
t counter iss within the raange to execute the for loo
the 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 iiterator.

F Each Lo
For oops
While a for lo
W oop is easy to use, it can be ample, when itterating over a collection
e tricky to get right. For exa
o an array, yo
or ou have to knnow how many elements th he collection or
o array contains. In many ccases this is
s
straightforwarrd, but somettimes it can be
e easy to get wrong.
w Thereffore, it is sometimes betterr 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 aand Using
g Arrays

An array is a sset of objects that are grouped togetherr and manage


A ed as a unit. Yo
ou can think o
of an array as
a sequence off elements, alll of which are the same typ pe. You can buuild simple arrays that have
e one
d
dimension (a list), two dime
ensions (a tab
ble), three dim ube), and so on. Arrays in Visual C# have
mensions (a cu
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 tthe 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 dimensionss in the array.
Arrays of a pa
A articular type can
c only hold d elements of that type. If yyou need to mmanipulate a se
et of unlike
o
objects or valu
ue types, conssider using on
ne of the colle
ection types th hat are define
ed in the
S
System.Colle ections namesspace.

C
Creating Arrrays
When you declare an arrayy, you specify the type of da
W ata that it con
ntains and a n
name for the aarray.
D
Declaring an array
a brings the array into scope, but do
oes not actually allocate anyy memory forr it. The CLR
p
physically creaates the arrayy when you usse the new keeyword. At thiss point, you should specify the size of
t array.
the

T following list describess how to creatte single-dime


The ensional, multtidimensional,, and jagged aarrays:
Single-dim
mensional arrrays. To declarre a single-dimmensional arrray, you speciffy the type of elements in
the array and use brackets, [] to indicate that a vaariable is an array. Later, yo
ou specify the size of the
array wheen you allocatte memory for the array byy using the ne ew keyword. T The size of an array can be
any integ
ger expression
n. The followinng 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 arrayys. An array caan have more


e than one dim mension. The number of dimensions
correspon
nds to the nummber of indexxes that are ussed to identifyy an individuaal 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 Namesspaces

The Microsoftt .NET Framew


T work consists o
of many namespaces that organize
o its cllasses into log
gically related
h
hierarchies. Yo
ou can use naamespaces in yyour own app
plications to similarly organnize your classses into
h
hierarchies.
Namespaces function
N f as bo
oth an internaal system for oorganizing your applicationn and as an exxternal way to
o
a
avoid name clashes betwee en your code and other applications. Eacch namespace e contains typ
pes that you
c use in you
can ur program, such as classess, structures, e
enumerations,, delegates, an
nd interfaces. Because
d
different classses can have the
t same nam me, you use naamespaces to differentiate the
t same nam med class into
t
two different hierarchies to
o avoid interoperability issuues.

.
.NET Frame
ework Classs Library Na
amespacess
The most imp
T portant namesspace in the .NNET Framewo ork is the Syste
em namespacce, which contains the
c
classes that m
most applicatio
ons use to inte
eract with the
e operating syystem. 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 ttable:

Namespace Definittion

System.Win
ndows Provides the classess that are usefful for building
g WPF applica
ations.

System.IO Provides classes for reading and w


writing data tto files.

System.Data
a Provides classes for data access.

System.Web
b Provides classes that are useful fo
or building we
eb application
ns.

U
User-Defin ed Namesp
paces
User-defined namespaces are
U a namespacces defined in your code. It is good practtice to define all your
c
classes in nam
mespaces. The Visual Studioo environmentt follows this recommendation by using the name of
y
your project aas the top-level namespace
e in a project.

The following code example shows how to define a n


T namespace witth the name F
FourthCoffee
e.Console,
w
which ns the Program class.
contain
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 applicaation developpment. You may notice erroors as you writte code, but
s
some errors, e
especially logiic errors, may only occur in
n circumstance
es that you do
o not predict. Users may
r
report these eerrors to you aand you will have
h to correcct them.
Visual Studio 2012 provide
V es several tools to help you debug code. You might usse these while e you develop
p
c
code, during a test phase, o
or after the ap
pplication hass been release
ed. You will usse the tools in the same
w regardlesss of the circumstances.
way

You can run an


Y a application n with or witho
out debugging enabled. WWhen 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 shortccuts.

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
correspondingg keyboard sh hortcuts.

Menu item To
oolbar button
n Key
yboard shortccut De
escription

Start Debug
gging Sttart/continue F5 Thhis 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
ap ou are in
brreak mode.

Break All Brreak all Ctrl+Alt+Break Thhis button cau uses


appplication processing to
paause and breaak mode to be
e
enntered. The bu utton is
avvailable when an
appplication is ru
unning.

Stop Debug
gging Sttop Sh
hift+F5 Th
his button stops
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.

Step Into Step into F11 This button is used for


stepping into method calls.

Step Over Step over F10 This button is used for


stepping over method calls.

Step Out Step out Shift+F11 This button is used for


executing the remaining
code in the method and
returning to the next
statement in the calling
method.

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 Classs Enrollme
ent Appliccation Lab
b

I this demon
In nstration, you will learn abo
out the tasks tthat you will p
perform in the
e lab for this module.
m
1-38 Review of Visual C# Syntaxx

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

Sccenario
Yo
ou are a Visual C# develope er working forr a software development ccompany thatt is writing app
plications
of Fine Arts, an elementary school for giffted children.
forr The School o
The school adm ministrators req
quire an appliication that th
hey can use to
o enroll studennts in a class. The
ap
pplication musst enable an aadministrator tto 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 at implements the businesss logic for the
e the code tha e application.

Note: Durring the labs ffor the first tw


wo modules in n this course, you
y will write code for this
cla
ass enrollmentt application.
Wh hen The Scho ool of Fine Arts ask you to extend
e the application funcctionality, you realize that you
y
will need to testt proof of conncept and obtain client feed dback before writing the fin nal application,
so in the lab forr Module 3, yoou will begin d developing a prototype ap pplication and continue with
thiis until then end of Module e 8.
In the lab for Module 9, afterr gaining signoff for the final application n, you will devvelop the userr
intterface for the
e production version
v of thee application, w
which you willl work on for the remainde er
of the course.

Ob
bjectives
Aftter completing this lab, you
u will be able to:

Write Visuaal C# code tha


at implementss the logic neccessary to editt the details o
of a student.

Write Visuaal C# code tha


at implementss the logic neccessary to add
d new studentts.
Write Visuaal C# code tha
at implementss the logic neccessary to rem
move studentss from a class.

Perform sim
mple data tran
nsformations for
f displaying information.

Esttimated Time:: 45 minutes

Virtual Macchines: 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. Start the MSL-TMG1 virtual machine if it is not already running.

2. Start the 20483A-SEA-DEV11-01 virtual machine and log on as Student with the password
Pa$$w0rd.
3. Start Visual Studio and from the E:\Labfiles\Starter\Exercise 1 folder, and then open the School.sln
solution.

4. In the code for the MainWindow.xaml.cs window, find the studentsList_KeyDown method.
5. 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. 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.
2. Populate the following text boxes on the form with the corresponding properties of the current
student:

a. firstName
b. lastName

c. dateOfBirth

3. 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. At the end of the case Key.Enter block, display the StudentForm window by using the ShowDialog
method of the form.

2. 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. Build the solution and resolve any compilation errors.

2. 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. Change the last name of Kevin Liu to Cook and verify that the updated data is copied back to the
students list.

5. Verify that the Save Changes button is now enabled.

6. Close the application.

X Task 5: Use the Visual Studio Debugger to step through the code.
1. In Visual Studio, in the studentsList_KeyDown method, insert a breakpoint at the statement that sets
the Title property of the StudentForm.

2. Debug the application.

3. Edit the row for George Li.

4. When Visual Studio enters break mode, open the Watch 1 window and populate the grid with a row
for each of the following:

o sf.Title

o sf.firstName.Text
Programming in Visual C# 1-43

o sf.lastName.Text

o 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. Step over the next code statement four times.


6. 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. In the Watch 1 window, change the value George to Dominik.

8. In the Immediate Window, enter sf.lastName.Text and verify that the value "Li" is displayed.

9. 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 Value

First Name Dominik

Last Name Dubicki

Date of Birth 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. In Visual Studio, from the E:\Labfiles\Starter\Exercise 2 folder, open the School.sln solution.

2. In the code for the MainWindow.xaml.cs window, locate the studentsList_KeyDown method.
3. In this method, add a statement to detect whether the user has pressed Insert.

X Task 2: Initialize the student form


1. If the user has pressed Insert, create a new instance of the StudentForm window.

2. 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. Display the StudentForm window by using the ShowDialog method.

2. 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. Add the new student object to the list of students displayed on the form.

3. 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. Build the solution and resolve any compilation errors.

2. Run the application and verify that it displays the initial list of students.

3. Display the new student window and verify that it contains no data.

4. 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. Verify that the Save Changes button is now enabled.

6. Close the application.


7. 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. In Visual Studio, from the E:\Labfiles\Starter\Exercise 3 folder, open the School.sln solution.

2. In the code for the MainWindow.xaml.cs window, find the studentsList_KeyDown method.

3. 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. Build the solution and resolve any compilation errors.

2. Run the application and verify that it displays the initial list of students.

3. Delete the student Jon Orton from class 4B.

4. Verify that the prompt window appears, the student is removed from the list, and that the Save
Changes button is enabled.
5. Close the application.

6. 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. In Visual Studio, open the School.sln solution from the E:\Labfiles\Starter\Exercise 4 folder.
2. Build the solution.

3. View the MainWindow.xaml code.

4. 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. In the code for the MainWindow.xaml.cs window, find the Convert method in the AgeConverter
class.

2. In this method, add code that checks that the value parameter of the method contains data. If it does
not, return an empty string.

3. If the value parameter is not null, convert the value parameter to a DateTime object.

4. 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. Build the solution and resolve any compilation errors.

2. 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. Add yourself as a student and verify that your age displays correctly in the student list.

4. Close the application.

5. 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# Syntaxx

Modu
ule Reviiew and
d Takea
aways

M
Module Revie
ew
In this module, yyou learned about
a some off the core features provided by the .NET
T Framework aand
Miicrosoft 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 Frammework appliccations.

Test Your Know


wledge

Q
Question

W
What Visual Studio templaate would you
u use to creatte a .dll?

S
Select the corrrect answer.

Conso
ole application
n

Windo
ows Forms application

WPF aapplication

Class library

WCF SService applica


ation

Ve
erify the correcctness of the statement by placing a maark in the column to the rig
ght.

S
Statement Answer

When using the as operato


W or to perform a cast, if the cast
c is not posssible, the
a operator will
as w return a -11. Is this statem
ment true or ffalse?

Test Your Know


wledge

Q
Question

G
Given the follo
owing for loo
op statement,, what is the value
v of the ccount variable once the
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.

11

2-1

Module 2
Creating Methods, Handling Exceptions, and Monitoring
Applications
Contents:
Module Overview 2-2

Lesson 1: Creating and Invoking Methods 2-3


Lesson 2: Creating Overloaded Methods and Using Optional and Output
Parameters 2-13

Lesson 3: Handling Exceptions 2-20

Lesson 4: Monitoring Applications 2-27

Lab: Extending the Class Enrollment Application Functionality 2-36

Module Review and Takeaways 2-44


2-2 Creating Methods, Handling Exceptions, and Moonitoring Applications

Modu
ule Ove
erview

Ap of functionalitty that perform specific fun


pplications oftten consist of logical units o nctions, such aas
pro
oviding access to data or trriggering som me logical proccessing. Visuaal C# is an object-orientated d language
and uses the concept of meth hods to encap psulate logical units of funcctionality. A method
m can bee as simple
or as complex as you like, andd therefore it is important to consider w what happens to the state o of your
ap
pplication wheen an exceptio on occurs in a method.

In this module, yyou will learn how to creatte and use me


ethods and ho ow to handle exceptions.
e Yo
ou will also
leaarn how to use
e logging and d tracing to re
ecord the detaails of any excceptions that o
occur.

Ob
bjectives
Aftter completing this module
e, you will be able to:

Create and invoke metho


ods.
Create overrloaded metho
ods and use o
optional param
meters.

Handle exce
eptions.

Monitor applications by using logging


g, tracing, and
d profiling.
Programmingg in Visual C# 2-3
3

Lesson 1
Creatting an
nd Invoking M
Methodss

A key part of developing any applicationn is dividing the solution in


nto logical com
mponents. In object-
o
oriented languages such ass Visual C#, a method is a uunit of code thhat performs a discrete pie
ece of work.

I this lesson, you will learn


In n how to creatte and invoke
e methods.

L
Lesson Ob
bjectives
A
After completting 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 Moonitoring 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 youu to encapsulaate operationss that protect data that is stored
s inside a type.

Typically, any ap
pplication thaat you develop
p by using thee Microsoft .N
NET Frameworrk and Visual C# C will
have many methods, each wiith a specific p purpose. Some methods arre fundamenta al to the operration of an
ap
pplication. For example, all VVisual C# desktop applications must havve a method ccalled Main th hat defines
the
e entry point for the appliccation. When tthe user runs a Visual C# application, the
e common lan nguage
run
ntime (CLR) exxecutes the Main
M method for that application.

Me e designed for internal use by a type, and as such are hidden from other types. P
ethods can be Public
meethods may be designed too enable other types to request that an o ms an action, and are
object perform
exposed outside
e of the type.

The .NET Frame ework itself is built from classes that expo
ose methods tthat you can ccall from yourr
ap
pplications to iinteract with the
t user and thet computerr.
Programmingg in Visual C# 2-5
5

C
Creating M
Methods

A method com
mprises of two
o elements:

1
1. The meth
hod specificatiion.

2
2. The meth
hod body.

The method sspecification defines


T d the naame of the me ethod, the parrameters that the method canc take, the
r
return type off 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 signatture. The definnition of the rreturn 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 ass a variable naame. A metho
od must start with
w a letter
o an undersccore and can o
or only contain letters, undersscores, and nuumeric characters. Visual C#
# is case
s
sensitive, so a class can con
ntain two metthods that havve 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 arre recommend


The ded best pracctices when yo
ou choose the
e name of a m
method:

Use verbss or verb phraases to name m


methods. Thiss helps other developers
d to
o understand tthe structure
of your co
ode.

Use Pascaal case. Do no


ot start public method names with an un
nderscore or a lowercase lettter.

I
Implement
ting a Meth
hod Body
The body of a method is a block of code
T emented by using any of th
e that is imple he available Visual C#
p
programming g constructs. T nclosed in braces.
The body is en

You can defin


Y ne variables inside a method d body, in whhich case they exist only wh
hile the metho
od is running.
W
When the meethod finishes,, it is no longe
er in scope.

The following code example shows the b


T body for the S
StopService mmethod, which contains a vvariable
n
named isServ
viceRunning. The isService eRunning varriable is only aavailable insid
de the StopSe
ervice code
b
block. If you ttry to refer to the isService
eRunning variiable outside the scope of tthe method, tthe compiler
w raise a compile error w
will with the messaage The name e 'isServiceRu
unning' doess 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 Moonitoring Applications

In
nvoking M
Methods

Yoou call a method to run the code in that method from


m part of your application. Y
You do not ne eed to
unnderstand howw the code in a method wo orks. You may not even havve access to th
he code, if it iss in a class
in an assembly for
f which you u do not have the source, su
uch as the .NEET Frameworkk class library.
o call a method
To d, you specifyy the method name and pro
ovide any arg
guments that ccorrespond to
o the
meethod 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 methods signature.
ments of the m

Inv
voking a Metthod Passing
g Parameterss
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 tthe method re
eturns a value
e, you specify how to handlle this value, ttypically by asssigning it to a variable
of the same type, in your calling code.

ode example shows how to


The following co o capture the return value of
o the GetSerrviceName 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: FFor more inforrmation about methods, se ee the Method
ds (C#
Pro
ogramming G
Guide) page att http://go.miicrosoft.com/ffwlink/?LinkID
D=267774.
Programming in Visual C# 2-9
2-10 Creatingg Methods, Handling Exceptions, and M
Monitoring Applicatiions

Debugging
g Methodss

Whhen you are ddebugging your application n, you can step through cod de one statem
ment at a time e. This is an
exttremely usefu
ul feature becaause it enable
es you to test tthe logic thatt your applicattion uses one step at a
tim
me.
Vissual Studio prrovides a num
mber of debug gging tools thaat enable youu to step throuugh code in exactly the
waay you want to o. For example, you can ste
ep through ea ach line in eacch method thaat is executed, or you
can ignore the sstatements insside a methodd that you knoow are workin ng correctly. Y
You can also sstep over
code completelyy, preventing some statements from exe ecuting.

Wh hen debuggin ng methods, yyou can use thhe following tthree debug fe
eatures to con
ntrol whetherr you step
ovver, step into, o
or step out off a method:
The Step Into feature exeecutes the statement at the e current execcution position
n. If the statemment is a
method call, the current execution po osition will mo
ove to the codde inside the method.
m Afterr you have
stepped intto a method you
y can contin nue executing g statements inside the metthod, 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 thiss, the
application will enter bre
eak mode as ssoon as it startts.

The Step Ovver feature exxecutes the sta


atement at thhe current execution positio on. However, tthis feature
does not steep into code inside a methhod. 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 iff the code
for the metthod or propeerty contains a breakpoint. If this is the caase, execution
n will continue e up to the
breakpoint..

The Step Out feature enaables you to eexecute the re


emaining code e in a method
d. Execution will
w continue
to the state
ement that callled the methood, and then pause at that point.

Additionaal Reading: FFor more inforrmation about stepping thrrough code, see
s the Code
Ste
epping Overview page at h
http://go.microosoft.com/fwllink/?LinkID=267783.
Programming in
i Visual C# 2-11
1

D
Demonstr
ration: Crreating, In
nvoking, and Debug
gging Metthods

I this demon
In nstration, you will create a m
method, invokke the method
d, and then debug the metthod.

D
Demonstra
ation Steps
1
1. Start the MSL-TMG1 viirtual machine
e if it is not already running
g.

2
2. Start the 20483A-SEA-DEV11-02 virrtual machine..

3
3. Log on to
o Windows 8 as
a Student with the passwo
ord Pa$$w0rrd.

Note: Iff necessary, click Switch Usser to display the list of use
ers.

4
4. Switch to the Windowss 8 Start wind
dow.

5
5. Click Visu
ual Studio 201
12.
6
6. In Visual Studio, on the
e File menu, p n, and then click Project/Solution.
point to Open

7
7. In the Oppen Project dia wse to the E:\\Democode\Starter\FourthC
alog box, brow Coffee.Metho
odTestHarnesss
folder, click FourthCofffee.MethodTeestHarness.sln, and then clicck Open.

8
8. In Visual Studio, on the
e View menu,, click Task Liist.

9
9. In the Tassk List windo
ow, in the Cate
egories list, click Commen
nts.

1 Double-cclick the TODO


10. O: 01: Define the
t Initialize m
method. task.

1 In the cod
11. de editor, click in the blankk 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 Tassk List window


12. w, double-click the TODO: 0
02: Invoke the
e Initialize me
ethod. task.

1 In the cod
13. de editor, click in the blankk 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
Creatting Ov
verload
ded Metthods a
and Using Opttional a
and
Outp
put Paraameterrs

You have seen


Y n that you can n define a me
ethod that acccepts a fixed number
n of parrameters. How
wever,
s
sometimes yo
ou might write e one generic method that requires diffeerent sets of pparameters deepending on
t context in
the n which it is ussed. You can ccreate overloaaded methodss with unique e signatures to
o support this
n
need. In otherr scenarios, yo
ou may want tto define a method that haas a fixed num mber of parammeters, but
e
enables pplication to specify arguments for only the paramete
an ap ers that it need
ds. You can doo this by
d
defining a meethod that takkes optional parameters
p and then using named argum ments to satisffy the
p
parameters byy name.

IIn this lesson, you will learn


n how to creatte overloaded
d methods, de
efine and use optional para
ameters,
n
named argum
ments, and outtput paramete ers.

L
Lesson Ob
bjectives
A
After completting this lesson, you will be able to:
Create an
n overloaded method.

Use optio
onal paramete
ers.

Use name
ed argumentss.

Define ou
utput parametters.
2-14 Creatingg Methods, Handling Exceptions, and M
Monitoring Applicatiions

Crreating Ov
verloaded
d Methodss

Wh hen you defin ne a method, yyou might reaalize that it re


equires differe
ent sets of info
ormation in diifferent
cirrcumstances. Y You can define overloaded methods to ccreate multiplle methods with the same
fun nctionality thaat accept diffe
erent parametters dependin ng on the context in which they are calle ed.
Ovverloaded metthods have thhe same name e as each othe
er to emphasizze their comm mon intent. Hoowever,
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 inncludes its nam


me and its parrameter list. T
The return typ
pe is not part o
of the
sig
gnature. There nnot define ovverloaded methods that difffer only in their return type.
efore, you can

The following co
ode example shows three vversions 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)
{
...
}

Whhen you invokke the StopSeervice methodd, you have choice of which overloaded version you u use. You
sim t relevant aarguments to satisfy a particular overload
mply provide the d, and then th
he compiler w
works out
wh o invoke based on the argu
hich version to 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 ovverloaded me
B ethods, you caan implementt different verssions of a metthod that take
e different
p
parameters. W
When you build an applicattion that uses overloaded m methods, the compiler
c deteermines which
h
s
specific instan
nce of each method it shouuld use to satissfy each meth
hod call.
There are other languages and technolo
T ogies that developers can use for building applications and
c
components tthat do not fo ollow these rules. A key featture of Visual C# is the abillity to interop
perate with
a
applications aand components that are written
w by usin
ng other techn nologies. One of the princip pal
t
technologies tthat Windowss uses is the CComponent Object Model ((COM). COM d does not supp port
o
overloaded m
methods, but in nstead uses methods
m that ccan take optioonal paramete ers. To make it i easier to
i
incorporate C
COM libraries aand compone on, Visual C# also supports optional
ents into a Vissual C# solutio
p
parameters.

Optional paraameters are also useful in o


O other situation de a compactt and simple solution when
ns. They provid
i is not possib
it ble to use ove
erloading becaause the typees of the param
meters do nott vary sufficien
ntly to enable
e
t compiler tto distinguish
the h between impplementationss.

The following code example shows how to define a m


T method that accepts one mandatory paraameter and
t
two optional parameters.

D
Defining aM
Method with Optional
O Parrameters
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 ptional parameters.
any op
The following code example shows a me
T ethod definitio
on that uses o
optional param
meters that th
hrows a
c
compile errorr.
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 Arrguments

Traditionally, when calling a method, the


T e order and p
position of arg
guments in thee method calll 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, yyou receive a compile error.
IIn Visual C#, yyou can speciffy parameterss by name, and therefore su
upply argume
ents in a seque
ence that
d
differs from thhat defined in
n the method signature. To use named arguments, yo ou supply the parameter
n
name and corrresponding 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 serviiceName paraameter.

U
Using Named
d Argumentss
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 ue. However, if you omit an
eir default valu ny mandatoryy parameters,
y
your code will not compile.

You can mix p


Y positional and
d named arguments. Howevver, you mustt specify all po
ositional arguments before
a named arrguments.
any

onal Reading: For more infformation abo


Additio out using nam
med argumentts, see the Named
and Optional Arguments (C
a C# Programm ming Guide) paage at
h
http://go.micr
rosoft.com/fw
wlink/?LinkID=
=267784.
2-18 Creatingg Methods, Handling Exceptions, and M
Monitoring Applicatiions

Crreating M
Methods th
hat Use Ou
utput Paraameters

A method
m can pass
p a value back to the cod de that calls itt by using a re
eturn statemeent. If you nee
ed to
retturn more thaan a single value to the calling code, you u can use outp put parameters to return addditional
data from the m method. When n you add an output param meter to a metthod, the metthod body is e expected to
asssign a value to
o that parame eter. When the method com mpletes, the vvalue of the output parame eter is
asssigned to a vaariable that is specified as the correspond ding argumen nt in the meth
hod call.

To
o define an ou
utput parametter, you prefixx the paramete
er in the meth
hod signature
e with the outt keyword.

The following co
ode example shows how to
o define a metthod that use
es output para
ameters

De
efining Outpu
ut Parameterrs
b
bool IsServicceOnline(str
ring service
eName, out st
tring status
sMessage)
{
var isOnlline = Fourt
thCoffeeServ
vices.GetStat
tus(serviceN
Name);
if (isOnlline)
{
statu
usMessage = "Services is currently running.";
}
else
{
statu
usMessage = "Services is currently stopped.";
}
return issOnline;
}

A method
m can have
h as many output parammeters as requ
uired. When you declare an n output parammeter, you
muust assign a vaalue to the pa
arameter befo
ore the methood 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 aargument with
h the out keyyword. If you aattempt to spe
ecify an argum
ment that is
no
ot a variable or if you omit tthe out keyword, your codde will not com
mpile.

The following co
ode example shows how to
o invoke a me
ethod that acccepts 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 Creatingg Methods, Handling Exceptions, and M
Monitoring Applicatiions

Lesson 3
Handlling Excception
ns

Excception handling is an imp


portant concep
pt to ensure a good user exxperience and
d to limit dataa loss.
Ap
pplications sho
ould be designed with exceeption handlin
ng in mind.

In this lesson, yo
ou will learn h
how to implem
ment effective ur applications and how
e exception haandling in you
you can use excceptions in your methods to or condition to the code th
o elegantly indicate an erro hat calls
your methods.

Le
esson Obje
ectives
Aftter 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 finallyy block to run


n code after an
n exception.

Throw an exxception.
Programming in
i Visual C# 2-21
1

W
What Is an
n Exceptio
on?

Many things ccan go wrong


M g as an applicaation runs. Some errors may occur due to flaws in the e application
l
logic, but others may be du ue to conditioons outside th
he control of your
y applicatioon. For examp ple, your
a
application caannot guaranttee that a file exists on the file system orr that a requirred database is
i online.
W
When you design an appliccation, you sh hould considerr how to ensu ure that your aapplication caan recover
g
gracefully whe en such probllems arise. It is common prractice to simp ply check the return values from
m
methods to ensure that the ey have execuuted correctly,, however, this methodolog gy is not alwayys sufficient
t handle all e
to errors that maay occur because:

Not all methods


m return
n a value.

You need
d to know whyy the method call has failed
d, not just that it has failed..
Unexpectted errors such as running o
out of memory cannot be handled in this way.

Traditionally, applications u
T used the conccept of a global error objecct. When a pie
ece of code caaused an
e
error, it would
d set the data in this objectt to indicate th he error and then return to the caller. It
he cause of th
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 overcomme these issue es. An exceptioon is an indicaation of an
e
error or excep
ptional condittion. A method
d can throw ana exception w when it detectts that something
u
unexpected h
has happened,, for example,, the application tries to op
pen a file that does not exisst.

When a method throws an exception, th


W he calling code must be pre epared to dete ect and handle this
e
exception. If tthe calling cod
de does not ddetect the exceeption, the co
ode is abortedd and the exceeption is
a
automatically propagated tot the code thhat invoked th he calling cod
de. This processs continues until
u a section
o code takes responsibilityy for handling
of g the exception. Execution ccontinues in this section of code after
t exception
the n-handling log gic has compleeted. If no cod
de handles thhe exception, then
t the proccess will
t
terminate andd display a me essage to the user.

T Excepttion Type
The
When an exce
W eption occurs,, it is useful to
o include inforrmation about the original cause so thatt the method
t
that handles tthe exception can take the appropriate ccorrective actiion. In the .NEET Frameworkk, 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 Namespace Description

Exception System Represents any exception


that is raised during the
execution of an
application.

SystemException System Represents all exceptions


raised by the CLR. The
SystemException class is
the base class for all the
exception classes in the
System namespace.

ApplicationException System Represents all non-fatal


exceptions raised by
applications and not the
CLR.

NullReferenceException System Represents an exception


that is caused when
trying to use an object
that is null.

FileNotFoundException System.IO Represents an exception


caused when a file does
not exist.

SerializationException System.Runtime.Serialization Represents an exception


that occurs during the
serialization or
deserialization process.

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/Caatch Block
k

The try/catch block is the key


T k programm ming constructt that enabless you to imple
ement Structuured
E
Exception Han wrap code thatt may fail and cause an exception in a
ndling (SEH) in your applicaations. You w
t block, and add one or more
try m ocks to handle any exceptions that may occur.
catch blo
T following code example shows the ssyntax for deffining a try/catch block.
The

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 Visuaal C# statemen
T nts, and can
i
invoke metho ods in other ob o these statements cause an
bjects. If any of a exception to be thrown,, execution
p
passes to the appropriate ccatch block. The catch speccification for e each block dettermines whicch exceptions
i will catch an
it nd the variablle, if any, in w
which to store the exception n. You can spe
ecify catch blo
ocks for
d
different typees of exceptionns. It is good ppractice to incclude a catch block for the general Exceeption type att
t end of the
the e catch blockss to catch all eexceptions thaat have not be een handled otherwise.
o

IIn the followin


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 bloock runs. If anyy other type o
of exception occurs,
o the cod
de in the
c
catch block fo
or the Exceptiion 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 Fiinally Blocck

SSome method ds may contain critical code e that must allways be run, even if an unhandled exception occurs.
F example, a method maay need to enssure that it clo
For oses a file thatt 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 specifiies code that must be
p
performed whhen the block finishes, irresspective of wh
hether any excceptions, hand dled or unhanndled, occur.
I an exception is caught an
If nd handled, thhe exception handler in thee catch block will run beforre 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 aare
u
unhandled, buut the finally block
b will always run.
T following code example shows how to implemen
The nt a try/catch//finally block.

T
Try/Catch/Fi nally Blocks
try
{
}
catch (NulllReferenceEx
xception ex)
{
// Catc
ch all NullR
ReferenceException excep
ptions.
}
catch (Exceeption ex)
{
// Catc
ch all other
r exceptions.
}
finally
{
// Code that always
s runs.
}

Additioonal Reading: For more infformation abo out try/catch//finally blocks,, see the try-
ccatch-finally ((C# Reference
e) page at http oft.com/fwlinkk/?LinkID=267788.
p://go.microso
2-26 Creatingg Methods, Handling Exceptions, and M
Monitoring Applicatiions

Th
hrowing E
Exceptionss

Yo
ou can create aan instance off an exceptionn class in yourr code and throw the excepption to indicaate that an
excception has o
occurred. Wheen you throw an a exception, execution of the current b block of code terminates
and the CLR passses control to
o the first available exceptioon handler th
hat catches the
e exception.
o throw an excception, you use
To u the throw
w keyword and
d specify the e
exception object to throw.

The following co
ode example shows how to
o create an insstance of the NullReferencceException 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 strattegy is for a m
method or blo
ock of code too catch any exceptions and attempt to ha andle them.
If tthe catch blocck for an exce eption cannot resolve the error, it can retthrow the excception 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 catcch 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 Appliccations

When you devvelop real-wo


W orld applicatio
ons, writing co
ode is just one
e part of the process.
p You are
a likely to
s
spend a signifficant amountt of time resolving bugs, tro
oubleshootingg problems, aand optimizingg 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 morre effectively.
to

IIn this lesson, you will learn


n how to use a range of too
ols and techniiques to moniitor and troub
bleshoot your
a
applications.

L
Lesson Ob
bjectives
A
After completting this lesson, you will be able to:
Use loggiing and tracin
ng in your cod
de.

Use application profilin


ng in Visual Sttudio.

Use perfo
ormance coun
nters to monittor the perform
mance of you
ur application..
2-28 Creatingg Methods, Handling Exceptions, and M
Monitoring Applicatiions

Ussing Logg
ging and T
Tracing

When you implement logg


Logging and traacing are similar, but distincct, concepts. W ging in your ap
pplication,
you add code thhat writes info
ormation to a destination lo og, such as a ttext file or the
e Windows evvent log.
Logging enables you to provvide users and administrato ors with more information aabout what yo our code is
do mple, if your application han
oing. For exam ndles an exception, you miight write the details to the e Windows
ent log to enaable the user or a system administrator to
eve t resolve anyy underlying p problems.

Byy contrast, devvelopers use tracing to mon nitor the execution of an ap pplication. Wh hen you imple ement
tra
acing, you add d code that wwrites message es to a trace lisstener, which in turn directts your outputt to a
speecified target. By default, yyour trace messsages are sho own in the Ou utput window w in Visual Stu
udio. You
typpically use tracing to providde information about variable values or condition results, to help you y find out
whhy your appliccation behave es in a particullar way. You can
c also use trracing techniq ques to interru
upt the
exeecution of an application in n response to conditions th hat you define e.

W
Writing to th
he Window
ws Event Log
g
Wrriting to the W
Windows even nt log is one o
of the more coommon logging requireme ents you mighht
encounter. The System.Diag gnostics.Even ntLog class proovides various static metho ods that you ccan use to
wrrite to the Win
ndows event log. In particular, the EventtLog.WriteEn ntry method includes severral
ovverloads that yyou can use to
o log various ccombinationss of informatioon. To write to
o the Windowws event
logg, you need too 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 o. In most cases you will
ant to write to
write to the
e Application n log.

The event source. This ide


entifies where
e the event caame from, andd is typically th
he name of yo
our
application. When you crreate an evennt source, you associate it w
with an event llog.

The messag
ge. This is the text that you want to add tto the log.

Yo
ou can also use
e the WriteEn
ntry method to specify a caategory, an evvent ID, and aan event severrity if
req
quired.

Additiona al Reading: WWriting to the Windows eve ent log requirres a high leveel of
pe
ermissions. If your
y applicatio
on does not run with sufficcient permissio
ons, it will thro
ow a
Se
ecurityExcepttion when you u attempt to create
c an event source or w write to the evvent 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 long-
running 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 Creatingg Methods, Handling Exceptions, and M
Monitoring Applicatiions

Ussing Application Prrofiling

Wh hen you deve elop applicatio


ons, making your code worrk without bug gs is only partt of the challe
enge. You
alsso have to enssure that yourr code runs effficiently. You need to revie
ew how long yyour code takkes to
acccomplish taskks and whethe er it uses excessive processo or, memory, ddisk, or network resources.
Vissual Studio inccludes a range of tools, colllectively know
wn as the Visu ofiling Tools, that can
ual Studio Pro
heelp you to anaalyze the perfoormance 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 performaance analysis ttakes place wiithin a perform
mance
session. Youu can create and
a run a perfformance sesssion by launch hing the Perfoormance Wiza ard from
the Analyze e menu in Vissual Studio. W
When the perfoormance sessiion is running g, you run youur
application as you usually would. While your appliccation is runniing, you typically aim to use
functionalitty that you susspect may be causing perfoormance issue es.

2. Analyze the e profiling repo


ort. When you ng your appliccation, Visual Studio displays the
u finish runnin
profiling report. This includes a range of informatio
on that can prrovide insightss into the perfformance
of your appplication. For eexample, you can:

o See wh
hich functions consume the
e most CPU tim
me.
o View a timeline that shows what yyour application was doing
g when.

o View w
warnings and ssuggestions on how to imp
prove your cod
de.

3. Revise yourr code and rep peat the analyysis. When your analysis is complete,
c you
u should makee changes
to your cod
de to fix any isssues that you
u identified. Yo
ou can then run a new perfformance sesssion 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.
Peerformance sessions work by b sampling. W When you creaate a performance session, you can choo ose whether
you want to sam mple CPU use,, .NET memorry allocation, concurrency
c information fo
or multi-threaaded
ap
pplications, or whether you want to use instrumentatio on to collect d
detailed timin
ng informationn about
eveery function ccall. In most caases you will want
w to start b
by using CPU sampling, wh hich is the deffault
opption. CPU sammpling uses sttatistical pollinng to determine which funcctions are usin ng the most CPU
C time.
This provides ann insight into the performance of your application, without consum ming many ressources and
slo
owing down yyour 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 Creatingg Methods, Handling Exceptions, and M
Monitoring Applicatiions

Ussing Perfo
ormance C
Counters

Pe
erformance coounters are sysstem tools thaat collect information on hoow resources are used. View wing
pe
erformance coounters can prrovide additioonal insights innto what yourr application is doing, and ccan help
you to troublesh
hoot performance problem ms. Performance counters faall into three main groups:
Counters th
hat are provideed by the operrating system and the undeerlying hardwa are platform. T
This group
includes counters that yoou can use to measure proccessor use, ph hysical memorry use, disk usse, and
network usee. The details of the counte will vary accorrding to the hardware that the
ers available w
computer ccontains.

Counters th T Framework. The .NET Framework includes counters that you


hat are provideed by the .NET
can use to m
measure a widde range of appplication chaaracteristics. FFor example, yyou can look at
a the
number of exceptions thhrown, view de etails of locks and thread use, and examine the behavvior of the
garbage coollector.

Counters thhat you create yourself. You can create yoour own perfo
ormance coun nters to examiine specific
aspects of tthe behavior o ample, you can create a performance counter to
of your appliccation. For exa
count the n ular method or to count the
number of callls to a particu e number of times a specifiic exception
is thrown.

Brrowsing and
d Using Performance Counters
Peerformance coounters are orgganized into categories.
c This helps you tto find the cou
unters you waant when
you are capturin
ng and review wing performa ance data. Forr example, thee PhysicalDisk category typically
inccludes counte
ers for the percentage of tim
me spent readding and writing to disk, am mounts of data read
om and written to disk, and
fro d the queue leengths to read
d data from an nd write data to disk.

Note: You u can browse the performance counters available on yyour compute er from Visuall
udio. In Server Explorer, exp
Stu pand Serverss, expand the name of yourr computer, an
nd then expannd
Pe
erformance C Counters.

Typically, you caapture and vie ew data from performance e counters in P


Performance M
Monitor (perfmmon.exe).
Pe
erformance Mo onitor is inclu
uded in the W Windows operaating system and
a enables yoou to view or capture
data from perfoormance coun nters in real tim
me. When you
u use Performmance Monitorr, 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

Demonstrration: Exxtending tthe Class Enrollmen


D E nt Applicattion Functionality
L
Lab

I this demon
In nstration, you will learn abo
out the tasks tthat you will p
perform in the
e lab for this module.
m
2-36 Creatingg Methods, Handling Exceptions, and M
Monitoring Applicatiions

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

Sccenario
Yo
ou have been asked to refacctor the code that you wro ote in the lab e
exercises for module
m 1 into
o separate
meethods to avo
oid the duplicaation of code in the Class EEnrollment Appplication.

Alsso, you have b


been asked to
o write code th
hat validates tthe student in
nformation that the user en
nters and to
enable the updaated student information
i to
o be written b
back to the daatabase, handling any errorrs that may
occur.

Ob
bjectives
Aftter completing this lab, you
u will be able to:

ode to facilitatte reusability.


Refactor co

Write Visuaal C# code tha


at validates da
ata entered byy a user.
Write Visuaal C# code tha
at saves chang
ges back to a database.

Esttimated Time:: 60 minutes

Virtual Macchine: 20483A


A-SEA-DEV11--02, MSL-TMG
G1
User Name: Student

Password: Pa$$w0rd
P
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. Start the MSL-TMG1 virtual machine if it is not already running.

2. Start the 20483A-SEA-DEV11-02 virtual machine and log on as Student with the password
Pa$$w0rd.
3. Start Visual Studio and open the School.sln solution from the E:\Labfiles\Starter\Exercise 1 folder.

4. 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.

5. 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. Build the solution and resolve any compilation errors.

2. Change Kevin Lius last name to Cook by pressing Enter in the main application window.

3. Verify that the updated data is copied back to the students list and that the Save Changes button is
now enabled.
4. Change George Lis name to Darren Parker by double-clicking on his row in the main application
window.

5. Verify that the updated data is copied back to the student list.
6. 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. On the Analyze menu, click Analyze Solution for Code Clones.

2. In the Code Clone Analysis Results window, expand Exact Match.

3. 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.

4. 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. Refactor the code in the case Key.Insert code block in the studentsList_KeyDown method into a
method called addNewStudent that takes no parameters.

2. Call this method from the case Key.Insert code block in the studentsList_KeyDown method.
3. 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.

4. 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. Build the solution and resolve any compilation errors.

2. Run the application.

3. Add a new student by pressing Insert to display the New Student for Class 3C window, and verify that
it contains no data.

4. 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.

5. Delete the student Run Liu and verify that the prompt window appears and the student is removed
from the student list.

6. Close the application.

X Task 6: Debug the application and step into the new method calls
1. Add a breakpoint at the start of the switch statement in the studentsList_KeyDown method.

2. Debug the application.

3. Edit the row for Kevin Liu by pressing Enter.

4. 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.

5. Step out of the editStudent method.


6. Cancel editing the students details, and then continue debugging.

7. Add a new student by pressing Insert.

8. Step over the code until you reach the addNewStudent method call, and then step into that
method.

9. 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. In Visual Studio, from the E:\Labfiles\Starter\Exercise 2 folder, open the School.sln solution.

2. Build the solution and resolve any compilation errors.

3. Run the application.


4. Press Insert to display the new student window.

5. Leave the First Name and Last Name boxes empty, and type 10/06/3012 in the Date of Birth box.

6. 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. In the ok_Click method in StudentForm.xaml.cs code, add a statement to check if the First Name
box is empty.

2. 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.

3. In the ok_Click method in StudentForm.xaml.cs code, add a statement to check if the Last Name
box is empty.

4. 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. In the ok_Click method in StudentForm.xaml.cs code, add a statement to check if the Date of Birth
box is empty.
2. 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.

3. 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.

4. 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. Build the solution and resolve any compilation errors.
2. Run the application.

3. Press Insert to display the new student window.

4. Leave the First Name, Last Name, and Date of Birth boxes empty.
5. Click OK, verify that an error message appears containing the text The student must have a first
name, then close the error message box.

6. Type Darren into the First Name box, and then click OK.
7. Verify that an error message appears containing the text The student must have a last name, and
then close the error message box.

8. Type Parker into the Last Name box, and then click OK.

9. 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. In Visual Studio, from the E:\Labfiles\Starter\Exercise 3 folder, open the School.sln solution.

2. Build the solution and resolve any compilation errors.

3. Run the application.

4. Change Kevin Lius last name to Cook by pressing Enter in the main application window.
5. Verify that the updated data is copied to the student list and that the Save Changes button is
enabled.

6. Click Save Changes.


7. Delete the student George Li, and then click the Save Changes button.

8. Close the application.

9. 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. In the MainWindow.xaml.cs code bring the System.Data and System.Data.Objects namespaces
into scope.

2. Add code to perform the following tasks when a user clicks Save Changes:

a. Call the SaveChanges method of the schoolContext object.

b. 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. Below the try block, add a catch block to catch any OptimisticConcurrencyException exceptions
that may occur.

3. 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. Add another catch block to catch any UpdateException exceptions that may occur, storing the
exception in a variable named uEx.

5. 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. Add another catch block to catch any other type of exception that might occur, storing the exception
in a variable named ex.

7. 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. Build the solution and resolve any compilation errors.
2. Run the application.

3. Change Kevin Lius last name to Cook by pressing Enter in the main application window.

4. In the main application window, click Save Changes.


5. Delete the student George Li by pressing Delete.

6. Click Save Changes and note that the button is disabled when no changes are pending.

7. Close the application.

8. 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.

9. 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 Creatingg Methods, Handling Exceptions, and M
Monitoring Applicatiions

Modu
ule Reviiew and
d Takea
aways

M
Module Revie
ew
In this module, yyou learned how
h to create and use meth hods, and how w to handle exceptions. You also
leaarned how to use logging aand tracing to
o record the details of any e
exceptions tha
at occur.
Ve
erify the correcctness of the statement by placing a maark in the column to the rig
ght.

S
Statement Answer

T return typ
The pe of a metho
od forms part of a methodss signature.

Test Your Know


wledge

Q
Question

W
When using ooutput parameters in a me
ethod signature, which one
e of the follow
wing
statements is true?

S
Select the corrrect answer.

You caannot return d


data by using a return state
ement in a me
ethod that use
e output
param
meters.

You caan only use th


he type objectt when definin
ng an output parameter.

You m
must assign a vvalue to an ou
utput parametter before the
e method retu
urns.

You de
efine an output parameter by using the output keywo
ord.

Ve
erify the correcctness of the statement by placing a maark in the column to the rig
ght.

S
Statement Answer

A finally blockk enables you to run code in


i the event o
of an error occcurring?

Ve
erify the correcctness of the statement by placing a maark in the column to the rig
ght.
Programming in Visual C# 2-45

Statement Answer

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

3-1

Module 3
Developing the Code for a Graphical Application
Contents:
Module Overview 3-2

Lesson 1: Implementing Structs and Enums 3-3

Lesson 2: Organizing Data into Collections 3-17


Lesson 3: Handling Events 3-31

Lab: Writing the Code for the Grades Prototype Application 3-41

Module Review and Takeaways 3-52


3-2 Developinng the Code for a Graphical Applicationn

Modu
ule Ove
erview

Too create effective graphical applications b


by using Wind dows Presentaation Foundattion (WPF) or other .NET
Fraamework plattforms, you must first learn some basic V Visual C# consstructs. You neeed to know h how to
eate simple structures to re
cre epresent the ddata items you u are working with. You nee ed to know how to
orgganize these structures
s into
o collections, so that you caan add items, retrieve items, and iterate over your
ite
ems. Finally, yo
ou need to kn
now how to su ond to the actions of
ubscribe to evvents so that yyou can respo
your users.

In this module, yyou will learn how to creatte and use stru
ucts and enum
ms, organize d
data into colle
ections, and
eate and subscribe to eventts.
cre

Ob
bjectives
Aftter completing this module
e, you will be able to:
Create and use structs an
nd enums.

Use collection classes to organize dataa.

Create and subscribe to e


events.
Programmingg in Visual C# 3-3
3

Lesson 1
Implementiing Stru
ucts and
d Enum
ms

The .NET Fram


T mework includ des various buuilt-in data typ
pes, such as In
nt32, Decima al, String, and
d Boolean.
H
However, suppose you wan n object that represented a coffee. Whicch type would you use?
nt to create an
Y might use
You e built-in type
es to represennt the propertties of a coffee
e, such as the country of orrigin (a string))
o the strengtth of the coffe
or ee (an integerr). However, yoou need a way to represent coffee as a d discrete
e
entity, so thatt you can perfform actions ssuch as add a coffee to a co ollection or co
ompare one ccoffee 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 completting this lesson, you will be able to:

Create an
nd use enums.
Create an
nd use structs..

Define co
onstructors to instantiate sttructs.

Create prroperties to ge
et and set field values in a sstruct.
Create ind
dexers to expose struct me
embers by usin
ng an integerr index.
3-4 Developinng the Code for a Graphical Applicationn

Crreating an
nd Using E
Enums

An
n enumeration n type, or enu ure that enablles you to create a variable
um, is a structu e with a fixed sset of
po
ossible values. The most com mmon examp ple is to use an
n enum to deffine the day oof the week. There are
on
nly seven posssible values for days of the w
week, and you can be reasonably certain n that these vvalues will
ne
ever change.

The following exxample showss how to creatte an enum:

eclaring an En
De num
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 sspecify which enum memb
ber you
waant to use.

The following exxample showss how to use an


a enum:

Ussing an Enum
m
D
Day favoriteD
Day = Day.Fr
riday;

Ussing enums haas several advantages over using text or numerical typ
pes:

Improved manageability.
m . By constrainiing a variable to a fixed sett of valid value
es, you are lesss likely to
experience invalid argum
ments and speelling mistakess.

Improved developer
d expeerience. In Visu e IntelliSense feature will prompt you with the
ual Studio, 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 aand understan
nd.

Each member o of an enum haas a name and d a value. The name is the sstring you deffine in the braaces, such as
Sunday or Mond day. By default, the value iss an integer. If you do not specify a value for each meember, the
me mental values starting with 0. For example, Day.Sunday is equal to
embers are asssigned increm o 0 and
Da
ay.Monday iss equal to 1.

The following exxample showss how you can


n use names aand values intterchangeablyy:
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 Developinng the Code for a Graphical Applicationn

Crreating an
nd Using S
Structs

In Visual C#, a sstruct is a prog


gramming con ou can use to define custom
nstruct that yo m types. Struccts are
esssentially lightw
weight data structures thatt represent rellated pieces o
of information
n as a single ittem. For
exaample:
med Point might consist of fields to rep
A struct nam present an x-co
oordinate and
d a y-coordina
ate.

A struct nam
med Circle might consist o
of fields to rep
present an x-coordinate, a yy-coordinate, and a
radius.
med Color might consist of fields to rep
A struct nam present a red ccomponent, a green compo
onent, and
a blue component.

Mo ost of the built-in types in V


Visual C#, succh as int, bool, and char, are defined byy structs. You ccan use
e your own types that behaave like built-in types.
strructs to create

Crreating a Sttruct
Yo
ou use the stru
uct keyword tto declare a sttruct, as show
wn by the follo
owing example:

De
eclaring a Strruct
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 acceess modifier
public in the above exam mplethat spe ecifies
wh
here you can u You can use tthe following access modifiiers in your struct declaratio
use the type. Y ons:

A
Access Modifiier Detailss

p
public The tyype is available to code run
nning in any assembly.

i
internal The tyype is available to any code
e within the saame assemblyy, but not avaiilable to
code in
i another asssembly. This iss the default vvalue if you do
o not specify an access
modiffier.
Programming in Visual C# 3-7

Access Modifier Details

private 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 Developinng the Code for a Graphical Applicationn

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 beccause when yo ou instantiate
e a struct, you are actually ccalling a
spe
ecial type of m
method calledd a constructoor. A constructtor is a metho
od in the strucct that has the
e same
name as the struuct.

Whhen you instantiate a structt with no arguuments, such as new Coffe ee(), you are ccalling the deffault
con by the Visual C# compiler. If you want to
nstructor whicch is created b o be able to specify defaultt field
values when you u instantiate a struct, you can
c add constructors that aaccept parame eters to your sstruct.

The following exxample showss how to creatte a constructtor in a struct::

Ad
dding a Consstructor
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 exxample showss how to use this


t constructor to instantiaate a Coffee iitem:

Ca
alling a Consttructor
/
// 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 yourr struct, with e
each constructtor accepting a different co
ombination
However, you cannot add a default consstructor to a struct because
of parameters. H e it is created by the
compiler.
Programming in Visual C# 3-9
3-10 Developping the Code for a Graphical Applicatioon

Crreating Prroperties

In Visual C#, a pproperty is a programming


p construct that enables client code to ge
et or set the vaalue of
priivate fields within a struct o
or a class. To cconsumers of your struct or class, the property behaves like a
pu e property is implemented by using acceessors, which are
ublic field. Witthin your strucct or class, the a a
speecial type of mmethod. A pro operty can incclude one or b both of the fo
ollowing:

A get accesssor to provide read access to a field.

A set accessor to provide


e write accesss to a field.
perty in a struct:
The following exxample showss how to impllement a prop

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; }
}
}

Wiithin the prop


perty, the get and set accesssors use the ffollowing synttax:

The get acccessor uses the return keyw


word to return
n the value off the private fiield to the calller.
The set acccessor uses a sspecial local vaariable named
d value to sett the value of the private fie
eld. The
value variable contains tthe value provvided by the cclient code whhen it accesseed the propertty.

The following exxample showss how to use a property:

Ussing a Properrty
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 IIndexers

IIn some scenaarios, you mig


ght want to usse 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 cofffee shop. The
e struct mightt
u an array of
use o strings to sttore the list off beverages.
T following example sho
The ows a struct th
hat includes an
n array:

C
Creating a Sttruct that Inccludes an Arrray
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 arrayy as a public ffield, you wou
uld use the folllowing syntaxx to retrieve b
beverages
f
from the list:

A
Accessing Arrray Items Directly
Menu myMenu
u = new Menu
u();
string firs
stDrink = my
yMenu.beverages[0];

A more intuitiive 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 creatingg an indexer. An indexer is similar to a pproperty, in that it uses get
a set accesssors to contro
and ol access to a field.
f More im
mportantly, an n indexer enab bles you to access
c
collection members directlyy from the naame of the con ntaining strucct or class by p
providing an integer
i index
v
value. To decllare an indexe
er, you use thee this keyworrd, which indiccates 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 write-
only 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: Crreating an
nd Using a Struct

IIn this demon nstration, you will create a sstruct named Coffee and aadd several prroperties to th
he struct. You
w then creatte an instance
will e of the Coffeee struct, set some
s propertyy values, and display these property
v
values in a console windoww.

D
Demonstra
ation Steps
1
1. Start the MSL-TMG1 viirtual machine
e if it is not already running
g.

2
2. Start the 20483A-SEA-DEV11-03 virrtual machine..
3
3. Log on to
o Windows 8 as
a Student with the passwo
ord Pa$$w0rrd.

Note: Iff necessary, click Switch Usser to display the list of use
ers.

4
4. Switch to the Windowss 8 Start wind
dow.

5
5. Click Visu
ual Studio 20
012.

6
6. In Visual Studio, on the
e File menu, p
point to New,, and then clicck Project.
7
7. In the Ne ew Project dia
alog box, in th
he Templatess list, click Vissual C#, and tthen in the Prroject Type
list, click Console
C Appplication.

8
8. In the Na
ame box, type
e UsingStructts
9
9. In the Loccation box, se
et the location
n to E:\Demo
ocode, and then click OK.

1 In the UsingStructs naamespace, add the followin


10. 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, reggardless of wh
hether they arre integers, strrings, or a
c
custom type ssuch as Coffee, you need a way of manaaging the item ms as a set. Yo
ou need to be able to
c
count the nummber of itemss in the set, ad
dd items to orr remove itemms from the set, and iterate through the
s one item aat a time. To d
set do this, you caan use a collecction.

Collections arre an essentiall tool for man


C naging multiple items. Theyy are also centtral to develop
ping
g
graphical app ntrols such as drop-down list boxes and menus are typ
plications. Con 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 completting this lesson, you will be able to:
Choose appropriate co different scenarios.
ollections for d

Manage items
i in a colllection.

NQ) syntax to query a colle


Use Language Integratted Query (LIN ection.
3-18 Developping the Code for a Graphical Applicatioon

Ch
hoosing C
Collectionss

Alll collection claasses share vaarious commo


on characteristtics. To manag
ge a collection
n of items, yo
ou must be
ab
ble to:

Add items tto the collection.

Remove items from the ccollection.

ecific items fro


Retrieve spe om the collecction.

Count the n
number of items in the collection.

Iterate through the itemss in the collecction, one item


m at a time.

Eveery collection class in Visuaal C# providess methods and d properties tthat support these core ope erations.
Be
eyond these operations, how wever, you wiill want to maanage collectio ons in differennt ways depennding on
the
e specific requuirements of your
y applicatiion. Collection
n classes in Visual C# fall into the followiing broad
cattegories:

List classes store linear co


ollections of ittems. You can ne-dimensional array
n think of a lisst class as a on
that dynam mically expands as you add items. For exaample, you might use a list class to main ntain a list
of availablee beverages att your coffee shop.
s

Dictionary cclasses store a collection off key/value pa airs. Each item


m in the collecttion consists o
of two
objectsthhe key and the e value. The vaalue is the objject you wantt to store and retrieve, and the key is
the object tthat you use tto index and look up the vaalue. In most dictionary
d classses, the key m
must be
unique, whe ereas duplicatte values are perfectly
p acceeptable. For exxample, you might
m use a diictionary
class to maiintain a list off coffee recipe
es. The key woould contain tthe unique naame of the cofffee, and
the value w
would contain the ingredien nts and the insstructions for making the coffee.
c

Queue classses represent a first in, first out collection


n of objects. Ittems are retrieved from the
e collection
in the same
e order they w
were added. Fo or example, you might use a queue classs to process o orders in a
coffee shop
p to ensure that customers receive their d drinks in turn.

Stack classe out collection of objects. Th


es represent a last in, first o he item that yo
ou added to tthe
collection laast is the first item you retrrieve. For exam
mple, you mig
ght use a stackk class to dete
ermine the
10 most reccent visitors to o your coffee shop.

Wh
hen you choo
ose a built-in ccollection classs for a specifiic scenario, assk 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 Developping the Code for a Graphical Applicatioon

Sttandard Collection Classes

The System.Collections nam mespace provides a range of o general-purrpose collectio


ons that includes lists,
dicctionaries, que
eues, and staccks. The follow ows the most important collection classe
wing table sho es in the
Sy
ystem.Collecttions namespaace:

C
Class Descrription

A
ArrayList The AArrayList is a general-purp
pose list that sstores a linearr collection off objects.
The AArrayList includes method ds and properrties that enab ble you to add d items,
remoove items, couunt the numbber of items in the collection n, and sort the
colle
ection.

B
BitArray The BitArray is a list class that represents a collection
c of b
bits as Boolean values.
The BitArray is m
most commonlly used for bittwise operatio ons and Boole ean
hmetic, and includes metho
arith ods to performm common Bo oolean operattions such
as AND, NOT, and d XOR.

H
Hashtable The Hashtable claass is a generaal-purpose dictionary classs that stores a collection
ey/value pairss. The Hashtable includes m
of ke methods and properties thaat enable
you to retrieve ite
ems by key, addd items, remove items, and check for particular
keys and values wwithin the colle
ection.

Q
Queue The Queue class is a first in, lasst out collectio
on of objects. The Queue in
ncludes
methhods to add oobjects to the back of the q queue (Enqueue) and retrieeve objects
from
m the front of the queue (Dequeue).

S
SortedList The SortedList claass stores a coollection of ke
ey/value pairs that are sorte
ed by key.
ddition to the functionality provided by the Hashtablle class, the So
In ad ortedList
enabbles you to rettrieve items either by key or
o by index.

S
Stack The Stack class is a first in, firstt out collection of objects. T
The Stack includes
meth hods to view the
t top item iin the collectio on without reemoving it (Peeek), add
an ittem to the top
p of the stack (Push), and rremove and re eturn the item
m at the top
of th
he stack (Pop)).
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 Developping the Code for a Graphical Applicatioon

Sp
pecialized Collectio
on Classes

The System.Collections.Spe ecialized namespace provid des collection classes that aare suitable fo
or more
spe
ecialized requ
uirements, succh as specializzed dictionaryy collections and strongly tyyped string co ollections.
The following taable shows the most imporrtant collection classes in th he System.Co ollections.Spe ecialized
namespace:

C
Class Descriptio
on

L
ListDictionar
ry The LListDictionary y is a dictionaary class that is optimized foor small
collecctions. As a ge
eneral rule, if yyour collectio
on includes 10 0 items or
fewerr, use a ListDiictionary. If yyour collectionn is larger, use
ea
Hashhtable.

H
HybridDictio
onary The HybridDiction
H nary is a dictionary class th
hat you can usse when
you cannot
c estimate the size of the collectionn. The HybriddDictionary
uses a ListDictionaary implemen ntation when the collectionn size is
small, and switchess to a Hashtaable implemen ntation as the
e collection
size g
grows larger.

O
OrderedDicti
ionary The OrderedDictio
O onary is an in
ndexed diction
nary class thatt enables
you to retrieve item ms by key or by
b index. Note that unlike tthe
SorteedList class, ittems in an OrdderedDiction nary are not ssorted by
key.

N
NameValueC
Collection The NameValueCo
N ollection is an indexed dicctionary class iin which
both the key and tthe value are strings.
s The N
NameValueCo ollection
will th
hrow an errorr if you attemppt to set a keyy or a value to
o anything
otherr than a string
g. You can retrrieve items byy key or by inddex.

S
StringCollect
tion The StringCollecti
S ion is a list claass in which e
every item in tthe
collecction is a strin
ng. Use this claass when you want to store e a simple,
linearr collection off strings.

S
StringDiction
nary The StringDiction
S nary is a dictio
onary class in which both thhe key and
the vaalue are string
gs. Unlike the NameValueC Collection cla
ass, you
cannoot retrieve items from a StrringDictionarry by index.
Programming in Visual C# 3-23

Class Description

BitVector32 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 Developping the Code for a Graphical Applicatioon

Ussing List C
Collections

The most comm monly used listt collection is the ArrayListt class. The ArrrayList storees items as a linear
collection of objjects. You cann add objects of any type to o an ArrayLisst collection, b
but the Array yList
reppresents each item in the ccollection as a System.Obje ect instance. W
When you add d an item to aan
ArrrayList collecction, the ArraayList implicittly casts, or co
onverts, your item to the O
Object type. W When you
rettrieve items frrom the collecction, you must explicitly caast the object back to its orriginal type.

The following exxample showss how to add and retrieve iitems 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", "Coluumbia");
C
Coffee coffee
e2 = new Cof
ffee(3, "Ara
abica", "Viettnam");
C
Coffee coffee
e3 = new Cof
ffee(4, "Rob
busta", "Indoonesia");
/
// Add the it
tems to the collection.
/
// Items are implicitly cast to the
e Object typee 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 tyype.
C
Coffee firstC
Coffee = (Co
offee)bevera
ages[0];
C
Coffee second
dCoffee = (C
Coffee)bever
rages[1];

Wh hen you workk 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 inn turn, usuallyy to render
a list of items, to
o evaluate eacch item again nst some criterria, or to extraact specific me
ember values from each
ite
em. To iterate over a collecttion, you use a foreach loo op. The foreacch loop exposses each item from the
collection in turrn, using the variable
v name e you specify in the loop de eclaration.

The following exxample showss how to iteraate over an ArrrayList collecttion:


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 Developping the Code for a Graphical Applicatioon

Ussing Dictionary Colllections

Dicctionary classe
es store collecctions of key//value pairs. Th
he most comm monly used dictionary classs is the
Haashtable. Whe en you add an n item to a Ha ashtable colle must specify a key and a value. Both
ection, you m
the
e key and the value can be e instances of any type, but the Hashtab ble implicitly ccasts both the key and
the
e value to thee Object type.. When you re etrieve values from the collection, you mmust explicitly cast the
ob
bject back to itts original typ
pe.

The following exxample showss how to add and retrieve iitems 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, Chhocolate");
ingredients.A
Add("Cappucc
cino", "Coff
fee, Milk, Fooam");
ingredients.A
Add("Irish C
Coffee", "Co
offee, Whiskeey, Cream, S
Sugar");
ingredients.A
Add("Macchia
ato", "Coffe
ee, Milk, Foaam");
/
// 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"]);
}

Dicctionary classe
es, such as the
e Hashtable, actually contain two enum merable collecttionsthe ke eys and the
values. You can iterate over e either of these
e collections. In
I most scenaarios, howeverr, you are likelly to iterate
thrrough the keyy collection, fo
or example too retrieve the value
v associatted with each key in turn.

The following exxample showss how to iteraate over the ke


eys in a Hashtable collectio
on and retrievve 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 Developping the Code for a Graphical Applicatioon

Querying a Collectio
on

LINNQ is a query technology that is built in to .NET languuages such as Visual C#. LIN
NQ enables yoou to use a
staandardized, deeclarative que
ery syntax to q
query data froom a wide ran
nge of data soources, such ass .NET
collections, SQLL Server databbases, ADO.NE ET datasets, an
nd XML docum ments. A basicc LINQ query uses the
folllowing syntaxx:

fro
om <variable names> in <data source>

wh
here <selectio
on criteria>
orderby <resultt ordering critteria>

select <variablee names>

For example, suppose you usse a Hashtablle to maintain n a price list fo


or beverages aat Fourth Cofffee. You
miight use a LIN
NQ expression to retrieve all the drinks th
hat meet certaain price criteria, such as drrinks that
cost less than $2
2.00.

The following exxample showss how to use a LINQ expresssion to queryy a Hashtable
e:

Ussing LINQ to Query a Colllection


/
// Create a n
new Hashtabl
le and add ssome 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.89MM);
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.59MM);
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 $22.00, and or
rder them by
y cost.
v
var bargains =
from strin
ng drink in prices.Keyss
where (Dec
cimal)prices
s[drink] < 22.00M
orderby pprices[drink
k] ascendingg
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 thaat enable obje other objects when someth
ects to notify o hing happens.. For example,,
c
controls on a web page or in a WPF user interface generate eventss when a user interacts with h the control,
s
such as by cliccking a button
n. You can cre
eate code that subscribes to
o these eventss and takes so
ome action in
r
response to an event.

Without events, your code would need tto constantly read control values
W v to lookk for any channges in state
t
that require action. This wo
ould be a veryy inefficient way of developping an appliccation. In this lesson, you
w learn how
will w to create, or raise, events, and how to ssubscribe to e
events.

I this lesson, you will learn


In n how to hand
dle events.

L
Lesson Ob
bjectives
A
After completting this lesson, you will be able to:
Create evvents and dele
egates.

Raise events.

Subscribe
e to events an
nd unsubscribe
e from eventss.
3-32 Developping the Code for a Graphical Applicatioon

Crreating Ev
vents and Delegates

Whhen you creatte an event in a struct or a class, you neeed 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 methood signature; in
i other word ds, the return type
t and the parameters off a method. A As the name
sug
ggests, a dele
egate behavess like a represeentative for methods
m with matching sign natures.

Whhen you defin


ne an event, you associate a delegate witth your event. To subscribe
e to the eventt from client
code, you need to:

Create a me
ethod with a signature
s thatt matches the
e event delegaate. This meth
hod is known aas the event
handler.

o the event byy giving the name


Subscribe to n of your event handler method to tthe event publlisher, in
other words, the object tthat will raise the event.

Wh e delegate invokes all the evvent handler methods thatt have subscribed to the
hen the eventt is raised, the
eve
ent.
Suppose you cre eate a struct n
named Coffeee. One of the responsibilitie
es of this strucct is to keep ttrack of the
sto
ock level for e
each Coffee in nstance. When
n the stock levvel drops belo
ow a certain ppoint, you mig ght want to
raise an event too warn an orddering system that you are running out o of beans.
The first thing yyou need to doo is to define a delegate. To define a delegate, you usse the delega
ate
keyyword. A dele egate includess two parameters:

The first parameter is the


e object that rraised the eve
entin this caase, a Coffee iinstance.
The second parameter is the event arggumentsin o other words, aany other info
ormation thatt you want
to provide tto consumers. This must be
e an instance of the EventA
Args class, or an instance o
of a class
that derivess from EventA
Args.
Ne
ext, you need to define the event. To deffine an event, you use the event
e keyworrd. You preced
de the
name of your evvent with the name of the ddelegate you want to assocciate with you
ur event.

The following exxample showss 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 Developping the Code for a Graphical Applicatioon

Raaising Eve
ents

Aftter you have defined


d an evvent and a delegate, you caan write code that raises the
e event when certain
conditions are met.
m When yo ou raise the evvent, the deleg
gate associate
ed with your eevent will invo
oke any
eveent handler m
methods that have
h subscrib
bed to your evvent.
To
o raise an even
nt, you need tto do two thin
ngs:

1. Check whetther the eventt is null. The event


e will be n
null if no code
e is currently ssubscribing to
o it.

2. Invoke the event and pro


ovide argume
ents to the dellegate.
For example, suppose a Cofffee struct inclu
udes a method named MakeCoffee. Eve ery time you call
c the
MaakeCoffee method, the me ethod reduces the stock levvel of the Cofffee instance. If the stock le
evel drops
be
elow a certain point, the Ma
akeCoffee method will raisse an OutOfB Beans event.

The following exxample showss how to raise


e an event:

aising an Even
Ra nt
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 Developping the Code for a Graphical Applicatioon

Su
ubscribing
g to Eventts

If yyou want to h ode, you need to do two things:


handle an event in client co

Create a me
ethod with a signature
s thatt matches the
e delegate for the event.

Use the add


dition assignm
ment operatorr (+=) to attacch your event handler meth
hod to the eve
ent.

For example, suppose you haave created ann instance of tthe Coffee strruct named co
offee1. In you
ur
ventory class, you want to subscribe to the OutOfBe
Inv eans that mayy be raised by coffee1.

e previous top
Note: The pic shows howw the Coffee sstruct, the OutOfBeans eve
ent, and the
Ou
utOfBeansHaandler delegaate are defined
d.

The following exxample showss how to subsscribe to an evvent:

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 dleOutOfBeanns method matches the de elegate for the
e
OuutOfBeans evvent. When yo ou call the Sub
bscribeToEveent method, tthe HandleOu utOfBeans mmethod is
added to the list of subscribe
ers for the OuttOfBeans eve
ent on the cofffee1 object.

o unsubscribe from an even


To nt, you use the
e subtraction assignment o
operator (-=) tto remove you
ur event
handler methodd from the eve
ent.

The following exxample showss how to unsu


ubscribe from an event:
Programming in Visual C# 3-37

Unsubscribing from an Event


public void UnsubscribeFromEvent()
{
coffee1.OutOfBeans -= HandleOutOfBeans;
}
3-38 Developping the Code for a Graphical Applicatioon

Demonstration: Working with


h Events in
n XAML

Vissual Studio prrovides tools tthat make it e


easy to work w
with events in WPF applicattions. In this
de
emonstration, you will learn n how to subsccribe to eventts raised by W
WPF controls.

De
emonstration Steps
1. Start the MSL-TMG1 virtual machine if it is not already running.

2. 0483A-SEA-DEEV11-03 virtual machine.


Start the 20

3. Log on to W
Windows 8 as Student with
h the password Pa$$w0rd.

Note: If necessary, clickk Switch Userr to display th


he list of userss.

4. he Windows 8 Start window


Switch to th w.

5. Click Visual Studio 2012


2.

6. udio, on the F
In Visual Stu a then clickk Project/Solution.
File menu, point to Open, and

7. In the Open
n Project diallog box, brow
wse to the E:\D
Democode\Starter folder, click
EventsAnddXAML.sln, an nd then click Open.
O

8. In Solution Explorer, expand EventsAn


ndXAML, and
d then double
e-click MainW
Window.xamll.

9. Notice that the window iincludes a buttton named b


btnGetTime aand a label naamed lblShow
wTime.
0. In the Desig
10 gn window, click the butto
on to select it.

11. In the Prop


perties window
w, ensure that btnGetTime
e is selected, aand then clickk Events.

Note: The
e Events butto
on is marked with a lightning icon.

12. Notice that the Propertiies window no ents to which you can subscribe.
ow displays a list of the eve
perties window
13. In the Prop w, double-clicck inside the C
Click text boxx.
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 double-
click 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 Developping the Code for a Graphical Applicatioon

Demonstration: Writing Code


e for the G
Grades Pro
ototype A
Application
n Lab

In this demonstration, you wiill learn aboutt the tasks thaat you will perrform in the laab for this mo
odule.
Programming in
i Visual C# 3-41
1

Lab: Writingg the C


Code for the Grades P
Prototy
ype
Appllication
n

S
Scenario
The School off Fine Arts hass decided thatt they want to
T o extend their basic class en nrollment app plication to
e
enable teacheers to record tthe grades thaat students in their class haave achieved ffor each subje ect, and to
a
allow students to view their own grades.. This function nality necessittates impleme enting applicaation log on
f
functionality tto authenticatte the user an
nd to determin ne whether th he user is a teaacher or a student.

You decide to
Y o start by deve
eloping parts of a prototyppe application to test prooff of concept and to obtain
c
client feedbacck before emb barking on the ototype appliccation will use basic WPF
e final applicaation. The pro
v
views rather than separate forms for the
e user interface. These views have alreadyy been design ned and you
m
must add the code to naviggate among them.

You also decid


Y de to begin by
b storing the user and grad de information in basic stru
ucts, and to usse a dummy
d
data source in
n the application to test your log on funcctionality.

O
Objectives
A
After completting this lab, you
y will be able to:
Navigate among viewss.

Create an
nd use collectiions of structss.

Handle evvents.
E
Estimated Tim
me: 60 minutes

3A-SEA-DEV11-03, MSL-TM
Virtual Machine: 20483 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. Start the MSL-TMG1 virtual machine if it is not already running.

2. Start the 20483A- SEA-DEV11-03 virtual machine and log on as Student with the password
Pa$$w0rd.

3. Start Visual Studio and open the GradesPrototype.sln solution from the
E:\Labfiles\Starter\Exercise 1 folder.

4. Build the solution.

5. 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.

7. 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.

8. 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.

X Task 2: Define the LogonSuccess event and add dummy code for the Logon_Click
event
1. In the LogonPage.xaml.cs class, in the Event Members region, define a public event handler named
LogonSuccess.

2. 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.

3. In the Logon_Click event handler, add code to do the following:

a. Save the username and role that the user specified on the form in the relevant properties of the
SessionContext object.
b. If the user is a student, set the CurrentStudent property of the SessionContext object to the
string Eric Gruber.

c. Raise the LogonSuccess event.


d. In the LogonPage.xaml XAML editor, locate the definition of the Log on button.

e. 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. 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.

2. 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.

3. In the MainWindow.xaml XAML editor, locate the definition of the LogonPage page.

4. Modify the definition to call the Logon_Success method for the LogonSuccess event.

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.
2. In the GotoStudentProfile method, add code to hide the studentsPage view, and then to display
and refresh the studentProfile view.

3. In the GotoStudentsPage method, add code to hide the studentProfile view, and then add code to
display and refresh the studentsPage view.

4. In the StudentProfile.xaml.cs file, in the Refresh method, add code to:


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. If a name is successfully parsed, display the first name and last name of the student in the
appropriate boxes.
5. 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. In the StudentsPage.xaml.cs file, in the StudentsPage class, locate the Student_Click method.
2. 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.
3. 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.

4. Call the GotoStudentProfile method.

5. In the MainWindow.xaml XAML editor, locate the definition of the StudentsPage page.

6. Modify the definition to call the studentsPage_StudentSelected method for the StudentSelected
event.

X Task 6: Build and test the application


1. Build the solution and resolve any compilation errors.

2. Run the application.


3. Log on as the teacher, vallee with a password of password.

4. 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. Log off the application.
7. Log on as the student, grubere, with a password of password.

8. Verify that the application displays the student profile page for Eric Gruber.

9. 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. Open the GradesPrototype solution from the E:\Labfiles\Starter\Exercise 2 folder.

2. In the Data folder, open Grade.cs.

3. 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

4. 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
5. 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. In Solution Explorer, rename the UnitTest1.cs file as GradesUnitTests.cs.

3. Add a using directive to the GradesUnitTests file to bring the GradesPrototype.Data namespace
into scope.

4. 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 Value

FirstName Eric

LastName Gruber

UserName grubere

Password password

TeacherTest test method: To create a new teacher by using the following information, and then
verify that it is created correctly.

Field Value

FirstName Esther

LastName Valle

UserName vallee

Password password

Class 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 Value

assessment B+

subject Math

comments 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 subject comments

B+ Math Good

A- English Very Good

C- Geography Could do better

D- History Very poor

5. Build the solution and resolve any compilation errors.


6. Run all tests and verify that they all pass.

7. 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. Open the GradesPrototype solution from the E:\Labfiles\Starter\Exercise 3 folder.

2. In the Data folder, in the DataSource.cs file, expand the Sample Data region.

3. Note how the Teachers ArrayList is populated with Teacher data, each containing TeacherID,
UserName, Password, FirstName, LastName, and Class fields.

4. Note how the Students ArrayList is populated with Student data, each containing a StudentID,
UserName, Password, TeacherID, FirstName, and LastName fields.
5. 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. In the LogonPage.xaml.cs file, in the Event Members region, define a public event handler named
LogonFailed.

2. 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.

c. 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.
d. 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.
e. If the credentials do not match any teachers or students, raise the LogonFailed event.

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.

2. In the Logon_Failed event handler, add code to display an error message to the user.

3. In the MainWindow.xaml XAML editor, locate the definition of the LogonPage page.
4. Modify the definition to call the Logon_Failed method for the LogonFailed event.

5. In the MainWindow.xaml.cs code, locate the Refresh method.

6. In the case statement for a student, add code to display the student name in txtName text box at the
top of the page.

7. In the case statement for a teacher, add code to display the teacher name in the banner at the top of
the page.

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. Find all the students for the current teacher and store them in a new ArrayList object.

b. Bind the collection to the ItemsSource property of the list control.

c. Display the class name.

3. Locate the Student_Click event and then add code to do the following:
a. Identify which student was clicked by using the Tag property of the button.

b. Find the details of that student by examining the DataContext of the button.

c. Raise the StudentSelected event, passing the student as the second parameter.
d. 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.

2. In the StudentProfile.xaml XAML editor, locate the definition of the firstName text block.

3. Modify the definition to bind the Text property to the FirstName field.
4. Locate the definition of the lastName text block.

5. Modify the definition to bind the Text property to the LastName field.

6. 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.

X Task 6: Build and test the application


1. Build the solution and resolve any compilation errors.

2. Run the application.

3. Log on as parkerd with a password of password and verify that the Logon Failed message box
appears.
4. Log on as vallee with a password of password and verify that the Students page appears.

5. Click Kevin Liu, verify that the Student Profile page appears, and then log off.

6. Log on as grubere with a password of password and verify that the Student Profile page appears.
7. 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 Developping the Code for a Graphical Applicatioon

Modu
ule Reviiew and
d Takea
aways

M
Module Revie
ew
In this module, yyou have learrned how to im
mplement stru
ucts and enum
ms, organize d
data into colle
ections, and
woork with eventts and delegates.
Test Your Know
wledge

Q
Question

Y
You want to ccreate a string
g property naamed CountryyOfOrigin. Yo
ou want to bee able to
re
ead the property value froom any code, but you shouuld only be able to write tto the
p
property from
m within the ccontaining strruct. How sho
ould you decllare the propeerty?

S
Select the corrrect answer.

publicc string CountryOfOrigin { g


get; set; }

publicc string CountryOfOrigin { g


get; }

publicc string CountryOfOrigin { sset; }

publicc string CountryOfOrigin { g


get; private se
et; }

private
e string CountryOfOrigin { get; set; }

Test Your Know


wledge

Q
Question

YYou want to ccreate a collecction to store


e coffee recipees. You must be able to re
etrieve
eeach coffee re
ecipe by provviding the nam me of the cofffee. Both thee name of thee coffee
aand the coffeee recipe will b
be stored as sstrings. You also need to b
be able to retrrieve
ccoffee recipess by providingg an integer iindex. Which collection claass 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 4-2

Lesson 1: Creating Classes 4-3

Lesson 2: Defining and Implementing Interfaces 4-18


Lesson 3: Implementing Type-Safe Collections 4-31

Lab: Adding Data Validation and Type-Safety to the Application 4-49

Module Review and Takeaways 4-61


4-2 Creating Classes and Implem
menting Type-Safe Collections
C

Modu
ule Ove
erview

Claasses enable yyou to create your own cusstom, self-con ntained, and re
eusable types. Interfaces en
nable you
to define a set o
of inputs and outputs that cclasses must implement in order to ensu ure compatibility with
consumers of th he classes. In tthis module, you
y will learn how to use innterfaces and classes to deffine and
cre
eate your own n custom, reussable types. YYou will also le e enumerable, type-safe
earn how to crreate and use
collections of anny type.

Ob
bjectives
Aftter completing this module
e, you will be able to:

Create and instantiate claasses.

Create and instantiate interfaces.

Use genericcs to create tyype-safe collecctions.


Programmingg in Visual C# 4-3
3

Lesson 1
Creatting Cla
asses

IIn Visual C#, yyou can define e your own cu ustom types by
b creating cla asses. As a pro
ogramming coonstruct, the
c
class is central to object-orriented prograamming in Vissual C#. It enaables you to eencapsulate th
he behaviors
a characterristics of any lo
and ogical entity in a reusable aand extensible
e way.

I this lesson, you will learn


In n how to creatte, use, and te
est classes in yyour own app
plications.

L
Lesson Ob
bjectives
A
After completting this lesson, you will be able to:

Create claasses.
Create ob
bjects by insta
antiating classses.

Use consttructors to sett values or to run logic whe


en classes are instantiated.

Explain th
he difference between reference types and value type
es.
Create staatic classes an
nd members.

Describe the high-leve


el process for ttesting class functionality.
f
4-4 Creating Classes and Implem
menting Type-Safe Collections
C

Crreating Classes and Members

In Visual C#, a cclass is a programming construct that yo ou can use to d define your own custom tyypes. When
you create a class, you are efffectively creatting a blueprint for the typpe. The class defines the beh haviors and
characteristics, o
or class memb bers, which arre shared by aall instances off the class. Yo
ou represent thhese
beehaviors and ccharacteristics by defining m methods, fieldds, properties, and events w within your claass.

For example, suppose you cre eate a class naamed DrinksMachine. You u would use fields and prop perties to
de
efine the charaacteristics of a drinks machine, such as thhe make, mod del, age, and service
s interva
al of the
maachine. You w
would create m methods to represent the thhings that a drinks machine e can do, suchh as make
an espresso or mmake a cappu uccino. Finally,, you would d
define events to
t represent aactions that mmight
req
quire your atttention, such aas replacing ccoffee beans w
when the macchine has run o out of coffee beans.

De
eclaring a Class
C

Yo o declare a claass, as shown in the following example:


ou use the classs keyword to

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 accesss modifier, su
uch as public in the above example, which specifies
fro
om where youu can use the ttype. You can
n use the following access modifiers
m in yo
our class decla
arations:

A
Access modifier Description

p
public The type is available to ccode running in any assemb
bly that refere
ences the
assembly in
n which the cla ass is containe
ed.

i
internal The type is available to aany code within the same assembly, but not
available to
o code in anotther assemblyy. This is the default value iff you do
not specify an access mo odifier.

p
private The type is only available
e to code with
hin the class th
hat contains it. You can
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 usee the behaviorrs and charactteristics that yyou define witthin a class,
you need to cre eate instances of the class. A
An instance off a class is callled an object.

o create a new
To w instance of a class, you usse the new keyword, as sho
own in the folllowing examp
ple:

Insstantiating a Class
D
DrinksMachine
e dm = new D
DrinksMachin
ne();

Wh
hen you instantiate a class in this way, yo
ou are actuallly doing two tthings:

eating a new object


You are cre o in mem
mory based on the DrinksM
Machine type.
You are cre
eating an objecct reference named dm thaat refers to the
e new DrinkssMachine object.

Wh hen you creatte your objectt reference, instead of expliicitly specifyin


ng the DrinkssMachine type, you can
allo
ow the compiler to deduce e the type of tthe object at compile
c time.. This is known
n as type inferrence. To
usee type inferen
nce, you create your object reference by using the varr keyword, as shown in the e following
exaample:

Insstantiating a Class by Using Type Infe


erence
v
var dm = new DrinksMachi
ine();

In this case, the compiler doe es not know inn advance the e type of the ddm 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
DrrinksMachine e. Using type iinference in this way causees no change iin how your aapplication run ns; it is
sim
mply a shortcu ut for you to aavoid typing tthe class name e twice. In som
me circumstan nces, type infe
erence can
maake your code e easier to reaad, while in other circumstaances it may m make your cod de more confu using. As a
geeneral rule, consider using ttype inference e when the type of variable e is absolutelyy clear.

Aftter you have instantiated


i yyour object, yoou can use any of the mem mbersmetho ods, fields, pro
operties,
and eventsthaat you defined d within the cclass, 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

Ussing Consstructors

In the previous topics, you might


m have notticed that the syntax for insstantiating a cclassfor example, new
DrrinksMachine e()looks sim milar to the syn
ntax for callin
ng a method. This
T is becausse when you in nstantiate a
cla
ass, you are acctually calling a special metthod called a constructor. A constructor is a method in n the class
tha
at has the samme name as th he class.

Co
onstructors are
e often used tto specify initiial or default vvalues for datta members w
within the new
w object, as
sho
own by the fo
ollowing exammple:

Ad
dding a Consstructor
p
public class DrinksMachi
ine
{
public int
t Age { get;
; set; }
public Dri
inksMachine(
()
{
Age = 0
0;
}
}

A constructor
c thhat takes no pparameters is known as the default consttructor. This co onstructor is ccalled
wh
henever some eone instantiattes your class without provviding any arg guments. If you do not inclu ude a
constructor in yyour class, the Visual C# commpiler will auttomatically ad
dd an empty public
p defaultt
constructor to your
y compiled d class.
In many cases, it is useful for consumers off your class to
o be able to sp
pecify initial vvalues for dataa members
whhen the class is instantiated
d. For examplee, when someo one creates a new instance e of DrinksMa achine, it
miight be useful if they can sppecify the make and model of the machine at the sam me time. Your class can
incclude multiple
e constructorss with differen
nt signatures tthat enable co
onsumers to provide
p differe
ent
combinations of information when they in nstantiate your class.

The following exxample showss how to add multiple consstructors to a class:


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 Creatingg Classes and Impleementing Type-Safe Collections

Re
eference T
Types and
d Value Ty
ypes

Noow that you know how to create


c and instantiate classe
es, you will lea
arn about the
e differences between
b
cla
asses and struccts.

A struct
s is a valu
ue type. This definition
d appplies to built-in
n struct types,, such as int aand bool, as w
well as to
strructs that you define yourse elf. A value tyype contains itts data directlyy. In other woords, when you interact
witth a value typpe, you are intteracting direcctly with the d ns in memory.. By contrast, a class
data it contain
deefines a referennce type. Whe en you create an object by instantiating a class, you are creating a reference
typpe. The objectt itself is store
ed in memory,, but you inte eract with the object throug gh an object reeference.
Alll the object re
eference does is point to th he object in memory.

Note: Mo ost of the builtt-in types in V


Visual C#, such
h as int, bool,, byte, and ch
har, are value
typ
pes. For more information aabout built-in n types, see th
he Built-In Typ
pes Table (C# Reference)
page at http://g
go.microsoft.ccom/fwlink/?LinkID=267800 0.

Vaalue types andd reference typpes behave diifferently. If yo


ou copy a value type from one variable to another,
you are copying g the data thaat your variablle contains annd creating a new
n instance of that data in memory.
If yyou copy an o
object reference from one vvariable to another, all you are doing is ccopying the object
o
refference. You aare not creatin
ng a second object
o in mem mory. Both varriables will poiint to the sam
me object.

Bo
oxing and U
Unboxing
In some scenario os you may need to convert value typess to reference types, and vicce versa. For e example,
some collection classes will only
o accept refference types.. This is less likkely to be an issue with the
e advent of
geeneric 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 cconverting a vvalue type to a reference tyype is called b
boxing. To boxx 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 Creatingg Classes and Impleementing Type-Safe Collections

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

ore an integerr value and a reference typ


In this demonstration, you wiill create a vallue type to sto pe to store
an integer value
e. You will create a copy of each type, an nd then obserrve what happ pens when you u change
the
e value of the
e copy in eachh case.

De
emonstration Steps
1. Start the MSL-TMG1 virtual machine if it is not already running.

2. 0483A-SEA-D
Start the 20 DEV11-04 virttual machine.
3. Log on to W
Windows 8 as Student with
h the password Pa$$w0rd.

Note: If necessary, clickk Switch Userr to display th


he list of userss.

4. he Windows 8 Start window


Switch to th w.

5. Click Visual Studio 2012


2.

6. udio, on the F
In Visual Stu File menu, point to New, and then click Project.
7. In the New w Project dialo
og box, in the
e Templates liist, click Visua en in the Project Type
al C#, and the
list, click Co
onsole Appliccation.

8. In the Nam
me text box, tyype ValuesAn
ndReferencess
9. In the Location text boxx, set the locattion to E:\Dem
mocode, and then click OK
K.

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

struct MyStruct
{
public int Content
ts;
}

11. Immediately below the code


c you just added, add th
he following ccode:

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 Creatingg Classes and Impleementing Type-Safe Collections

Crreating Sttatic Classe


es and Me
embers

In some cases, yyou may wantt to create a class purely to encapsulate some useful ffunctionality, rather
r than
to represent an instance of anything. For e example, supp pose you wantted to create a set of methods that
convert imperiaal weights and d measures to metric weigh hts and measu ures, and vice versa. It would not make
sennse if you had ese methods, because you do not need to store or
d to instantiate a class in orrder to use the
rettrieve any insttance-specificc data. In fact, the concept o
of an instance
e is meaningleess in this case
e.

In scenarios like
e this, you can
n create a statiic class. A stattic class is a class that canno
ot be instantiaated. To
cre
eate a static class, you use the
t static keyyword. Any me embers within n the class muust also use th
he static
keyyword, as shoown in the folllowing 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 cclass, you call the method o
on the class name itself insttead of on an instance
name, as shownn by the follow
wing example:

alling Method
Ca ds on a Staticc Class
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 Creatingg Classes and Impleementing Type-Safe Collections

Te
esting Classes

Claasses often represent self-ccontained unitts of functionaality. In manyy cases, you wiill want to test the
funnctionality of your classes in isolation be
efore you integrate them w with other classes in your ap pplications.

To
o test functionnality in isolation, you create a unit test. A unit test preesents the cod de under test with
known inputs, p performs an acction on the ccode under te est (for exampple by calling a method), an nd then
verifies that the outputs of th ed. In this wayy, the unit testt represents a contract
he operation aare as expecte
thaat your code must
m fulfill. Hoowever, whenn you change the implemen ntation of a class or metho od, the unit
tesst ensures that your code aalways returns particular ou utputs in respo onse to particular inputs.

For example, coonsider the casse where you create a simp present a custtomer. To help you
ple class to rep
tarrget your marrketing effortss, the Custom
mer class includ
des a GetAge e method thatt returns the ccurrent age
of the customerr 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 tto create a un
nit test that en
nsures the GettAge method d behaves as e expected.
As such, your teest method neeeds to instanttiate the Custtomer class, specify a date of birth, and then verify
tha
at the GetAge e method retu ect age in years. Depending
urns the corre g on the unit ttest framework you use,
your test metho od might lookk something like the followiing:
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 Creatingg Classes and Impleementing Type-Safe Collections

Lesson 2
Definiing and
d Imple
ementin
ng Interrfaces

An
n interface is a little bit like a class withou
ut an impleme entation. It sp
pecifies a set o
of characteristtics and
be
ehaviors by de efining signatu ures for methoods, propertie d indexers, witthout specifyiing how
es, events, and
any of these me embers are im mplemented. W When a class implements an n interface, th
he class providdes 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 provvide the functionality speciffied by the intterface.

In this lesson, yo
ou will learn h
how to define and impleme
ent interfaces..

Le
esson Obje
ectives
Aftter completing this lesson, you will be ab
ble to:

Explain the purpose of in


nterfaces in Viisual C#.

Create interrfaces.
Create classses that imple
ement a single
e interface.

Create classses that imple


ement multiple interfaces.

Implement the IComparrable interface


e.
Implement the IComparrer interface.
Programming in
i Visual C# 4-19
9

I
Introducin
ng Interfa
aces

IIn Visual C#, aan interface sp o characteristics and behaviors; it does this by definin
pecifies a set of ng methods,
p
properties, evvents, and inde exers. The inteerface itself does not speciffy how these members are
i
implemented . Instead, classses can implemment the inte erface and proovide their owwn 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 functionaality through specific members, even
t
though the acctual impleme entation is nott part of the ccontract.
FFor example, suppose that you want to develop
d eme for Fourth Coffee. You might start
a loyalty card sche
b creating an
by n interface named ILoyalty
yCardHolder that defines:

A read-o
only integer property name
ed TotalPointts.
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 interfacce that define
es one read-only property aand 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 naames should b
begin with an "I".

Notice that th
N he methods in n the interface
e do not include method bo odies. Similarlly, the properrties in the
i
interface indiccate which accessors to include but do not
n provide an ny implementtation details. The interface e
s
simply states tthat any implementing classs must includ de and providde an impleme entation for th he three
m
members. Thee creator of th
he implementing class can choose how tthe methods aare 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 transactionn) and return an integer (thhe 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 IInterfacess

T syntax forr defining an interface is sim


The milar to the syyntax 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.
}

SSimilar to a class declaratio


on, an interfacce declaration can include aan access mod
difier. You can
n use the
f
following acceess modifiers in your interfaace declaratio
ons:

Access modifier Description

public The interfa


ace is availablle to code run
nning in any aassembly.

internal The interfaace is availablle to any code


e within the saame assemblyy, but not
available tto code in anoother assemblly. This is the d
default value if you do nott
specify an access modiffier.

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 detaails.
I
Interfaces can
n include methhods, properties, events, an
nd indexers:

To define
e a method, yo
ou specify the
e name of the
e method, the return type, aand any param
meters:

int Get
tServingTemperature(bool
l includesMilk);

To define
e a property, yyou 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 namee 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 claass that imple


T ements an inte dd a colon followed by the name of the interface to
erface, you ad
y
your class decclaration.

T following example sho


The ows how to cre
eate a class th
hat implementts 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. Yoour class can
i
include additiional memberrs that are nott defined by tthe interface. In fact, most cclasses will incclude
a
additional meembers, becauuse generally tthe class extennds the interfaace. Howeverr, you cannot o omit any
i
interface memmbers from thhe implementiing class. The way you implement the interface memb bers does not
m
matter, as lon
ng as your imp
plementationss have the sam me signatures (that is, the same names, ttypes, return
t
types, and parameters) as tthe member definitions
d in tthe interface.
T following example sho
The ass that implements the interface:
ows a trivial interface, togetther with a cla

I
Implementin
ng an Interfacce
public inteerface IBeve
erage
{
int GetSServingTempe
erature(bool includesMil
lk);
bool IsFFairTrade { get; set; }
}
public classs Coffee : IBeverage
{
private int servinggTempWithoutMilk { get; set; }
private int servinggTempWithMilk { get; set
t; }
public iint GetServingTemperature(bool incl
ludesMilk)
{
if(inncludesMilk)
)
{
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 Multtiple Interrfaces

IIn many casess, you will wan


nt to create classes that imp
plement more
e than one intterface. For exxample, you
m
might want to
o:

nt the IDisposable interfacce to enable the .NET runtime to dispose


Implemen e of your classs correctly.

Implemen
nt the IComp
parable interfaace to enable collection claasses to sort in
nstances of yo
our class.

Implemen
nt your own custom
c interfaace to define tthe functionality of your claass.

To implementt multiple inte


T erfaces, you ad
dd a comma--separated listt of the interfaaces that you want to
i
implement to your class de
eclaration. You
ur class must implement evvery member of every interrface you add
t your class d
to declaration.

T following example sho


The ows how to cre
eate a class th
hat implementts multiple intterfaces:

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 implementts an interface e, you can cho oose whether to implementt the
i
interface impllicitly or expliccitly. To imple
ement an inte
erface implicitlly, you implemment each interface
m
member with a signature that matches tthe member definition
d in th
he interface. T
To implementt an interface
e
explicitly, you fully qualify each
e memberr name so that it is clear thaat the membe er belongs to a particular
i
interface.

T following example sho


The ows an explicitt implementattion of the IBeverage interrface:
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 IComparaable Interfface

The .NET Fram


T mework includ des various coollection classe
es that enable
e you to sort tthe contents o
of the
c
collection. The
ese classes, su
uch as the ArrrayList class, include a method named S Sort. When yo ou call this
m
method on ann ArrayList innstance, the co
ollection ordeers its contents.
How does the
H e ArrayList instance know h how items in the collection n should be orrdered? In the e case of
s
simple types, such as integeers, this appeaars fairly straig
ghtforward. In
ntuitively, thre
ee follows twoo and two
f
follows one. HHowever, supp pose you creaate a collection n of Coffee o
objects. How would
w the ArrrayList
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 provvide the ArrayyList instance with logic thaat enables it to compare on ne coffee with
h
a
another. To do this, the Cooffee class muust implementt the IComparrable interfacce.
T following example sho
The ows the IComp
parable interfface:

T IComparrable Interfacce
The
public inte
erface IComp
parable
{
int Comp
pareTo(Objec
ct obj);
}

As you can se
A ee, the IComp parable interfaace declares a single metho
od named Co
ompareTo.
I
Implementatioons of this meethod must:

Compare the current object


o instance with anothe he same type (the argumen
er object of th nt).

Return an
n integer value that indicates whether th he current object instance sshould be placced before, in
n
the same position, or aafter the passe
ed-in object in
nstance.

T integer vaalues returned


The d by the Com
mpareTo meth
hod are interp
preted as follo
ows:

Less than zero indicate


es that the currrent object in
nstance precedes the suppllied instance in the sort
order.

Zero indiccates that the


e current object instance occcurs at the sa
ame position as
a the supplie
ed instance in
the sort o
order.

More than zero indicattes 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 Interfacce

When you calll the Sort me


W ethod on an A ArrayList instaance, the Arra
ayList sorts th
he collection b
based on the
I
IComparable e interface imp plementation in the underlying type. For example, if yyou sort an ArrrayList
c
collection of integers, the ssort criteria is defined by th
he IComparab ble interface implementatio on in the
I
Int32 type. Thhe creator of tthe ArrayListt instance has no control ovver the criteriaa that are use
ed to sort the
c
collection.

m want to ssort instances of your class using alternaative sort criteria. For
IIn some casess, developers may
e
example, supppose you wan nt to sort a collection of Coffee instances by the valuee of the AveraageRating
p
property rathe ariety properrty. To sort an ArrayList insstance by usin
er than the Va ng custom sorrt criteria, you
u
n
need to do tw
wo things:
1
1. Create a cclass that imp
plements the IIComparer in
nterface to pro
ovide your cusstom sort functionality.

2
2. Call the S
Sort method o on the ArrayL
List instance, aand pass in an
n instance of yyour ICompa
arer
implemen ntation as a parameter.

T following example sho


The ows the IComp
parer interfacce:

T IComparrer Interface
The
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 tyype.

Return an
n integer value that indicates whether th he current object instance sshould be placced before, in
n
the same position, or aafter 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
Implementiing Typ
pe-Safe Collecttions

Almost every application th


A hat you create e will use colle
ection classes in one form oor another. In most cases,
c
collections co
ontain a set of objects of the
e same type. W When you intteract with a ccollection, youu often rely
o the collecttion to provide objects of a specific type. Historically, this created vvarious challen
on nges. You hadd
t create exce
to eption handlinng logic in casse a collectionn contained items of the wrrong type. You also had to
b value types in order to
box o add them to collection claasses, and unb box them on retrieval.
r Visuaal C#
r
removes many of these chaallenges by ussing generics

IIn this lesson, you will learn


n how to creatte and use ge
eneric classes tto create strongly typed co
ollections of
a type.
any

L
Lesson Ob
bjectives
A
After completting this lesson, you will be able to:
Describe generics.

Identify the advantage


es of generic cclasses over no
on-generic cla
asses.

Apply con
nstraints to tyype parameterrs.
Use gene
eric list collections.

Use gene
eric dictionary collections.

Create cu
ustom genericc collections.
Create en
numerable generic collectio
ons.
4-32 Creatingg Classes and Impleementing Type-Safe Collections

In
ntroducing
g Genericss

Geenerics enable e you to create e and use stro


ongly typed coollections that are type safe
e, do not requuire you to
casst items, and ddo not require you to box and unbox vaalue types. Ge eneric classes work
w by including a type
parameter, T, inn the class or interface decla aration. You d
do not need too specify the type of T until you
insstantiate the cclass. To create a generic class, you need
d to:

Add the typ


pe parameter T in angle braackets after th
he class name
e.

Use the typ


pe parameter T in place of ttype names in
n your class m
members.
The following exxample showss how to creatte a generic cclass:

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.
}
}

Whhen you creatte an instancee of your gene


eric class, you specify the tyype you want to supply as a type
parameter. For e
example, if yoou want to use
e your custom m list to store objects of typ
pe Coffee, you
u would
sup
pply Coffee aas the type paarameter.

The following exxample showss 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 Creatingg Classes and Impleementing Type-Safe Collections

Ad
dvantagess of Generics

The use of gene


eric classes, paarticularly for collections, offfers three maain advantage
es over non-generic
ap
pproaches: typ
pe safety, no casting,
c and no boxing and unboxing.

Ty
ype Safety
Coonsider an exa
ample where yyou use an ArrrayList to sto ore a collectio
on of Coffee o objects. You can add
ob
bjects of any tyype to an ArrrayList. Suppo
ose a developer adds an ob bject of type TTea to the collection. The
code will build w
without comp plaint. Howeve er, a runtime e
exception willl occur if the Sort
S method is called,
be
ecause the collection is unable to compare objects of different type es. Furthermorre, when you retrieve an
bject from the collection, yo
ob ou must cast tthe object to the
t correct type. If you atte empt to cast tthe object
to the wrong type, an invalid cast runtime exception will occur.
The following exxample showss the type safe
ety limitationss of the Array
yList approach:

Ty
ype Safety Lim
mitations forr Non-Generiic Collectionss
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 ccollection of CCoffee
ob
bjects. When you
y instantiate e the list, you provide a typ
pe argument o of Coffee. In tthis case, your list is
gu
uaranteed to b be homogeno ous, because your
y code will not build if yyou attempt to o add an obje ect of any
oth
her type. The Sort method will work beccause 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 caast exceptionss.

The following exxample showss an alternativve 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 Creatingg Classes and Impleementing Type-Safe Collections

Co
onstrainin
ng Genericcs

In some cases, yyou may need d to restrict the types that developers
d cann supply as arrguments whe en they
insstantiate yourr generic class. The nature o pend on the logic you implement in
of these consttraints will dep
your generic cla ass. For exampple, if a collecttion class usess a property named
n Averag geRating to sort
s the
ite
ems in a collecction, you wou uld need to co onstrain the tyype paramete er to classes th
hat include th
he
AvverageRating g property. Suppose the Av verageRating g property is ddefined by the e IBeverage innterface. To
implement this restriction, yo ou would consstrain the type e parameter tto classes thatt implement the
IBeeverage interrface by using g the where kkeyword.

The following exxample showss how to consstrain a type parameter


p to classes
c that im
mplement a paarticular
intterface:

Co
onstraining T
Type Parametters by Interfface
p
public class CustomList<
<T> where T : IBeverage
{
}

Yo
ou can apply the following ssix types of co
onstraint to tyype parameters:

C
Constraint Description

w
where T : <naame of interface> Th
he type argum
ment must be, or implement, the specifie
ed interface.

w
where T : <naame of base cllass> Th
he type argum
ment must be, or derive from
m, the specifie
ed class.

w
where T:U Th
he type argum
ment must be, or derive from
m, the supplie
ed type
arg
gument U.

w
where T : new
w() Th
he type argum
ment must havve a public de
efault construcctor.

w
where T : struct Th
he type argum
ment must be a value type.

w
where T : classs Th
he type argum
ment must be a reference tyype.

Yo
ou can also ap
pply multiple cconstraints to the same classs, 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 Creatingg Classes and Impleementing Type-Safe Collections

Ussing Gene
eric List Co
ollections

Onne of the most common an nd important usesu of generics is in collecction classes. Generic
G collections fall
intto two broad categories: ge eneric list collections and g
generic diction nary collectionns. A generic list stores a
collection of objjects of type T.
T

Th
he List<T> Class
The List<T> claass provides a strongly-type
ed alternative
e to the Array e the ArrayList class, the
yList class. Like
Lisst<T> class in
ncludes metho
ods to:
Add an item
m.

Remove an item.

Insert an ite
em at a speciffied index.
ng the defaultt comparer orr a specified comparer.
Sort the items in the collection by usin

Reorder all or part of the


e collection.

The following exxample showss how to use the


t List<T> cclass.

Ussing the List<


<T> Class
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 Creatingg Classes and Impleementing Type-Safe Collections

Ussing Gene
eric Dictio
onary Colle
ections

Dicctionary classe
es store collecctions of key value
v pairs. Th
he value is the
e object you w want to store, and the
keyy is the objectt you use to in
ndex and retrrieve the value e. For example e, you might u use a dictionaary class to
sto
ore coffee recipes, where th he key is the name
n of the co
offee and the e value is the rrecipe for thatt coffee. In
the
e case of gene eric dictionariies, both the kkey and the vaalue are stronngly typed.

Th
he Dictiona
ary<TKey, T
TValue> Cla
ass
The Dictionary<TKey, TValu ue> class provides a generral purpose, sttrongly typed dictionary claass. You can
add duplicate vaalues to the ccollection, butt the keys musst be unique. The class will throw an
ArrgumentExce eption if you attempt
a to ad
dd a key that aalready exists in the diction
nary.

The following exxample showss how to use the


t Dictionarry<TKey, TVa
alue> class:

Ussing the Dictiionary<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 keey 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 indexxer.
/
// 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 {00}", 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 Creatingg Classes and Impleementing Type-Safe Collections

Ussing Colle
ection Inte
erfaces

The System.Collections.Gen neric namespa ace provides a range of generic collectio


ons to suit varrious
sce
enarios. Howe ever, there willl be circumsta ances when you will want tto create yourr own genericc collection
cla
asses in order to provide more specialize ed functionalitty. For example, you mightt want to storee data in a
ee structure or create a circcular linked list.
tre

Wh here should yyou start when n you want to create a custtom collection n class? All colllections have
e certain
thiings in common. For example, you will tyypically want to be able to enumerate th he items in thhe collection
byy using a forea ach loop, andd you will need
d methods to o add items, reemove items, and clear the list. The
piccture on the slide
s shows that the .NET Frramework pro ovides a hierarrchical set of iinterfaces that define the
characteristics aand behaviors of collectionss. These interffaces build on
n one anotherr to define pro ogressively
mo ore specific fu
unctionality.

Th
he IEnumerrable and IE
Enumerable
e<T> Interffaces
If yyou want to b
be able to use a foreach looop to enumerrate over the items in your custom geneeric
collection, you m
must impleme ent the IEnummerable<T> interface.
i The IEnumerable e<T> methodd defines a
sin
ngle method n named GetEn numerator(). T This method must return an object of tyype IEnumeraator<T>.
The foreach sta atement reliess on this enum
merator objectt to iterate thrrough the collection.

The IEnumerab ble<T> interfaace inherits fro


om the IEnum merable interrface, which allso defines a ssingle
meethod named GetEnumera ator(). When an interface in nherits from aanother interfface, it expose
es all the
meembers of the
e parent interfface. In other words, if you implement IEEnumerable< <T>, you also need to
implement IEnuumerable.

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
intterface inheritts from IEnum
merable<T>, which means that if you waant to implem ment ICollectiion<T>,
you must also im mplement thee members de efined by IEnuumerable<T> > and IEnume erable.
Programming in Visual C# 4-43

The ICollection<T> interface defines the following methods:

Name Description

Add Adds an item of type T to the collection.

Clear Removes all items from the collection.

Contains Indicates whether the collection contains a specific value.

CopyTo Copies the items in the collection to an array.

Remove Removes a specific object from the collection.

The ICollection<T> interface defines the following properties:

Name Description

Count Gets the number of items in the collection.

IsReadOnly 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 Description

Insert Inserts an item into the collection at the specified index.

RemoveAt Removes the item at the specified index from the collection.

The IList<T> interface defines the following properties:

Name Description

IndexOf 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 Description

Add Adds an item with the specified key and value to the collection.

ContainsKey Indicates whether the collection includes a key-value pair with the specified
key.

GetEnumerator Returns an enumerator of KeyValuePair<TKey, TValue> objects.

Remove Removes the item with the specified key from the collection.

TryGetValue 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 Description

Item 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.

Keys Returns the keys in the collection as an ICollection<T> instance.

Values Returns the values in the collection as an ICollection<T> instance.

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 Collecttions

To enumerate
T e over a collecction, 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 collectiion. The forea
ach statementt masks some e
o the comple
of exities of enum
meration. For the foreach statement
s to wwork, a generric collection class
c must
i
implement the IEnumerab ble<T> interfaace. This interrface exposes a method, Ge etEnumerato or, which mustt
r
return an IEnuumerator<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 De
escription

MoveNext Ad
dvanced the e
enumerator to
o the next item
m in the collection.

Reset 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 Descrription

Current Gets the item that the enumerator is pointing


g to.

An enumerato
A or is essentiallly a pointer to
o the items in the collection
n. The starting
g point for the
e pointer is
b
before the firsst item. When n you call the MoveNext method,
m the po
ointer advancces to the nextt element in
t collection. The MoveN
the Next method rreturns true iff the enumeraator 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 tto 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 fiirst item in the
e collection.

In what o
order the enum
merator shoulld move throu
ugh the itemss in the collecttion.
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 Creatingg Classes and Impleementing Type-Safe Collections

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

In this demonstration, you wiill learn aboutt the tasks thaat you will perrform in the laab for this mo
odule.
Programming in
i Visual C# 4-49
9

Lab: Addingg Data Validat


V tion and
d Type--Safety
y to the
Appllication
n

S
Scenario
Now that the user interface
N e navigation ffeatures are w
working, you ddecide to repla
ace the simple
e structs with
c
classes to makke your appliccation more eefficient and sttraightforward
d.

You have also


Y o been asked to t include validation logic in the applicaation to ensure e that when a user adds
g
grades to a sttudent, that th
he data is valid
d before it is written
w to the
e database. Yo ou decide to ccreate a unit
t
test project th
hat will perforrm tests against the require ed validation ffor different g
grade scenarioos.

Teachers who
T o have seen th
he application have expresssed concern th
hat the studen
nts in their claasses 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 alphabeticaal order.
in

FFinally, you haave been aske


ed to add funcctionality 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 completting this lab, you
y will be able to:
Create claasses.

Write datta validation code


c and unit tests.

Implemen
nt the IComp
parable interfaace.
Use gene
eric collectionss.

E
Estimated Tim
me: 60 minutes

3A-SEA-DEV11-04, MSL-TM
Virtual Machine: 20483 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 write-
only, 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. Start the MSL-TNG1 virtual machine if it is not already running.

2. Start the 20483A-SEA-DEV11-04 virtual machine and log on as Student with the password
Pa$$w0rd.

3. Start Visual Studio and open the GradesPrototype.sln solution from the
E:\Labfiles\Starter\Exercise 1 folder.
4. In the Data folder, in Grade.cs, convert the Grade struct into a class.

5. Define a class constructor that takes the following parameters and uses them to populate the public
properties of the class:
o studentID

o assessmentDate

o subject
o assessment

o comments

6. Define a default class constructor that takes no parameters and assigns the following default values to
the public properties:

o Student ID: 0

o AssessmentDate: the current date


o SubjectName: Math

o Assessment: A

o 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. Create a write-only password property that generates a new GUID for the default value.

3. 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 studentID
o userName

o password

o firstName
o lastName

o teacherID

5. Define a default class constructor that takes no parameters and assigns the following default values to
the public properties:

o Student ID: 0

o UserName: an empty string


o Password: an empty string

o FirstName: an empty string

o LastName: an empty string

o TeacherID: an empty string

6. Convert the Teachers struct into a class.

7. 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.

8. Define a class constructor that takes the following parameters and uses them to populate the public
properties of the class:

o teacherID

o userName

o password

o firstName

o lastName
o className

9. Define a default class constructor that takes no parameters and assigns the following default values to
the public properties:
o TeacherID: 0

o UserName: an empty string


4-52 Creating Classes and Implementing Type-Safe Collections

o Password: an empty string

o FirstName: an empty string


o LastName: an empty string

o Class: an empty string

X Task 3: Use the VerifyPassword method to verify the password when a user logs in
1. 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.

2. Modify the code to check whether teacher is null before examining the UserName property.

3. In the Student class, modify the code in the Logon_Click method to use the VerifyPassword
method to verify the students password.

4. 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. Build the solution and resolve any compilation errors.
2. Log in as vallee with a password of password.

3. Verify that you can log on as a teacher.

4. Log off from the application.

5. Log in as grubere with a password of password.

6. Verify that you can log on as a student.

7. Close the application.

8. 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. In Visual Studio, from the E:\Labfiles\Starter\Exercise 2 folder, open the GradesPrototype.sln
solution.

2. In the Data folder, in the DataSource class, define a generic List collection to hold the names of valid
subjects.

3. In the CreateData method in that class, populate the list with the following subject names:
o Math

o English

o History
o Geography

o Science

X Task 2: Add validation logic to the Grade class to check the data entered by the user
1. 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.

2. 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.

3. 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. Add a Unit Test Project called GradesTest to the solution and reference the GradesPrototype
project from it.
2. 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

3. Build the solution and resolve any compilation errors.

4. Run all tests and verify that they all pass.


5. 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. In Visual Studio, from the E:\Labfiles\Starter\Exercise 3 folder, open the GradesPrototype.sln
solution.
2. Build the solution and resolve any compilation errors.

3. Log in as vallee with a password of password. Verify that the students are not displayed in any
specific order.
4. Close the application.

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


students
1. In the Grade.cs code window, locate the Student class definition, and modify it to implement the
IComparable<Student> interface.
2. 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. In the Data folder, in the DataSource.cs code, in the DataSource class, modify the Students
ArrayList collection to be a generic List collection.

2. 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. Build the solution and resolve any compilation errors.

2. Run the application without debugging.

3. Log in as vallee with a password of password.

4. Verify that the students are displayed in order of ascending last name.

5. Close the application.

6. 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. In Visual Studio, from the E:\Labfiles\Starter\Exercise 4 folder, open the GradesPrototype.sln
solution.

2. In the Data folder, in the DataSource.cs code, change the Teachers collection to be a generic List
collection.

3. Change the Grades collection to be a generic List collection.

4. In the CreateData method, modify the creation of the Teachers collection to create a new generic
List collection.

5. 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. 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.

2. In the Teacher class, add code to the RemoveFromClass method as follows:


4-58 Creating Classes and Implementing Type-Safe Collections

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.

3. 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. 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.

2. 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.

3. 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. Build the solution and resolve any compilation errors.
2. Log in as vallee with a password of password.

3. Add a student with the following details:

First name: Darren


Last name: Parker

Password: password

4. Verify that Darren Parker is added to the student list.


5. Remove the student Kevin Liu from the student list.

6. For the student Darren Parker, add a new grade by using the following information:

Date: current date


Subject: English

Assessment: B

Comments: Good

7. Verify that the grade information is added to the Report Card.

8. 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, interfacces, and generic collectionss in Visual C#..

T
Test Your Kno
owledge

Question

Which of the following types


t is a refe
erence type?

Select the correct answerr.

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 interfaace?

Select the correct answerr.

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 5-2

Lesson 1: Creating Class Hierarchies 5-3

Lesson 2: Extending .NET Framework Classes 5-17


Lab: Refactoring Common Functionality into the User Class 5-29

Module Review and Takeaways 5-37


5-2 Creating a Class Hierarchy byy Using Inheritance

Modu
ule Ove
erview

The concept of inheritance iss central to obbject-oriented programmin ng in any language. It is alsoo one of
the
e most powerrful tools in yoour developerr toolbox. Esseentially, inheriitance enabless you to creatte new
cla
asses by inheriting characteeristics and be
ehaviors from existing classes. When you u inherit from an existing
cla
ass and add so ome functionaality of your o
own, your classs becomes a more specializzed instance of o the
existing class. Not only does this save you time by reduccing the amount of code yyou need to w write, it also
enables you to create
c hierarcchies of related
d classes that you can thenn use interchangeably, depe ending on
your requirements.
In this module, yyou will learn how to use in
nheritance to create class hierarchies
h and
d to extend .N
NET
Fraamework typees.

Ob
bjectives
Aftter completing this module
e, you will be able to:

e classes and d
Create base derived classe
es by using inh
heritance.

Create classses that inheriit from .NET Framework


F claasses.
Programmingg in Visual C# 5-3
3

Lesson 1
Creatting Cla
ass Hierarchie
es

Rather than creating new classes


R c from nothing, in maany cases you can use an exxisting class ass a base for
y
your wn as inheritance. Your classs inherits all the
new classs. This is know t members from the base class, and
y simply incclude the funcctionality thatt you want to add to the ba
you pabilities. This way, your
ase classs cap
c
class becomess a more speccialized version of the base class. This concept of inheritance is one e of the main
p
pillars ect-oriented programming.
of obje

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 completting this lesson, you will be able to:

Describe inheritance.

Create baase classes.


Create baase class mem
mbers.

Create claasses 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 byy Using Inheritance

W
What Is Inh
heritance??

In Visual C#, a class


c can inherrit from anoth en you create a class that in
her class. Whe nherits from an
nother
cla
ass, your class is known as tthe derived cla
ass and the claass that you in
nherit from is known as thee base class.
The derived classs inherits all the
t members of the base class, including g constructorss, methods, prroperties,
fields, and events.

Inhheritance enables you to buuild hierarchie


es of progresssively more sp
pecialized classses. Rather th
han creating
a cclass from notthing, you can
n inherit from a more general base class to provide a starting pointt for your
funnctionality.

ou define a claass named Beverage, as shown below:


For example, yo

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;
}
}

Noow you want tto create a claass to represent coffees. Co


offee is a type of beverage. It shares all thhe
characteristics aand 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
he Beverage class.
c The deriived class inhe
erits all the m
members of
the
e Beverage claass, 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 needd to add mem mbers that
are
e specific to coffees.

The following exxample showss how to creatte 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 byy Using Inheritance

Crreating Baase Classes

Whhen you creatte a class, you should consider whether yyou or other d
developers will need to use e it as a
base for derived
d classes. You have full conttrol over whether, and how
w, your class can be inherite
ed.

Ab
bstract Classses and Members
As part of an ob d design, you may want to ccreate classes that serve so
bject-oriented olely as base classes for
oth
her types. The
e base class m
may contain missing or inco omplete functiionality, and yyou may not wwant to
enable code to instantiate yo
our class directly. In these sccenarios, you can add the aabstract keyw
word to
your class declaration.

The following exxample showss how to declaare an abstracct class:

De
eclaring an A
Abstract Classs
a
abstract clas
ss Beverage
{
}

The abstract keeyword indicates that the class cannot bee instantiated directly; it exxists solely to d
define or
implement mem mbers for derived classes. Iff you attempt to instantiate
e an abstract class
c you will get an
errror when you build your co
ode.

Ann abstract classs can contain both abstract and non-abstract membe ers. Abstract m
members are aalso
de
eclared with th he abstract ke eyword and aare conceptually similar to iinterface memmbers, in that abstract
meembers define e the signaturre of the mem
mber but do no ot provide any implementaation details. Any
A class
tha provide an implementation
at inherits from the abstracct class must p n for the abstrract members.. Non-
ab
bstract membe ers, however, can be used ddirectly by derived classes.

The following exxample illustrrates the difference betwee


en abstract and non-abstracct members:

bstract and N
Ab Non-Abstractt Members
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 byy Using Inheritance

Crreating Baase Class Members


M

Yo
ou may want tto implement a method in yyour base class, but allow d derived classe
es to replace your
y
me ethod implem mentation with h more specifiic functionalitty. To create a member that developers ccan
ovverride in a de
erived class, yo
ou use the virrtual keywordd.
The following exxample showss how to creatte a virtual method in a cla
ass:

dding Virtuall 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;
}
}

Whhen you creatte a class, you can use acceess modifiers tto control whe
ether the mem mbers of yourr class are
acccessible to de
erived types. Y
You can use th
he following aaccess modifieers for class m
members:

A
Access Modifiier Detaails

p
public The member is avvailable to code running in
n any assemblyy.

p
protected The member is avvailable only within
w the con
ntaining class or in classes d
derived
m the containing class.
from

i
internal The member is avvailable only tto code within
n the current assembly.

p
protected inte
ernal The member is avvailable to any code within n the current aassembly, and
d to types
deriived from the containing cllass in any asssembly.

p
private The member is avvailable 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 Creatingg a Class Hierarchy by Using Inheritancce

In
nheriting from
f a Basse Class

To
o inherit from another class, you add a co
olon followed
d by the name
e of the base cclass to your cclass
de
eclaration.

The following exxample showss how to inhe


erit from a basse class:

De
eclaring a Cla
ass that Inherrits From a B
Base Class
p
public class Coffee : Be
everage
{
}

The derived classs inherits eve


ery member frrom the base class. Within yyour derived class, you can
n add new
meembers to exttend the functtionality of the base type.

A class
c can onlyy inherit from one base classs. However, yyour 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 memberr works in you
ur derived classs.

For example, the Beverage base


b class includes a metho
od named GettServingTemperature:

dding Virtuall 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 GetSerrvingTemperrature is a virttual method, you y can overrride it in a derrived class. To
o override a
virrtual method iin a derived cclass, you create a method w
with the same
e signature annd prefix it witth the
ovverride keyworrd.

The following exxample showss how to overrride 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 Baase Class C
Constructo
ors and Members
M

You can use the base keyw


Y word to accesss base class methods
m onstructors frrom within a d
and co derived class.
T is useful in
This i the followin
ng scenarios:

You overrride a base cla


ass method, b nality in the base class
but you still want to execute the function
method in addition to your own add ditional functionality.

You creatte a new meth


hod, but you want
w to call a base class me
ethod as part of your meth
hod logic.

You creatte a constructor and you w


want to call a base
b class constructor as paart of your inittialization
logic.

You wantt to call a base


e class method from a prop
perty accessorr.

C
Calling Basse Class Con
nstructors ffrom a Deriived Class
You cannot ovverride constrructors in deriived classes. In
Y nstead, when you create co onstructors in a derived
c
class, your connstructors will automaticallly call the defaault base class constructor before they e
execute any
o the logic th
of hat you have added.
a Howevver, in some ccircumstancess, you might w want your con nstructors to
c an alternaative base classs constructorr. In these case
call es, you can usse the base keeyword in youur constructorr
d
declarations to specify whicch base class constructor yo ou want to caall.

T following example sho


The ows how to call base class constructors:

C
Calling Base Class Constrructors
public clas
ss Beverage
{
public B
Beverage()
{
// Im
mplementatio
on details not shown.
}
public B
Beverage(strring name, bool isFairTr
rade, int se
ervingTemp)
{
// Im
mplementatioon details are not shown
n.
}
// Other
r class membbers 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: Caalling Base
e Class Co
onstructors

IIn this demonnstration, you will step through the execu ution of an ap
pplication. Thee solution includes a class
n
named Coffee that inheritss from a class named Beverage. The Coffee class inclludes two con nstructors
o that implicitly calls the
one e default base class construcctor, and one that explicitlyy calls an alternative base
c
class construcctor. The appliication creates instances off the Coffee class
c by using both of these e
c
constructors. In both cases,, you can obseerve how deriived class connstructors call base class constructors.
Y will also ssee how derivved class consttructors pass argument values to base class constructtors.
You

D
Demonstra
ation Steps
1
1. Start the MSL-TMG1 viirtual machine
e if it is not already running
g.

2
2. Start the 20483-SEA-D
DEV11-05 virtu
ual machine.
3
3. Log on to
o Windows 8 as
a Student with the passwo
ord Pa$$w0rrd.

Note: Iff necessary, click Switch Usser to display the list of use
ers.

4
4. Switch to the Windowss 8 Start men
nu.

5
5. Click Visu
ual Studio 201
12.

6
6. In Visual Studio, on the
e File menu, p n, and then click Project/Solution.
point to Open
7
7. In the Op
pen Project dialog box, bro emocode, clicck BaseConstructors.sln, and
owse to E:\De a then click
Open.

8
8. In Solutio
on Explorer, do
ouble-click Be nd review the contents of tthe class.
everage.cs an
9
9. Note thatt the Beverag
ge class contains a default constructor
c an
nd an alternattive constructtor.

1 In Solutio
10. on Explorer, do
ouble-click Co
offee.cs and review the contents of the class.

1 Note thatt the Coffee cclass inherits ffrom the Beve


11. erage class.
1 Note thatt the Coffee cclass contains a default con
12. nstructor and an alternative
e constructor.

1 Note thatt the alternative constructo


13. or explicitly caalls the alternaative constructor in the basse class.

1 In Solutio
14. on Explorer, do
ouble-click Prrogram.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 Classses

The .NET Fram


T mework contaains several thousand classe es that provide a wide rang ge of functionality. When
y create your own classe
you es, you shouldd look to build
d on these classses by inheritting from .NEET Framework
t
types whereveer possible. Not only does tthis reduce th
he amount of code you nee ed to write, it also helps to
e
ensure that yo
our classes woork in a standa
ardized way.

The .NET Fram


T mework also enables
e you to nsion methodss to add functionality to seaaled .NET
o create exten
F
Framework tyypes. This enab built-in types, such as the String class,
bles you to exxtend the funcctionality of b
w
when the inheeritance approoach is not pe
ermitted.

IIn this lesson, you will learn


n how to extend .NET Fram b using inheritance and exxtension
mework types by
m
methods.

L
Lesson Ob
bjectives
A
After completting this lesson, you will be able to:

Create claasses that inhe


erit from .NET
T Framework ttypes.

Create cu
ustom exception classes.
Throw an
nd catch custo
om exceptionss.

Create claasses that inhe


erit from gene
eric types.

Create exxtension meth


hods for .NET Framework tyypes.
5-18 Creatingg a Class Hierarchy by Using Inheritancce

In
nheriting from
f .NET
T Framewo
ork Classe
es

There are almosst 15,000 public types in the .NET Framework. Althouggh not all of tthese are extendable
cla
asses, many off them are. W
When you wantt to develop a class, in man e is a built-in .NET
ny cases there
Fraamework classs that can pro
ovide a foundaation for yourr code.
There are two kkey advantage es to creating a class that in
nherits from a .NET Framew
work class, rath
her than
de
eveloping a claass from scrattch:

Reduced development time. By inhe eriting from an existing classs, you reduce
e the amount of logic
that you haave to create yyourself.

Standardizzed functiona ality. Just like implementing an interface e, inheriting frrom a standarrd base
class meanss that your claass will work in n a standardizzed way. You can also repre esent instancees of your
class as insttances of the base
b class, wh
hich makes it easier
e for developers to use e your class allongside
other typess that derive frrom the same e base class.

The rules of inheritance applyy to built-in .N


NET Framewo
ork classes in tthe same way they apply to
o custom
cla
asses:

You can creeate a class that derives from a .NET Fram


mework class, providing thaat the class is not sealed
or static.
erride any basse class memb
You can ove bers that are marked
m as virrtual.

If you inherrit from an abstract class, yo


ou must provide implemen
ntations for all abstract mem
mbers.

Wh hen you creatte a class, sele


ect a base classs that minimizes the amou unt of coding and customizzation
req
quired. If you find yourself replicating fuunctionality th
hat is available
e in built-in classes, you sho
ould
proobably choose a more speccific base class. On the othe er hand, if you
u find that you need to ove erride
sevveral memberrs, you should d probably cho oose a more ggeneral 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 classs must
enable you to re emove duplicate items from m the list. Rather than creating a new listt class from nothing, you
can accomplish this by creating a class thaat inherits fromm the generic List<T> class and adding a single
me ethod to remo ove duplicate items. In adddition, you cann take advanta age of the Sort method in the
Lisst<T> class. Iff you call the Sort method,, any duplicate items will be adjacent in the collection n, which can
maake it easier to
o identify and d remove them
m.
The following exxample showss 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 Creatingg a Class Hierarchy by Using Inheritancce

Crreating Cu
ustom Excceptions

The .NET Frame


ework contains built-in exce
eption classess to represent most commo
on error condiitions. For
exaample:

If you invokke a method w


with a null arg
gument value,, and the metthod cannot h
handle null arg
gument
values, the method will throw
t an Argu umentNullExxception.

mpt to divide a numerical vvalue by zero, the runtime w


If you attem DivideByZeroException.
will throw a D

If you attem
mpt to retrieve
e an indexed item from a ccollection, and
d the index it o
outside the bo
ounds of
the collectio
on, the indexe
er will throw aan IndexOutO
OfRangeExce eption.

Note: Moost built-in excception classe


es are defined in the System
m namespace
e. For more
infformation aboout the System m namespace e, see the Systtem Namespace page at
htttp://go.microssoft.com/fwlinnk/?LinkID=26 67804.

Whhen you need d to throw excceptions in your code, you should reuse existing .NET Framework e
exception
typ
pes wherever possible. Howwever, there mmay be circum
mstances when n you want to create your o
own custom
excception typess.

W
When Should
d You Creatte a Custom
m Exception
n Type?
Yo
ou should consider creating
g a custom excception type when:
w

Existing excception types do not adequ


uately represe
ent the error ccondition you are identifyin
ng.

The exceptiion requires vvery specific re


emedial action
n that differs ffrom how you
u would handle built-in
exception tyypes.

emember that the primary purpose


Re p of exxception typess is to enable you to handlee specific erro
or
conditions in sppecific ways byy catching a specific excepttion type. The e exception type is not designed to
communicate th he precise dettails of the prooblem. All excception classees include a message prope erty for this
pu
urpose. Thereffore, you shou uld not create a custom excception class jjust to commu unicate the naature of an
errror condition. Create a custtom exception n class only if you need to handle that error condition n in a
disstinct 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. Create a class that inherits from the System.Exception class.


2. Map your class constructors to base class constructors.

3. 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 Creatingg a Class Hierarchy by Using Inheritancce

Th
hrowing aand Catching Custo
om Exceptions

Aftter you have created


c your ccustom excep
ption type, you
u can throw aand catch custtom exception
ns in the
sam
me way that yyou would thrrow and catch om exception, you use
h any other exxceptions. To tthrow a custo
the
e throw keyw word and create a new instaance of your e
exception typee.
The following co
ode shows ho
ow you can throw a custom
m exception:

hrowing a Custom Excepttion


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 excception, you u use a try/catch
h block. Reme ember that yoou should always attempt to o catch the
moost specific exxceptions first,, and the mosst general exception (typicaally System.Ex
xception) lastt.

The following exxample showss how you can


n catch a custtom exception
n:

Ca
atching a Cusstom Exceptio
on
p
public bool PayWithPointts(int costIInPoints, string cardNum
mber)
t
try
{
int totalPoints = Loy
yaltyCard.GeetBalance(cardNumber);
// Throws a LoyaltyCa
ardNotFoundEException 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 Creatingg a Class Hierarchy by Using Inheritancce

In
nheriting from
f Gene
eric Typess

Whhen you inherrit from a gen


neric class, you
u must decidee how you want to manage
e the type parameters of
the
e base class. You
Y can handlle type param meters in two w
ways:

Leave the tyype paramete


er of the base type unspeciffied.

Specify a tyype argument for the base type.

Coonsider an exa
ample where yyou want to ccreate a custom m list class thaat inherits from List<T>. If you leave
the
e type parame eter of the baase type unspe
ecified, you m
must include th he same type parameter in your class
de
eclaration.

The following exxample showss 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 Wiithout Speciffying a Type Argument
p
public class CustomList<
<T> : List<T
T>
{ }

In the above exaample, when you instantiatte the Custom


mList class and provide a tyype argumentt for T, the
sam
me type argument is applie
ed to the basee class.

Altternatively, yo
ou can specifyy a type argum
ment for the b
base type in yo
our class declaration. When
n you use
thiis approach, any
a referencess to the type pparameter in tthe base type
e are replaced with the type
e you
speecify in your cclass declaration.

The following exxample showss how to speccify a type argument for a b


base type:

heriting from
Inh m a Generic B
Base Type by
y Specifying a Type Argum
ment
p
public class CustomList : List<int>
>
{ }

In the above exaample, when you instantiatte 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 thee type parame
eter are now sstrongly
typ
ped to the Intt32 type. For example, the List.Add metthod will onlyy accept argum
ments of type Int32.

If tthe base class that you are inheriting fro


om contains m
multiple type p
parameters, yoou can specifyy type
argguments 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 Creatingg a Class Hierarchy by Using Inheritancce

Crreating Exxtension Methods


M

In most cases, iff you want to extend the fu


unctionality off a class, you u
use inheritancce to create a derived
cla
ass. However, this is not alw
ways possible. Many built-inn types are sealed to prevent inheritance e. For
exaample, you caannot create a class that exxtends the Sysstem.String type.
As an alternative e to using inh
heritance to exxtend a type, you can creatte extension mmethods. When you
cre
eate extension n methods, yo ou are creating methods th hat you can caall on a particuular type without
acttually modifyiing the underrlying type. Ann extension mmethod is a typ pe of static method. To create an
exttension metho od, you create e a static method within a static class. Th meter of the method
he first param
speecifies the typ
pe you want to o extend. By ppreceding the
e parameter w with the this kkeyword, you indicate to
the
e compiler thaat your metho od is an extennsion method to that type.
The following exxample showss how to creatte 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 importt the namespaace that contaains your exte
ension
meethod by using a using dire
ective:

xtension Method Into Sco


Brringing an Ex ope
u
using FourthE
ExtensionMet
thods;

Yo
ou can then caall the extensio
on method ass 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 Creatingg a Class Hierarchy by Using Inheritancce

Demonstration: Refaactoring C
Common Functionaality into tthe User C
Class Lab

In this demonstration, you wiill learn aboutt the tasks thaat you will perrform in the laab for this mo
odule.
Programming in
i Visual C# 5-29
9

Lab: Refacto
oring Commo
C n Functionalitty into the Use
er
Classs

S
Scenario
You have notiiced that the Student and T
Y Teacher classe
es in the Grad
des application
n contain som
me duplicated
f
functionality. To make the application m
more maintainable, you deccide to refactoor this commo
on
f
functionality tto remove the
e duplication.
You are also cconcerned abo
Y out security. T
Teachers and students all re
equire a passw
word, but it iss important to
o
m
maintain conffidentiality and at the same e time ensure that studentss (who are children) do not have to
r
remember lonng and compllex passwordss. You decide tto implementt different passsword policie es for teacherss
a students; teachers' passswords must be stronger and
and a more diffiicult to guess than student passwords.

Also, you have


A e been asked to update the e application to limit the number of studdents that can
n be added to o
a class. You de ows a custom exception if a user tries to
ecide to add ccode that thro o enroll a student in a class
t
that is alreadyy at capacity.

O
Objectives
A
After completting this lab, you
y will be able to:
Use inherritance to facttor common ffunctionality in
nto a base cla
ass.

Implemen
nt polymorph
hism by using an abstract method.
m

Create a ccustom 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. Start the MSL-TMG1 virtual machine if it is not already running.

2. Start the 20483A-SEA-DEV11-05 virtual machine and log on as Student with the password
Pa$$word.

3. Start Visual Studio and open the GradesPrototype.sln solution from the
E:\Labfiles\Starter\Exercise 1 folder.

4. In the Grade.cs file in the Data folder, create a new abstract class called User.
5. Add the UserName and Password properties to the User class.

6. 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.

2. 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.

X Task 3: Run the application and test the log on functionality


1. Build the solution and resolve any compilation errors.
2. Run the application.

3. Log on as vallee (a teacher) with a password of password.

4. Verify that a list of students for this teacher appears in The School of Fine Arts window.
Programming in Visual C# 5-31

5. Select student Kevin Liu and verify that the report card listing the grades for this student appears.

6. Log off and then log on as liuk (a student) with a password of password.
7. Verify that the report card for Kevin Liu is displayed again.

8. Log off and then close the application

9. 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. In Visual Studio, open the GradesPrototype.sln solution from the E:\Labfiles\Starter\Exercise 2
folder.

2. 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.

3. 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.

X Task 2: Implement the SetPassword method in the Student and Teacher classes
1. In the User class, make the _password field protected rather than private; it needs to be accessible in
the Student and Teacher classes.
2. 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.

3. 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.

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. In the code for the StudentsPage view, locate the NewStudent_Click method. This method runs
when a teacher creates a new student.

2. 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. Build the solution.
2. 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.
3. 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.

4. 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:

FIGURE 5.1: THE CHANGEPASSWORDDIALOG WINDOW


5. 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.

6. 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.

c. 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.

d. 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.

X Task 5: Run the application and test the change password functionality
1. Build the solution and resolve any compilation errors.

2. Run the application.


3. 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. Change the password for the current user. First try setting it to a password that is insufficiently
complex, and then change it to password101.

5. Log out and then log back in again as vallee, and verify that the password has been changed to
password101.

6. 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.

7. Log off and then close the application.


8. 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. In Visual Studio, open the GradesPrototype.sln solution from the E:\Labfiles\Starter\Exercise 3
folder.

2. 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.

3. 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.

4. Add a default public constructor to the ClassFullException class. This constructor should simply
delegate its responsibilities to the equivalent constructor in the Exception class.

5. 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.
6. 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.

7. 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.

8. 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.

X Task 2: Throw and catch the ClassFullException


1. 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.

2. 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).

3. 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
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. Build the solution and resolve any compilation errors.
2. Run the application.

3. Log on as vallee (a teacher) with a password of password99.

4. Create four new students.


5. 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.

6. Log off and then close the application.

7. 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
IIn this modulee, you have leearned 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 iin derived claasses?

Select the correct answerr.

Absttract methodss.

Prottected method
ds.

Public methods.

Static methods.

Virtu
ual methods.

T
Test Your Kno
owledge

Question

You want too create an exxtension meth hod for the Sttring class. Yo
ou create a sttatic method
within a stattic class. How
w do you indiccate that your method exttends the Striing type?

Select the correct answerr.

The return type o


of the method
d must be a Sttring.
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 6-2

Lesson 1: Reading and Writing Files 6-3

Lesson 2: Serializing and Deserializing Data 6-17


Lesson 3: Performing I/O by Using Streams 6-33

Lab: Generating the Grades Report 6-44

Module Review and Takeaways 6-50


6-2 Reading aand Writing Local D
Data

Modu
ule Ove
erview

Reeading and wrriting data are e core requirements for many application ns, such as a ttext file editorr saving a
file
e to the file syystem, or a Wiindows servicee writing erro
or messages to
o a custom log g file. The local file
sysstem providess the perfect e environment for
f an applicaation to read aand write such h data, becausse access is
fasst and the locaation is readily available. Th
he Microsoft .NET
. Framewo ork provides a variety of I/O O classes
thaat simplify the e process of im
mplementing I/O functionaality in your appplications.

In this module, yyou will learn how to read and write datta by using atomic file systeem I/O operattions, how
to serialize and deserialize daata to the file system, and h
how to read and write dataa to the file sysstem by
usiing streams.

Ob
bjectives
Aftter completing this module
e, you will be able to:
Read and w
write data to aand from the ffile system by using file I/O
O.

Convert datta into a form


mat that can be
e written to o
or read from a file or other data source.

Use streamss to send and receive data to or from a file


f or data so
ource
Programmingg in Visual C# 6-3
3

Lesson 1
Read
ding and
d Writing File
es

The .NET Fram


T mework provid des the Systeem.IO namesp pace, which co
ontains a num
mber of classess that help
s
simplify appliccations that re
equire I/O fun
nctionality.

IIn this lesson, you will learnn how to use the


t classes in this namespace to read and write data tto and from
f
files, and to manipulate
m file ories on the file system.
es and directo

L
Lesson Ob
bjectives
A
After completting this lesson, you will be able to:

d write data byy using the File class.


Read and
Manipulaate files by using the FileInffo and the Fille classes.

Manipulaate directoriess by using the DirectoryInffo and Directtory classes.

Manipulaate file and dirrectory paths by using the Path class.


6-4 Reading aand Writing Local D
Data

Re
eading an
nd Writing
g Data by Using the
e File Classs

The File class in


n the System.IO namespace e exposes sevveral static me ethods that yo
ou can use to perform
ato
omic operatio ons for direct reading and wwriting of filess. These methoods are atomic because the ey wrap
sevveral underlying functions into a single m
method call. T Typically, to re
ead data from
m a file, you:
1. e file handle.
Acquire the

2. Open a stre
eam to the file
e.

3. Buffer the d
data from the file into mem
mory.
4. Release the
e file handle so
o that it can b
be reused.

The static metho ods that the F File class expooses are conve enient becausse they encapssulate intricatte, low-level
nctions. Howe
fun ever their convenience and the fact that they shield th he developer from the underlying
fun
nctionality me eans in some cases they do ont offer the ccontrol or flexxibility that ap
pplications req
quire. For
exaample, the ReeadAllText m method will reaad the entire ccontents of a file into mem mory. For smalll files this
will be fine, but for large filess it can presen
nt scalability isssues, and maay result in an unresponsive e UI in your
ap
pplication.

Re
eading Data
a from Files
The File class prrovides severaal methods that you can usse to read dataa from a file. T
The format off your data
and how your application inttends to proce ess it will influ
uence the metthod that you should use. T
The
folllowing list de
escribes some of these methods:

The ReadA AllText metho u to read the contents of a file into a single string variable. The
od enables you
following co
ode example shows how too 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 ccode example e shows how tto read the co ontents of the settings.txt
file and store each line in
n the string arrray named se
ettingsLineBy yLine.

ilePath = "C
string fi C:\\fourthCofffee\\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.
Programmingg in Visual C# 6-7
7

M
Manipulat
ting Files

As well as reading from and


A d writing to fiiles, applicatio
ons typically re
equire the ability to interacct with files
s
stored on the file system. FFor example, your
y applicatio
on may need to copy a file e from the systtem directoryy
t a temporarry location be
to efore performiing some further processing, or your app plication mayy need to read d
s
some metadata associated with the file, such as the file creation tim me. You can immplement this type of
f
functionality b
by using the FFile and FileInnfo classes.

F Manipu
File ulation by using
u the F
File Class
The File class provides static methods th
T hat you can usse to perform basic file manipulation. Th
he following
l describes ssome of these
list e methods:

The Copy y method enaables you to co


opy an existin
ng file to a diffferent directo
ory on the file system. The
following
g code example shows how w to copy the ssettings.txt filee from the C:\\fourthCoffee\\ directory to
the C:\tem
mp\ directoryy.

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: TThe overwrite parameter pa assed to the Copy


C method call indicates that the copyy
process should overwrite an existing file if it exists at tthe destinatio
p 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 exissting file from
m the file syste
em. The follow
wing code
example shows how to
o delete the exxisting setting
gs.txt file.

string filePath = "C:\\fourthC


Coffee\\sett
tings.txt";
File.De
elete(filePath);

The Existts method enaables you to ccheck 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 existts.

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 in-
memory 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 Readingg and Writing Local Data

M
Manipulati ng Directo
ories

It iis a common requirement forf applications to interact and manipulaate the file system directorry structure,
whhether to checck that a direcctory exists be
efore writing a file or to rem
move directorries when runn
ning a
sysstem cleanup process. The .NET Framew work class libra
ary provides thhe Directory and DirectorryInfo
cla
asses for such operations.

Manipulating
g Directorie
es by using
g the Directtory Class
Sim
milar to the Fiile class, the Directory
D classs provides staatic methods tthat enable yo
ou to interactt with
dirrectories, with
hout instantiatting a directory-related objject in your co
ode. The following list desccribes some
of these static mmethods:

The CreateDirectory me
ethod enabless you to create a new direcctory on the file system. The
e following
example shows how to create the C:\ffourthCoffee\ttempData 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 speciffic path. The fo
ollowing code
e example
shows how to delete the C:\fourthCofffee\tempDataa directory, annd all its conteents.

string di
irectoryPath
h = "C:\\fourthCoffee\\t
tempData";
bool recu
ursivelyDele
eteSubContent = true;
Directory
y.Delete(dir
rectoryPath, recursively
yDeleteSubCo
ontent);

Note: The
e recursivelyDDeleteSubCo ontent parame eter passed in
nto the Deletee method calll
inddicates whether the delete process should delete any content that may exist in tthe directory. If
you pass false into the Delette method calll, and the dire
ectory is not e
empty, the CLLR will throw a
Syystem.IO.IOEx xception.

The Exists method


m enables you to dettermine if a directory existss on the file syystem. The folllowing
code examp ple shows how
w to determin
ne if the C:\fouurthCoffee\tempData direcctory 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 aand Directtory Pathss

All files and all directories h


A have a name, which when ccombined to p point to a file in a directoryy, constitute a
p
path. Differen
nt file systems can have diffferent conventions and rule es for what co onstitutes a paath. The .NET
F
Framework prrovides the Paath class, whicch encapsulattes a variety o
of file system uutility function
ns that you
c use to parse and construct valid file names, directtory names, and paths with
can hin the Windo ows file
s
system. Thesee functions cann be useful if your application needs to w write a file to a temporary location,
e
extract an element from a ffile system paath, or even ge enerate a rand dom file name.
T following code shows how to create
The e a new directtory on the root of the C: drive.

C
Creating a Te
emporary Dirrectory 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 assumpttions, includin ng whether yo
our
a
application haas the necessaary privileges to perform I/O
O at the root of the C drive
e, and whethe
er the C drive
a
actually existss.

A better way is to use the sstatic 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 maany other statiic methods th


T hat provide a good
g starting point for anyy custom I/O
t
type functionaality that your application may require. These
T method ds include thee following:

The HasEExtension me ethod enables you to determine if the paath your appliication is proccessing 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 ccheck whetherr the path hass an extension n.

string settingsPath = "..coulld 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
Directoriess, and Paths

IIn this demon y, and Path classes to build


nstration, you will use the File, Directory d a utility that combines
m
multiple files into a single ffile.

D
Demonstra
ation Steps
1
1. Start the MSL-TMG1 viirtual machine
e if it is not already running
g.

2
2. Start the 20483A-SEA-DEV11-06 virrtual machine..

3
3. Log on to
o Windows 8 as
a Student with the passwo
ord Pa$$w0rrd.

Note: Iff necessary, click Switch Usser to display the list of use
ers.

4
4. Switch to the Windowss 8 Start wind
dow.

5
5. Open File
e Explorer and
d browse to th
he E:\Democo
ode\Data\Lo
ogs folder.

6
6. In the E:\Democode\D
Data\Logs folder, double-click each of the
e text files, an
nd view the co
ontents in
Notepad..
7
7. Close NottePad.

8
8. Switch to the Windowss 8 Start wind
dow.

9
9. 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, browwse to E:\Dem er\FourthCofffee.LogProcessor folder,
mocode\Starte
click FourrthCoffee.LogProcessor.sln,, and then clicck Open.
1 In Visual Studio, on the
12. e View menu,, click Task Liist.

1 In the Tassk List windo


13. ow, in the Cate
egories list, click Commen
nts.

1 Double-cclick the TODO


14. O: 01: Ensure log file directo
ory exists. task.
1 In the cod
15. de editor, click in the blankk 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 Datta

SSerialization iss the process of converting


g data to a forrmat that can be persisted o
or transported
d.
D
Deserializatio n is the proce
ess of convertiing serialized data back to objects.

IIn this lesson, you will learn


n how to seriaalize objects to
o binary, XMLL, and JavaScriipt Object No
otation
(
(JSON), and h
how to create a custom serializer so that you can seriaalize objects in
nto any formaat you choose.

L
Lesson Ob
bjectives
A
After completting this lesson, you will be able to:

Describe the purpose o


of serialization
n, and the forrmats that the
e .NET Framew
work supportss.
Create a ccustom type tthat is serializaable.

Serialize aan object as b


binary.

Serialize aan object as X


XML.
Serialize aan object as JSON.

Create a ccustom serialiizer by implem


menting the IFormatter interface.
6-18 Readingg and Writing Local Data

W
What Is Serrialization?

Appplications typpically processs data. Data iss read into me


emory, perhap ps from a file or web service call,
proocessed, and then passed tto another component in th he system for further proce essing. The co
omponents
of a system mayy run on the same
s machine e, but commonly components run on diffferent platforrms, on
diffferent hardwaare, and evenn in different geographical
g llocations. The
e format of the data also neeeds to be
lightweight so that it can be transported o over a variety of protocols, such as HTTP or SOAP. Serrialization is
thee process of cconverting thee state of an oobject into a form that can be persisted o or transported
d.

Se
erializable F
Formats
The requiremennts of your sysstem, and how
w you intend to
t transport th
he data, will in
nfluence the serialization
s
forrmat you choo
ose. The following table de
escribes some of the comm
mon formats avvailable.

FFormat Descripttion

B
Binary Serializing data into tthe machine-readable binaary format enaables you to p preserve the
fidelity and state of aan object betwween differentt instances of your applicattion. Binary
ation is also fa
serializa ast and lightw
weight, becausse the binary fformat does n
not require the e
processing and storage of unnecessary formattiing constructss.
Binary sserialization iss commonly used when perrsisting and trransporting ob bjects betweeen
applicattions running on the same platform.
Binary EExample
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 tthe XML form mat enables yo ou to utilize an
n open standa ard that can be
b
processed by any app plication, regaardless of plattform. In conttrast to binaryy, XML does not
preserve e type fidelityy; it only lets you
y serialize ppublic membe ers that your tyype exposes.
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, data-
interchange 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 Readingg and Writing Local Data

Crreating a S
Serializable Type

The .NET Frame ework provide es many classees that are serrializable. If yo
ou want to cre
eate your ownn types that
are
e serializable, you need to e ensure that th
he type definittion incudes tthe necessary configuration n and
fun
nctionality forr the serilalize
er to consume e. The .NET Fraamework provvides the Systtem and
Sy
ystem.Runtim me.Serializatio on namespaces, which provide classes to alization support.
o enable seria

To
o create a seriaalizable type, perform the ffollowing step
ps:

1. Define a de
efault construcctor.

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 tthe System.R
Runtime.Seria
alization nam mespace.
The GetObjjectData metthod enables you to extractt the data from your objectt during the sserialization
process.

[Serializzable]
public cllass Service
eConfiguratio
on : ISerial
lizable
{
...
publicc 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 Readingg and Writing Local Data

Se
erializing O
Objects ass Binary

The .NET Frame ework provide es the BinaryF


Formatter claass in the
Sy
ystem.Runtim me.Serializatio on.Formatters.Binary nammespace, whicch you can use to serialize aand
de
eserialize objeccts as binary.

Note: The e BinaryFormmatter and SooapFormatterr classes imple ement the IFo
ormatter
intterface. You caan also implement the IForrmatter interrface 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 claass, perform the following steps:
s

1. Obtain a reference to the


e object you w
want to serialiize.

2. nstance of the
Create an in e BinaryForm
matter that yo
ou want to use
e to serialize yyour type.
3. Create a strream that you
u will use as a buffer to storre the serialize
ed data.

4. Invoke the BinaryForma atter.Serialize


e method, passsing in stream
m that the serrialized data will
w be
buffered to, and the obje
ect you want tto serialize.

The following co
ode example shows how to
o use the Bina
aryFormatterr class to seria
alize an objectt as binary.

naryFormatter Serialize E
Bin 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 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 writess the serialized d data to a filee. It is
important to noote that serialiization doesnt just imply w
writing data to
o a file. Serializzation 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. Create an instance of the BinaryFormatter that you want to use to deserialize your type.

2. Create a stream to read the serialized data.

3. Invoke the BinaryFormatter.Deserialize method, passing in stream that contains the serialized data.
4. 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 Readingg and Writing Local Data

Se
erializing O
Objects ass XML

The .NET Frame ework provide es the SoapFo


ormatter classs in the
Sy
ystem.Runtim me.Serializatioon.Formatters.Soap name espace, which
h you can use to serialize an
nd
de
eserialize objeccts as XML.

Se
erialize an Object
O by Using
U the So
oapFormattter Class
The process for serializing daata as XML is ssimilar to the process of serrializing 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 cclass to serializze an object aas XML.

So
oapFormatterr 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 Classs
The process for deserializing data from XM
ML to an objecct is identical to the processs of deserializzing 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 cclass to deseriialize XML datta to an
ob
bject.

So
oapFormatterr 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 Readingg and Writing Local Data

Se
erializing O
Objects ass JSON

The .NET Frame ework also sup


pports serializing objects ass JSON by usin
ng the DataCContractJsonS Serializer
cla
ass in the Systtem.Runtime e.Serializationn.Json namesspace. The JSOON serializatio
on steps are d
different
beecause the DataContractJssonSerializer class is derive ed from the abbstract XmlObjectSerialize er class,
and it is not an implementatiion of the IFoormatter interrface.

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 classs, perform the
e following ste
eps:
1. Obtain a reference to the
e object that yyou want to serialize.
s

2. nstance of the
Create an in e DataContra actJsonSerialiizer class thatt you want to use to serializze your
type. The co
onstructor also requires you to pass in a Type object, representing the type of o object you
want to serialize.

3. Create a strream that you


u will use as a buffer to storre the serialize
ed data.

4. Invoke the DataContracctJsonSerializzer.WriteObje ect method, p passing in stre


eam that the sserialized
data will be
e buffered too
o, and the obje
ect you want to serialize.

The following co
ode example shows how to
o use the Data
aContractJso
onSerializer class
c to serializze an
ob
bject as JSON.

Da
ataContractJssonSerializerr 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.

2. Create a stream that will read the serialized JSON into memory.

3. Invoke the DataContractJsonSerializer.ReadObject method, passing in the stream that contains the
serialized data.

4. Cast the result of the DataContractJsonSerializer.ReadObject method call into the type of object
you are expecting.

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 Readingg and Writing Local Data

Crreating a C
Custom Serializer

Yo
ou may want tto serialize datta into a form
mat other than n binary, XML,, or JSON. The
e .NET Framew work
pro
ovides the IFo
ormatter inteerface in the SSystem.Runtime.Serializattion namespa ace, so you can create
your own formaatter. Your cusstom formatte er will then fo
ollow the same
e pattern as th
he BinaryForrmatter and
So
oapFormatterr classes.

To
o create your o
own formatter, perform the
e following ste
eps:

1. Create a claass that implements the IFo


ormatter inte
erface.
2. Create impllementations for the Surro
ogateSelectorr, Binder, and
d Context pro
operties.

3. Create impllementations for the Deserrialize and Se


erialize metho
ods.

The following co
ode example shows a custo
om formatter that can seriaalize and dese
erialize objectss to the .ini
forrmat.

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[] _delimm = new char[] { '=' };
public ISurrogateS
Selector SurrrogateSelect
tor { get; s
set; }
public Serializati
ionBinder Binder { get; set; }
public StreamingCo
ontext Conteext { get; se
et; }
public IniFormatte
er()
{
this
s.Context
= new Stream
mingContext((StreamingCon
ntextStates.
.All);
}
public object Dese
erialize(Strream serializ
zationStream
m)
{
Stre
eamReader bu
uffer
= new Stream
mReader(serializationStream);
// G
Get the type
e from the sserialized 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

IIn this demon


nstration, you will serialize aand deserialize a custom tyype to XML byy using the
S
SoapFormatt ter class.

D
Demonstra
ation Steps
1
1. Switch to the Windowss 8 Start wind
dow.

2
2. Click Visu
ual Studio 201
12.

3
3. In Visual Studio, on the
e File menu, p n, and then click Project/Solution.
point to Open

4
4. In the Op
pen Project dia
alog box, browwse to E:\Dem mocode\Starte
er\FourthCofffee.ExceptionLLogger, click
FourthCooffee.Exception
nLogger.sln, aand then clickk Open.

5
5. In Visual Studio, on the
e View menu,, click Task Liist.
6
6. In the Tassk List windo
ow, in the Cate
egories list, click Commen
nts.

7
7. Double-cclick the TODO
O: 01: Decoratte the type wiith the Serializzable attribute
e. task.

8
8. In the cod
de editor, click in the blankk line below th
he comment, and then type
e the followin
ng code:

[Seriali
izable]

9
9. In the Tassk List window
w, double-click the TODO: 0
02: Implemen
nt the ISerializzable interface
e. task.

1 In the cod
10. de editor, click in the blankk line below th
he comment, and then type
e the followin
ng code:

: ISeria
alizable

1 Right-clicck the text ISe


11. erializable, poiint to Implement Interface, and then clicck Implement Interface.
1 In the Ge
12. etObjectData method, repllace the existing code to th
hrow a new
NotImple
ementedExceeption objectt with the follo
owing code:

info.Add
dValue("Titl
le", this.Title);
info.Add
dValue("Deta
ails", this.Details);

1 In the Tassk List window


13. w, double-click the TODO: 0
03: Add a desserialization 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. Title: Critical database error


b. 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 sserver
a
accessible ove
er HTTP, the ddata sometime es becomes to oo large to load into memo ory and transm mit in a single
e
a
atomic operattion. For exam
mple, imagine trying to loadd a 200-gigab byte video file
e from the file
e system into
m
memory in a single
s operatiion. Not only would the opperation take a long time, b but it would also consume
a large amoun nt of memoryy.

IIn this lesson, you will learn


n how to use streams
s to reaad from and w
write to files w
without having
g to cache
t entire file in memory.
the

L
Lesson Ob
bjectives
A
After completting this lesson, you will be able to:

Describe the purpose o


of a stream.
Describe the different types of streaams provided in the .NET Frramework.

Describe how to use a stream.


6-34 Readingg and Writing Local Data

W
What are Sttreams?

The .NET Frame ework enabless you to use sttreams. A stream is a seque ence of bytes, which could come from
a ffile on the file system, a nettwork connection, or memo ory. Streams eenable you too read from orr write to a
data source in small, manage eable data pacckets. Typically, streams pro
ovide the follo
owing operatiions:
Reading chunks of data into
i a type, su
uch as a byte array.

unks of data frrom a type to


Writing chu o a stream.

Querying th
he current position in the stream and mo
odifying a spe
ecific selection
n of bytes at tthe current
position.

Sttreaming in
n the .NET Framework
F k
The .NET Frameework provide
es several streaam classes thaat 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 exxample, binarry or alphanum
meric.

Where the d
data is stored, for example, on the local file system, in
n memory, or on a web servver over a
network.

The .NET Frame ework class lib brary provides several classees in the Systeem.IO namesspace that you u can use to
reaad and write ffiles by using streams. At thhe highest level of abstractiion, the Strea
am class definnes the
common functio onality that alll streams provide. The classs provides a ggeneric view oof a sequencee of bytes,
tog he operations and properties that all stre
gether with th eams provide.. Internally, a Stream objecct maintains
appointer that reefers to the cu
urrent locationn in the data source. When n you first con
nstruct a Strea
am object
ovver a data source, this pointter is positione
ed immediate ely before the first byte. As you read andd write data,
thee Stream classs advances th his pointer to the end of the e data that is read or writte
en.

Yo
ou cannot use the Stream cclass directly. Instead, you instantiate spe of this class that are
ecializations o
opptimized 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 implementts a stream that uses a diskk file as the daata source, and
d the MemorryStream classs
implements a sttream that usees a block of mmemory 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 thhat you can usse to read and
d write differe
ent types of
d
data from diffferent types o
of data source
es. The following table desccribes some off these stream
m classes, and
w
when you migght want to usse them.

Stream classs Descriptio


on

FileStream Enables yyou to establissh a stream to


o a file on the file system. The FileStream
m
class handdles operationns such as opeening and cloosing the file, and
a provides
access to the file through a raw sequ uence of byte es.

MemoryStre
eam Enables yyou to establissh a stream too a location in memory. The
e
MemoryS Stream class handles operaations such ass acquiring the in-memory
storage, aand provides access
a to the memory locattion through a raw sequence
of bytes.

NetworkStream Enables yyou to establissh a stream to


o a network lo
ocation in memmory. The
Network kStream class handles operrations such ass opening and d closing a
connectioon to the netwwork location, and providess access to the
e network
location tthrough a raw
w sequence of bytes.

A stream thatt is establishedd by using a F


FileStream, M MemoryStream m, or NetworrkStream objject is just a
r sequence
raw e of bytes. If th
he source dataa is structured
d, you must coonvert the bytte sequence into the
a
appropriate tyypes. This can
n be a time-coonsuming and d error-prone task. Howeve er, the .NET Fraamework
c
contains classes that you caan use to readd and write te extual data and primitive tyypes in a stream that you
h
have opened by using the FileStream, MemoryStrea
M am, or Netwo orkStream claasses. The following table
d
describes som
me of the streaam reader and d writer classees.

Stream classs Description

StreamRead
der Enables youu to read textu
ual data from
m an underlying data source
e stream, such
h as
a FileStream, MemoryS Stream, or NeetworkStream m object.

StreamWriter Enables you


u to write texttual data to an
n underlying d
data source sttream, such as a
FileStream
m, MemoryStrream, or Netw workStream object.

BinaryReade
er 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 aand Writin
ng Binary Data by U
Using Stre
eams

M
Many applicattions store daata in raw binaary form for a number of re
easons, such aas the followin
ng:

Writing b
binary data is fast.
f

Binary daata takes up le


ess space on d
disk.

Binary daata is not hum


man readable.

You can read and write datta in a binary format in you


Y ur .NET Frame
ework applicattions by using
g the
B
BinaryReade r and BinaryWWriter classess.

To read or write binary datta, you constru


T uct a BinaryRReader or Bin
naryWriter ob bject by provid
ding a stream
m
t
that is conneccted 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 aryWriter classes, passing
ader and Bina
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 havve created a BinaryReader object, you can use its members to read
A d the binary d
data. The
f
following list d me of the key members:
describes som

The Base
eStream property enables yyou to access the underlyin
ng stream thatt the BinaryR
Reader object
uses.
The Close
e method enaables you to cclose the BinaryReader objject 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 ReaddByte 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 Readingg and Writing Local Data

Re
eading an
nd Writing
g Text Datta by Using Streamss

a store data as plain textt. You may waant to do


In addition to sttoring data ass raw binary data, you can also
thiis in your application if the persisted datta needs to be
e human read
dable.

The process for reading fromm and writing plain


p text to a file is very sim
milar to reading and writin
ng binary
data, except thaat you use the
e StreamReadder and Strea amWriter classses.

Whhen you initiaalize the Strea


amReader or StreamWrite
er classes, you
u must provide a stream ob
bject to
handle the interraction with th
he data source.
The following co ode example shows how to
o initialize the
e StreamRead
der and Strea
amWriter classses,
passing a FileSttream object.

Iniitializing a SttreamReaderr and StreamWriter Objecct


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);

Aftter you have created


c a Stre
eamReader o object, you can
n use its mem
mbers to read the plain text. The
folllowing list de
escribes some of the key members:

The Close m
method enablles you to closse the Stream
mReader obje
ect and the un
nderlying strea
am.

The EndOfS
Stream prope
erty enables yyou to determ
mine whether yyou have reacched the end of the
stream.

The Peek m
method enable er in the stream, but does n
es you to get the next available characte not
consume it..
The Read m method enables you to get and consume e the next avaailable charactter in the stream. This
method retturns an int vaariable that re hich you may need to
epresents the binary of the character, wh
explicitly co
onvert.
The ReadBlock method enables you to
t read an entire block of ccharacters 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 tthat you will p
perform in the
e lab for this module.
m
6-44 Readingg and Writing Local Data

Lab: G
Generatting the
e Grade
es Repo
ort

Sccenario
Yo
ou have been asked to upgrade the Grad des Prototype application to o enable userrs to save a stuudents
gra
ades as an XMML file on the local disk. The
e user should be able to cliick a new button on the
Stu
udentProfile vview that asks the user wheere they wouldd like to save the file, displaays a preview of the data
to the user, and asks the userr 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 formatt in the locatio
on that the usser specified.

Ob
bjectives
Aftter completing this lab, you
u will be able to:

Serialize data to a memo


ory stream.

Deserialize data from a memory


m stream.

Save serializzed data to a file.

Esttimated Time:: 75 minutes

Virtual Macchine: 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. Start the MSL-TMG1 virtual machine if it is not already running.

2. Start the 20483A-SEA-DEV11-06 virtual machine and log on as Student with the password
Pa$$w0rd.
3. Start Visual Studio and from the E:\Labfiles\Starter\Exercise 1 folder, open the
GradesPrototype.sln solution.

4. 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.

5. 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.

6. Save the return value from the dialog box in a nullable Boolean variable.

7. Check if the return value from the SaveFileDialog contains data. If it does, do the following:

a. Get the grades for the currently selected student and store them in a generic list.

b. Call the FormatAsXMLStream method, passing the list of grades to it, and store the returned
data in a MemoryStream object.

X Task 2: Serialize the grade data to a memory stream


1. In StudentProfile.xaml.cs code file, locate the FormatAsXMLStream method.

2. Add code to save the XML document to a MemoryStream object by using an XmlWriter object.

3. 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. Add code to finish the XML document with the appropriate end elements.

6. Add code to flush the XmlWriter object and then close it to ensure that all the data is written to the
MemoryStream object.

7. Add code to reset the MemoryStream object so that it can be read from the start, and then return it
to the calling method.
8. Delete the line of code that throws a NotImplementedException exception.

X Task 3: Debug the application


1. Build the solution and resolve any compilation errors.

2. In the SaveReport_Click method, add a breakpoint to the closing brace of the if block.
3. Debug the application.

4. Log in as vallee with a password of password99.

5. View Kevin Lius report, and then click Save Report to generate the XML document.
6. 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. Review the grade data that is returned.


9. 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. In Visual Studio, from the E:\Labfiles\Starter\Exercise 2 folder, open the GradesPrototype.sln
solution.

2. 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.

3. 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.

X Task 2: Build a string representation of the XML document


1. In StudentProfile.xaml.cs, in the FormatXMLData method, add code to create a new StringBuilder
object used to construct the string.
2. Add code to create a new XmlTextReader object used to read the XML data from the stream.

3. 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.

4. Add code to reset the MemoryStream object and return the string containing the formatted data to
the calling method.
5. Delete the line of code that throws a NotImplementedException exception.

X Task 3: Run the application and preview the data.


1. Build the solution and resolve any compilation errors.

2. Run the application.


3. Log in as vallee with a password of password99.

4. View Kevin Lius report, and then click Save Report to generate the XML document.

5. 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. Review the XML data displayed in the message box and close the application.

7. 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. In Visual Studio, from the E:\Labfiles\Starter\Exercise 3 folder, open the GradesPrototype.sln
solution.
2. 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.

3. Modify this line of code as follows:

a. Save the return value of the MessageBox.Show method in a MessageBoxResult variable

b. Set the caption of the message box to Save Report?

c. Include Yes and No buttons in the message box.


d. Display a question mark image.

4. 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.
5. 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. Build the solution and resolve any compilation errors.

2. Run the application.


3. Log on as vallee with a password of password99.

4. View Kevin Lius report card and then click Save Report to generate the XML document.

5. Specify to save the file in the Documents folder by using the default name.
6. Review the XML data displayed in the message box, and then confirm that you want to save the file.

7. Close the application.

8. Open the saved report in Internet Explorer and verify that it contains the expected grade data.
9. 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 Readingg and Writing Local Data

Modu
ule Reviiew and
d Takea
aways

M
Module Revie
ew
In this module, yyou have learrned how to w work with the file system byy using a nummber of classess in the
Sysstem.IO nameespace, and ho ow to serialize
e application data to differrent formats.
Question: You Y are a devveloper workin ng on the Fou urth Coffee WWindows Presentation
Foundation n (WPF) client application. Y
You have been n asked to sto
ore some settiings in a plain
n
text file in tthe users tem
mporary folderr on the file syystem. Briefly explain which
h classes and
methods yo ou could use tto achieve this.

Question: YouY are a devveloper workin ng for Fourth Coffee. A bug g has been raised and you
have been asked
a to invesstigate. To help reproduce the error, you u have decide ed to add somme
logic to perrsist the state of the applicaation to disk, w
when the app plication encounters the
error. All the types in thee application aare serializable, and it woulld be advantaageous if the
persisted sttate was humaan readable. What
W approacch will you takke?
Test Your Know
wledge

Q
Question

YYou are a deve eloper workinng for Fourthh Coffee. You have been assked to write some
ccode to proceess a 100 GB vvideo file. You
ur code needs to transfer tthe file from one
loocation on diisk, to anothe
er location onn disk, withou
ut reading thee entire file in
nto
mmemory. Whicch classes wo ould you use to
t read and w write the file?

S
Select the corrrect answer.

The M
MemoryStream
m, BinaryReade
er and BinaryW
Writer classess.

The FileStream, BinaaryReader and


d BinaryWrite
er classes.

The BiinaryReader and BinaryWritter classes.

The FileStream, Stre


eamReader an
nd StreamWritter classes.
Programming in Visual C# 6-51

Question

The MemoryStream, StreamReader and StreamWriter classes.



7-1

Module 7
Accessing a Database
Contents:
Module Overview 7-2

Lesson 1: Creating and Using Entity Data Models 7-3

Lesson 2: Querying Data by Using LINQ 7-16


Lab: Retrieving and Modifying Grade Data 7-28

Module Review and Takeaways 7-36


7-2 Accessingg a Database

Modu
ule Ove
erview

Ma ons require acccess to data tthat is stored in a database. Microsoft Visual Studio 2012
any applicatio
and the Microsooft .NET Framework provide tools and fu unctionality th
hat you can usse to easily acccess, query,
and update dataa.

In this module, yyou will learn how to creatte and use enttity data models (EDMs) an
nd how to que
ery many
typ
pes of data byy using Langu uage-Integrateed Query (LIN
NQ).

Ob
bjectives
Aftter completing this module
e, you will be able to:
Create, use,, and customize an EDM.

Query data by using LINQ.


Programming with
w Visual C# 7-3
3

Lesson 1
Creatting an
nd Using
g Entity
y Data Modelss

Data access applications haave traditionally been tedio


D ous to develop
p. They often contain queriies that are
w
written as textt strings that cannot be typpe-checked orr syntax-checkked at compille time, and re
esults are
r
returned as un
ntyped data rrecords. The A ADO.NET Entitty Frameworkk solves these problems and d simplifies
t process off developing d
the data access ap
pplications byy using EDMs..

IIn this lesson, you will learn


n how to use the
t ADO.NET Entity Data T Tools to createe EDMs, how to
t customize
t classes tha
the at the tools ge
enerate, and how
h to accesss the entities iin the generatted model.

L
Lesson Ob
bjectives
A
After completting this lesson, you will be able to:

Describe the ADO.NET


T Entity Frame
ework.

Use the A
ADO.NET Entitty Data Mode
el Tools.
Customizze generated cclasses.

Read and
d modify data by using the Entity Framew
work.
7-4 Accessingg a Database

In
ntroductio
on to the A
ADO.NET Entity Fraamework

Hisstorically whe
en you write code to accesss data that is sstored in a dattabase, you have to undersstand the
strructure of the data in the database and h how it all interrelates. Often
n it is stored in a normalize
ed fashion,
whhere tables doo not logicallyy map to the real-life
r objectts that they re
epresent. The ADO.NET Enttity
Fraamework enables you to de evelop applicaations that target a concep ptual model in nstead of the normalized
database structu ure in the storrage layer.

The ADO.NET Entity Framewo


ork provides tthe following::

EDMs. Thesse are models that you can use to map d


database table
es and queriess to .NET Fram
mework
objects.

Entity Structured Query Language


L (SQL). This is a sto
orage independent query language
l thatt enables
you to querry and manipuulate EDM constructs.

Object Servvices. These are


e services that enable you tto work with tthe Common Language Ru
untime
(CLR) objects in a concepptual model.
ents enable yo
These compone ou to:

Write code against a con


nceptual model that include
es types that support inherritance and re
elationships.

Update appplications to ta
arget a differe
ent storage m
model without rewriting or rredistributing all of your
data access code.

dard code thatt is not depen


Write stand ndent on the data
d storage system.
s

Write data access code that supports ccompile-time type-checkin


ng and syntax-checking.
The conceptual model that you work with in the Entity Framework describes the semantics of the business
ntities and relationships in a business sen
ew of the dataa. It defines en
vie nse and is mapped to the lo ogical
mo odel of the un
nderlying dataa in the data ssource. For exxample, in a hu
uman resourcces application n, entities
maay include emmployees, jobs, and branch locations. An entity is a desscription of thhe items and ttheir
prooperties, and they are linkeed by relationships, such ass an employee e being related to a particu
ular branch
loccation.

Additiona al Reading: FFor more inforrmation about the ADO.NEET Entity Frammework, see th
he
AD
DO.NET Entityy Framework p page at http:///go.microsoftt.com/fwlink/??LinkID=2678
806.
Programming with Visual C# 7-5
7-6 Accessingg a Database

Ussing the A
ADO.NET Entity Datta Model Tools

Vissual Studio 20
012 provides tthe Entity Datta Model Toolls that you cann use to creatte and update
e EDMs in
your applicationns. It supportss both database-first design
n and code-firrst design:

Database-fifirst design. In database-firstt design, you design and crreate your database before e you
generate yo our model. Th his is common nly used when you are deve eloping appliccations againsst an
existing datta source; how wever, this can
n limit the flexxibility of the application in
n the long term
m.

Code-first d
design. In code
e-first design, you design the entities forr your applicaation and thenn create the
database sttructure arounnd these entities. Developers prefer this method because it enabless you to
design yourr application around
a the bu
usiness functio
onality that yoou require. Ho owever, in reaality, you
often have to work with an existing daata source.

Ussing the Entity Data M


Model Toolss
Vissual Studio 20
012 provides tthe ADO.NET Entity Data Model
M Tools, w
which include the Entity Data Model
De
esigner for graaphically creating and relatting entities in
n a model andd three wizard
ds for working
g with
mo odels and datta sources. The
e following taable describes the wizards.

W
Wizard Descripttion

E
Entity Data M
Model Wizard Enabless you to generate a new co
onceptual mod del from an exxisting data
source by using the d
database-firstt design meth
hod.

U
Update Mode
el Wizard Enabless you to update an existing
g conceptual m model with ch
hanges that
are madde to the dataa source on which
w it is base
ed.

G
Generate Dataabase Wizard Enabless you to generate a database from a connceptual model that you
have de esigned in the
e Entity Data M
Model Design
ner by using th
he code-
first dessign method.

Wh hen you creatte a model byy using the Entity Data Mod del Wizard, the model openns in the Desig
gner pane,
dissplaying the e
entities that th
he wizard has generated an nd the relation en them. You can use
nships betwee
thiis pane to add
d, modify, and d delete entities and relatio
onships.

Byy default, when


n you create a model from a database, tthe Entity Dessigner automaatically generaates the
maappings from the data sourrce to the connceptual mode el. You can vie
ew, modify, and delete the
ese
maappings in thee 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 Accessingg a Database

Demonstration: Crea
ating an E
Entity Data Model

In this demonstration, you wiill use the Entity Data Wizard to generatte an EDM forr an existing d
database.

De
emonstration Steps
1. Start the MSL-TMG1 virtual machine if it is not already running.

2. 0483A-SEA-D
Start the 20 DEV11-07 virttual machine.

3. Log on to W
Windows 8 as
a Student with the passwo
ord Pa$$w0rrd.

Note: If necessary, clickk Switch Userr to display th


he list of userss.

4. he Windows 8 Start window


Switch to th w.

5. Click Visual Studio 2012


2.
6. In Visual Stu File menu, point to Open, and
udio, on the F a then clickk File.

7. In the Open
n File dialog b
box, browse to
o the E:\Demo ocode\Databaase folder, clicck
AttachFourtthCoffeeDatabaseScript.sqll, and then click Open.

8. On the SQL
L menu, pointt to Transact--SQL Editor, aand then clickk Execute.

9. In the Conn
nect to Serve
er dialog box, in the Serverr name box, type (localdb))\v11.0, and tthen click
Connect.

he query time
Note: If th Connect to Server dialog box, click OK,, and then in
es out, in the C
e Connect to
the g box, click Connect.
o Server dialog

10
0. When the query
q has com
mpleted, on th
he File menu, click Close.

11. On the File menu, point to New, and then click Pro
oject.

w Project dialo
12. In the New nd Templatess, click Visual C#, and then in the Template list,
og box, expan
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 Accessinng a Database

Cu
ustomizin
ng Generatted Classe
es

Whhen you use tthe Entity Dataa Model Wizaard to create a model, it automatically ge enerates classses that
expose the entitties in the mo odel to your application cod
de. These classses contain properties thatt provide
acccess to the prroperties in the entities.
ode example shows an Employee class tthat the Entityy Data Model Wizard gene
The following co erated.

Wizard-Genera
ated Classes
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 entiity classes; howwever, if at an
ny time in
thee future you rrun the Updatte Model Wiza ard, the classe
es will be regeenerated and your code will be
ovverwritten. However, the geenerated classes are defined d as partial claasses; thereforre, you can exxtend them
to add custom ffunctionality tto the classes.

For example, if yyou have a daate of birth prroperty in you


ur model, you could write a GetAge metthod in a
partial class to e
enable a run-ttime calculatio
on of the empployees age.

The following co
ode example shows how yo
ou can add bu
usiness logic tto a generated
d class by usin
ng a partial
cla
ass.

Ad
dding Busine
ess Logic in a Partial Classs
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 Accessinng a Database

Re
eading an
nd Modify
ying Data by Using tthe Entity
y Framewo
ork

The automatically generated code files forr a model also o contains a partial class thaat inherits from the
Sy
ystem.Data.En ntity.DbConttext class. The e DbContext class provides facilities for querying and d working
efault constructor which iniitializes the class by using tthe
witth entity data as objects. It contains a de
connection strinng that the wizard generate es in the application configguration file. T
This defines th
he data
connection and model definition to use. The DbContex xt class also co
ontains a DbS Set property tthat
exposes a DbSe et(TEntity) claass 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 updatee, and delete data.

The following co
ode example shows the claass for the Fou
urthCoffeeEnttities 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, yyou create an instance of th
he DbContextt class and the
en access the properties
byy using the staandard 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 Accessinng a Database

Demonstration: Reading and Modifying Data in an EDM

In this demonstration, you wiill use the ObjjectSet(TEntiity) class to re


ead and modiify data in an EDM.

De
emonstration Steps
1. Start the MSL-TMG1 virtual machine if it is not already running.

2. 0483A-SEA-D
Start the 20 DEV11-07 virttual machine.

3. Log on to W
Windows as Student with
h the passworrd Pa$$w0rd..

Note: If necessary, clickk Switch Userr to display th


he list of userss.

4. he Windows 8 Start window


Switch to th w.

5. Click Visual Studio 2012


2.
6. udio, on the F
In Visual Stu a then clickk Project/Solution.
File menu, point to Open, and

7. In the Open n Project diallog box, brow


wse to the E:\D
Democode\D Demo2\FourtthCoffee.Emp
ployees
folder, clickk FourthCofffee.Employee es.sln, and the
en click Open
n.

8. In Solution Explorer, expand FourthCo


offee.Employ
yees, and then double-click Program.css.

9. Review the definition of the DBConte


ext variable.

0. Review the code in the P


10 PrintEmploye
eesList metho
od that uses th
he DBContex
xt variable to aaccess the
data in the EDM.

11. Review the code in the M


Main method that uses the First extensio
on method to
o retrieve an employee
e
and then m
modifies that e
employees La
astName propperty.
12. On the Deb
bug menu, clicck Start Witho
out Debugging.

13. Verify that tthe employee


es list is displayed, and then
n press Enter.

4. Verify that tthe employee


14 e named Dian
ne Prescott iss now named Diane Forsytth, and then press
Enter.

15. Press Enter to close the aapplication.


Programming with Visual C# 7-15
7-16 Accessinng a Database

Lesson 2
Query
ying Da
ata by U
Using LINQ

As an alternative
e to using thee Entity Frame
ework for queerying data, yo
ou can use LIN NQ. This also supports
s
compile-time syyntax-checking and type-ch ense in Visual Studio.
hecking and aalso uses Micrrosoft IntelliSe
LIN
NQ defines a rrange of standdard query opperators that enable you too retrieve exacctly the data tthat you
req
quire in a declarative way.

In this lesson, yo how to query data and use anonymous m


ou will learn h methods and how to force query
exeecution to override the deffault deferred query executtion behavior..

Le
esson Obje
ectives
Aftter completing this lesson, you will be ab
ble to:

Query data.

onymous types.
Query data by using ano
Force queryy execution.
Programming witth Visual C# 7-17
7

Q
Querying Data

You can use LLINQ to queryy data from a w


Y wide range off data sourcess, including .N
NET Frameworrk collections,
M
Microsoft SQLL Server dattabases, ADO.NET data setss, and XML do ocuments. In ffact, you can u
use it to
q
query any datta source thatt implements the IEnumeraable interfacee.
T syntax of all LINQ querries has the saame basis, as follows:
The f

f
from <variab
ble names> in <data sourcee>

s
select <variab
ble names>
However, you
H u can customizze this syntax in many wayss to retrieve e
exactly the datta that you re
equire in the
f
format that yo
ou want. The following cod de examples aall use LINQ to
o Entities to query data in aan EDM;
h
however, the syntax of the query itself d
does not changge if you use a different typ
pe of data souurce.

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 dataa in a single
e
entity.

U
Using a selecct Clause
IQueryable<
<Employee> emps
e = from e in DBConte
ext.Employee
es
select e;

The return data type from the query is aan IQueryable


T e<Employee>, enabling yo
ou to iterate tthrough 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 dataa by row to
c
contain employees witth a last name
only e e of Prescott.

U
Using a wherre 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 witth 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. Start the MSL-TMG1 viirtual machine
e if it is not already running
g.

2
2. Start the 20483A-SEA
A-DEV11-07 vvirtual machine.

3
3. Log on to
o Windows 8 as
a Student with the passwo
ord Pa$$w0rrd.

Note: Iff necessary, click Switch Usser to display the list of use
ers.

4
4. Switch to the Windowss 8 Start wind
dow.

5
5. Click Visu
ual Studio 20
012.
6
6. In Visual Studio, on the
e File menu, p n, and then click Project/Solution.
point to Open

7
7. In the Oppen Project dialog box, bro
owse to the E::\Democode\\Demo3\Fou
urthCoffee.Em
mployees
folder, click FourthCo
offee.Employ yees.sln, and tthen click Ope
en.

8
8. In Solutio
on Explorer, exxpand Fourth hen double-click Program.cs.
hCoffee.Emplloyees, and th

9
9. 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, cclick Start Witthout Debugg


11. ging.

1 In the con
12. nsole window
w, review the o
output of the QueryingDatta method, an
nd then press Enter.

1 Repeat sttep 12 for each of the follow


13. wing methods:
a. FilterringDataByRow

b. FilterringDataByColumn

1 Press Ente
14. er to close the
e application.
1 In Visual Studio, on the
15. e File menu, cclick Close So
olution.
7-20 Accessing a Database
Programming witth Visual C# 7-21
1

Q
Querying Data by Using
U Ano
onymous T
Types

IIn the examplles in the prevvious topic an


nd demonstrattion, the returrn data was allways 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 contaaining a subse
the et of columnss before defining the queryy. Although th
his is a perfectly valid way
o working, it can become tedious to explicitly define multiple classes.
of

You can use aanonymous tyypes to store tthe returned d


Y n type as an implicitly
data by declarring the return
t
typed local va
ariable, a var, and by using the new keyw
word in the se o create the instance of
elect clause to
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
c
clause to filterr the returned
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 tyypes 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 employyees 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 aggregatte 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 witth Visual C# 7-23
3

D
Demonstr
ration: Qu
uerying D
Data by Ussing 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. Start the MSL-TMG1 viirtual machine
e if it is not already running
g.

2
2. Start the 20483A-SEA
A-DEV11-07 vvirtual machine.

3
3. Log on to
o Windows 8 as
a Student with the passwo
ord Pa$$w0rrd.

Note: Iff necessary, click Switch Usser to display the list of use
ers.

4
4. Switch to the Windowss 8 Start wind
dow.

5
5. Click Visu
ual Studio 20
012.
6
6. In Visual Studio, on the
e File menu, p n, and then click Project/Solution.
point to Open

7
7. In the Oppen Project dialog box, bro
owse to the E::\Democode\\Demo4\Fou
urthCoffee.Em
mployees
folder, click FourthCo
offee.Employ yees.sln, and tthen click Ope
en.

8
8. In Solutio
on Explorer, exxpand Fourth hen double-click Program.cs.
hCoffee.Emplloyees, and th

9
9. 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, cclick Start Witthout Debugg


11. ging.

1 In the con
12. nsole window output of the UsingAnonymousTypes m
w, review the o method, and tthen press
Enter.
1 Repeat sttep 12 for each of the follow
13. wing methods:

a. Grou
upingData

b. AggrregatingData
c. 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 witth Visual C# 7-25
5

F
Forcing Q
Query Execcution

By default, wh
B hen you define a LINQ query that return ns a sequence of values, it iss not run until you actuallyy
t to use som
try me of the returned data. This feature is known as deferrred query exeecution and ensures that
y can create a query to rretrieve data in a multiple-u
you user scenario and know tha at whenever itt is executed
y will receivve the latest in
you nformation.

I the followin
In ng code exam
mple, the querry is not actuaally executed u
until the start of the foreacch 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 exaample, an Av
verage,
C
Count, or Ma ax function, th
he query is run
n immediatelyy. This is know
wn as immedia ate query execcution and is
n
necessary in the singleton result
r scenario
o because thee query must produce
p a seq
quence to calcculate the
s
singleton resuult.
You can overrride the defau
Y ult deferred qu or queries thatt do not produce a
uery execution behavior fo
s
singleton resu one of the following metho
ult by calling o ods on the query:

ToArray
ToDiction
nary

ToList

I the followin
In ng code exam
mple, the querry is executed immediately after it is defiined.
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 witth Visual C# 7-27
7

D
Demonstr
ration: Re
etrieving and
a Modiffying Grad
de Data Laab

I this demon
In nstration, you will learn abo
out the tasks tthat you will p
perform in the
e lab for this module.
m
7-28 Accessinng a Database

Lab: R
Retrieving and
d Modiffying Grade Da
ata

Sccenario
Yo
ou have been asked to upgrade the proto otype applicaation to use an
n existing SQLL Server datab
base. You
beegin by workin
ng with a dataabase that is stored
s on your local machinne and decide ntity Data
e to use the En
Mo odel Wizard to generate an n EDM to acce ess the data. Y
You will need to update thee data access code for
thee Grades sectiion 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 alsso decide to incorporate vaalidation logicc into the EDMM to ensure th hat
stu
udents cannott be assigned to a full class and that the data that use n they assign new grades
ers enter when
conforms to thee required valuues.

Ob
bjectives
Aftter completing this lab, you
u will be able to:

Create an EEDM from an e


existing datab
base.

Update datta by using the


e .NET Entity Framework.
Extend an EEDM to validaate data.

Esttimated Time:: 75 minutes

A-SEA-DEV11-07, MSL-TMG
Virtual Macchine : 20483A G1
User Name: Student

Password: Pa$$w0rd
P
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. Start the MSL-TMG1 virtual machine if it is not already running.
2. Start the 20483A-SEA-DEV11-07 virtual machine and log on as Student with the password
Pa$$w0rd.

1. Start Visual Studio, and from the E:\Labfiles\Starter\Exercise 1 folder, open the GradesPrototype.sln
solution.

2. Add a new class library project named Grades.DataModel to the solution.

3. Add a new ADO.NET Entity Data Model named GradesModel to the Grades.DataModel project.
4. Generate the model from the SchoolGradesDB database on the (localdb)\v11.0 server and include
the following tables:

Grades
Students

Subjects

Teachers

Users

5. If the Security Warning dialog box appears, click Do not show this message again, and then click
OK.
6. Build the solution.

X Task 2: Review the generated code


1. In the designer window, review the entities that the wizard generated.

2. Review the properties and navigation properties of the Grade entity.

3. Review the mapping details for the Grade entity.

4. In the GradesModel.Context.tt folder, in GradesModel.Context.cs file, review the code for the
SchoolGradesDBEntities DbContext object.
5. In the GradesModel.tt folder, in the Grade.cs file, review the properties of the Grade entity.

6. 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. In Visual Studio, from the E:\Labfiles\Starter\Exercise 2 folder, open the GradesPrototype.sln solution.

2. Set the GradesPrototype project to be the startup project.

3. In the Views folder, in StudentProfile.xaml.cs, in the Refresh method, add code to the end of the
method to:

a. 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.
b. Use data binding to display the list of grades in the studentGrades ItemsControl control.

4. Build the solution and resolve any compilation errors.

5. Run the application.


6. Log on as vallee with a password of password99.

7. Click Kevin Liu, and then verify that his grades appear in the list.

8. 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. Convert the subject ID that is passed into the method into the subject name.

2. 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. Create and display a new instance of the GradeDialog view.

b. 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. Build the solution, and then resolve any compilation errors.
2. Run the application.

3. Log on as vallee with a password of password99.

4. Click Kevin Liu, and verify that the list of grades now displays the subject name, not the subject ID.
5. Add a new grade for Kevin Liu using the following information:

Subject: Geography

Assessment: A+
Comments: Well done!

6. Verify that the new grade is added to the list, and then close the application.

7. 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. In Visual Studio, open the GradesPrototype.sln solution from the E:\Labfiles\Starter\Exercise 3 folder.
2. Set the GradesPrototype project to be the startup project.

3. Add a new class named customTeacher.cs to the Grades.DataModel project.

4. Modify the class declaration to make it a public partial class named Teacher.
5. Add a private integer constant named MAX_CLASS_SIZE with a value of 8 to the Teacher class.

6. Add an EnrollInClass method that takes a Student object as a parameter and returns void.

7. 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. If the class is full, throw a new ClassFullException exception.

9. 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. Call the EnrollInClass method to assign the student to this teachers class, passing the student as
a parameter.

b. Save the updated student/class information back to the database.

X Task 2: Add validation logic for the Assessment and AssessmentDate properties
1. Add a new class named customGrade.cs to the Grades.DataModel project.

2. Modify the class declaration to make it a public partial class named Grade.
7-34 Accessing a Database

3. Add a ValidateAssessmentDate method that takes a DateTime object as a parameter and returns a
boolean.

4. In the ValidateAssessmentDate method, add code to:

a. If the DateTime object passed to the method is later than the current date, throw a new
ArgumentOutOfRangeException exception.
b. Otherwise, return true.

c. Bring the System.Text.RegularExpressions namespace into scope.

d. 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. If the string passed is not in the valid range, throw a new ArgumentOutOfRangeException
exception.

7. Otherwise, return true.


8. In the Views folder, in the GradeDialog.xaml.cs class, locate the ok_Click method.

9. In this method, add code to:

a. Create a new Grade object.


b. Call the ValidateAssessmentDate method, passing the selected date in the assessmentDate
date picker control.

c. 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. Build the solution, and then resolve any compilation errors.

2. Run the application.


3. Log on as vallee with a password of password99.

4. 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.
5. 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!

6. 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. Modify the new grade date by using the following information:

Date: 8/19/2012
Subject: Math

Assessment: F+

Comments: Well done!

8. Verify that an error message is displayed explaining that the assessment grade must be in the range
A+ to E-.

9. 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 Accessinng a Database

Modu
ule Reviiew and
d Takea
aways

M
Module Revie
ew
In this module, yyou learned how
h to create and use EDM
Ms and how to
o query many types of data by using
LIN
NQ.
Question: What
W advantaages does LINQ provide ovver traditional ways of queryying data?

Test Your Know


wledge

Q
Question

FFourth Coffee e wants you to


o add custom m functionality
y to an existing EDM in itss Coffee
SSales applicatiion. You need
d to write a m
method for addding a new p product to th
he
aapplication. In
n which of the
e following lo
ocations shouuld you write your code?

S
Select the corrrect answer.

In the relevant gene


erated class in
n the EDM pro
oject.

In a paartial class in the


t EDM project.
8-1

Module 8
Accessing Remote Data
Contents:
Module Overview 8-2

Lesson 1: Accessing Data Across the Web 8-3

Lesson 2: Accessing Data in the Cloud 8-19


Lab: Retrieving and Modifying Grade Data in the Cloud 8-34

Module Review and Takeaways 8-42


8-2 Accessingg Remote Data

Modu
ule Ove
erview

Sysstems often consist of man ny componentts and services; some might be hosted w within your orgganizations
inffrastructure, w
whereas others could be ho osted in data ccenters anywh
here in the wo
orld. The abilitty for
ap
pplications to b quirement in modern applications.
be able to interact with succh services is a common req

In this module, yyou will learn how to use the request an nd response cllasses in the System.Net
S n
namespace
to directly maniipulate remote data source es. You will alsso learn how tto use Windowws Commun nication
Foundation (WC CF) Data Serviices to exposee and consum me an entity daata model (ED DM) over the web.
w

Ob
bjectives
Aftter completing this module
e, you will be able to:

Send data tto and receive


e data from w
web services an
nd other remo
ote data sourcces.

Access data
a by using WC
CF Data Servicces.
Programmingg in Visual C# 8-3
3

Lesson 1
Acce
essing Data
D Accross the Web

Data is often e
D exposed overr the web throough web servvices or other application p
programming interfaces
(
(APIs). To be aable to consume such data sources in yoour application, you need a way to send and receive
m
messages so tthat you can e
establish a con
nnection and ultimately send and receivve data.

IIn this lesson, you will learnn how to conssume remote data sources such as web sservices and FFile Transfer
P
Protocol will include how to create a request, sup
(FTP)) sites, which w pply credentia
als for authenttication,
p
package data into the requ uest, and proccess data that is returned in
n the response
e.

L
Lesson Ob
bjectives
A
After completting this lesson, you will be able to:

Describe how the Micrrosoft .NET Framework usses requests and


a responsess.

Expose tyypes from web


b services by u
using data contracts.
Create a rrequest and p
process a response.

Provide ccredentials or a security tokken to enable the remote data source to perform auth
hentication.

Send and
d receive data..
8-4 Accessingg 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 datta source coulld be anything
g from an FTPP site to an ASSP.NET or WC
CF Web
Service.
Wh hen consuminng a remote d
data source in your applicattion, the .NET
T Framework u uses requests and
between the ttwo (or more) systems. Thiss involves the following steps:
ressponses to pass messages b

1. onnection to tthe remote daata source. This might inclu


Initiate a co ude passing a security token
n or user
credentials so that the re
emote data soource can auth henticate you.

2. Send a requ uest message to the remote e data source. This message may also include any datta that the
remote data source requuires to satisfyy the request, such as the id
dentifier for th
he sales record
d you want
to retrieve.

3. Wait for the


e remote dataa source to prrocess your request and issuue a response
e. As a develop
per, you
have no conntrol over how
w long it migh ht take to rece
eive a response from a web
b service.
4. Process the
e response, and extract any data that is in
ncluded in the
e response.

Note: Nott all communications have to include bo oth a request aand response message.
Deepending on tthe nature of the applicatio on, it might on
nly be applicaable to send oone message.
For example, if yyour applicatiion wants to let a web service know thatt it has finishe
ed processing a
tassk, you only need to send a request. Thiss is known as a one-way op peration.

W Connecctivity in the
Web 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 tarrget different data sources. The following
g table describes some of tthese
req
quest and response classes.

C
Class Descriptiion

W
WebRequest An abstrract class that provides the base infrastru
ucture for anyy request to
a Uniformm Resource Id dentifier (URI)).
Programming in Visual C# 8-5

Class Description

WebResponse An abstract class that provides the base infrastructure to process any
response from a URI.

HttpWebRequest A derivative of the WebRequest class that provides functionality for any
HTTP web request.

HttpWebResponse A derivative of the WebResponse class that provides functionality to


process any HTTP web response.

FtpWebRequest A derivative of the WebRequest class that provides functionality for any
FTP request.

FtpWebResponse A derivative of the WebResponse class that provides functionality to


process any FTP response.

FileWebRequest A derivative of the WebRequest class that provides functionality for


requesting files.

FileWebResponse 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 Accessingg Remote Data

Defining a Data Conttract

A remote
r data ssource can expose any type e of data. For example, a web service can n expose binaary streams,
scaalar values, orr custom objects. The choicce of the type of data that yyou expose is determined bby the
reqquirements off your applicaation, but how
w you expose it d by the data contracts that you
i is controlled
de
efine in your w web services.

If yyou want to eexpose a custo om object from m a web serviice, you must provide metaadata that desscribes the
strructure of the object. The se erialization prrocess uses th
his metadata to convert you
ur object into a
tra
ansportable fo ormat, such ass XML or JavaScript Object Notation (JSO ON). This metaadata provide
es
insstructions to tthe serializer tthat enable yo ou to control wwhich types aand members are serialized.

Da
ata Contraccts in the .N
NET Framew
work
The .NET Frame
ework provide
es the System.Runtime.Serrialization na amespace, which includes the
Da
ataContract aand DataMemmber attribute butes to define serializable types and
es. You can usse these attrib
meembers.

The following co
ode example shows how to
o define a seriializable type by using the DataContracct and
Da
ataMember attributes.
a

De
efining a Datta 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: FFor more inforrmation about the DataContract and DataMember
atttributes, see th
he DataContrractAttribute C
Class page at
htttp://go.microssoft.com/fwlinnk/?LinkID=26 67812.
Programming in Visual C# 8-7
8-8 Accessingg Remote Data

Crreating a Request aand Processsing a Re


esponse

The protocol that your remotte data source e uses determ


mines the requ
uest and respo
onse classes yo
ou must
usee. Irrespective
e of the classe
es you use, you
u can apply th
he same patte
ern to send a request and rreceive a
ressponse.

Th
he HttpWeb
bRequest a
and HttpWe
ebResponse
e Classes
The following stteps describe how to send an HTTP requ
uest to a web service and process the ressponse by
usiing the HttpW
WebRequest and HttpWe ebResponse cclasses:
1. Get a URI to
o the web servvice to which you want to send a requesst. The followiing code exammple shows
an HTTP UR RI that addressses 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 tto configure the request an
nd access the response. The
e following co
ode
example shows how to create an Http pWebRequesst 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 tthe static
Create method that the Web bRequest basse class exposes and then ccast to the typ
pe of request
you require.

3. ponse from th
Get the resp he request obj
bject. The follo
owing code exxample showss how to get the
response fro
om an HttpWWebRequest 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 casst 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 Accessinng Remote Data

Au
uthenticatting a We
eb Requesst

Re
emote data soources are ofte en protected to
t prevent unauthorized ussers from usin ng the service and
gaining access tto data. Expossing an unprootected data soource over the web can leaad to unauthoorized users
sennding requestts and increassing the load on
o the data so ource. There aare many wayys in which you can
seccure remote d
data sources. One
O approach h is to authenticate each usser who attem
mpts to conneect to the
rem
mote data sou urce.

Ty
ype of Auth
hentication
The following taable describess some of the common authentication te
echniques thaat you can use
e to secure
rem
mote data sou urces.

A
Authentication mechanism
m De
escription

B
Basic En
nables users too authenticatee by using a u
user name and d password.
Baasic authenticaation does no
ot encrypt the credentials w
while in
traansit, which means
m that unaauthorized ussers may access the
creedentials.

D
Digest En
nables users too authenticatee by using a u
user name and d password,
bu
ut unlike basicc authenticatio
on, the credentials are encrypted.

W
Windows En
nables clients to authenticate by using thheir Windows domain
creedentials. Win
ndows authen ntication uses either hashing or a
Keerberos token to securely authenticate users. Window ws
au
uthentication is typically use e a single sign-on (SSO)
ed to provide
exxperience in o
organizations.

C
Certificate En
nables only clients that havee the correct certificate installed to
au
uthenticate wiith the service
e.

The nature of th
he service andd where it is hosted are like
ely to influence an organiza ations choice of
authentication mmechanism. For example, a service that is i exposed ovver an organizzations intranet might
use
e Windows au uthentication so that users can authenticcate by using their Active D Directory Do omain
Services (AD DSS) credentials. Using Window ws authenticaation in this sccenario will prrovide the use
ers with an
SSO experience and not requ uire them to reemember cred dentials for eaach service thhey 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 aand Receiv
ving Data

You use reque


Y ests and respo
onses to send data to or rettrieve data fro
om a remote data source. FFor example,
y may wantt to add a new
you w record to a web service o
or retrieve a fiile from an FT
TP site.

Each derivativve of the Web


E bRequest and d WebRespon nse classes en
nables you to ssend and rece
eive data by
u
using the speccific protocol that the classs implements. For example,, the HttpWebRequest claass enables
y to send re
you equests to a web
w service byy using the HT TTP protocol.

The WebRequest base classs includes the following m


T members that you can use tto send data to a remote
d
data source:

ContentT Type. This pro


operty enable
es you to set th quest will send. For
he type of datta that the req
example, if you are sen
nding JSON data by using tthe HttpWeb bRequest class, you use the e
applicatiion/json conttent type.

Method. This propertyy enables you to set the typpe of method that the Web bRequest objject will use
to send th
he request. Fo
or example, if you are uploaading a file byy using the FttpWebReque est class, you
use the STOR method..

ContentL
Length. This p
property enab
bles you to sett 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 enaables you to acccess and
s
stream data frrom 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 processs for creating
t request re
the emains the sam
me:

1
1. Get the U
URI to the rem
mote data sourrce and the daata you want to send.

2
2. Create the request object.

3
3. Configure e the request object, which
h includes settting the reque
est method an
nd the length of the data
that the rrequest will se
end.

4
4. 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 Accessinng Remote Data

Demonstration: Con
nsuming a Web Serv
vice

In this demonstration, you wiill use the HtttpWebReque


est and HttpW
WebResponse
e classes to co
onsume a
weeb service ove
er HTTP.

The application will use the S


System.Net classes to get ssales people rrecords from tthe Fourth Co offee Sale
Service. You will send a reque
est that will co mail address off the sale persson record you want to
ontain the em
ge
et in the JSON format, process the respon ecord details in the UI.
nse, and then display the re

De
emonstration Steps
1. Start the 20
0483A-SEA-DEEV11-08 virtual machine.

2. Log on to W
Windows 8 as Student with
h the password Pa$$w0rd.

Note: If necessary, clickk Switch Userr to display th


he list of userss.

3. he Windows 8 Start window


Switch to th w.

4. Click Visual Studio 2012.


5. udio, on the F
In Visual Stu a then clickk Project/Solution.
File menu, point to Open, and

6. In the Openn Project dialo


og box, browsse to E:\Demo ocode\Starter\\Fourth Coffee
e Contact Find
der folder,
click Fourth
h Coffee Contaact Finder.sln,, and then clicck Open.

7. In the Soluttion Explorerr window, exp


pand the FourrthCoffee.Da
ataService pro
oject, and the
en double-
click ISalesS
Service.cs.

8. In the code
e editor, review
w the signaturre of the GetS
SalesPerson operation,
o hich accepts an email
wh
address in tthe form of a JSON string and
a returns a SalesPerson object.

9. In the Soluttion Explorerr window, exp


pand the FourrthCoffee.Inffrastructure project,
p expan
nd the
Models folder, and thenn double-click SalesPerson.cs.
0. In the code
10 e editor, review
w the DataCo
ontract and D
DataMember attributes thaat decorate th
he type and
type memb bers.

11. In Microsofft Visual Studio


o, on the Viiew menu, click Task List.
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 Serrvices follows the Representational State


W e Transfer (RESST) architectural model andd uses open
w standards such as the Open Data Prrotocol (ODatta) to expose and consume
web e data over the
e web. By
f
following thesse standards, you can build d solutions based on WCF D Data Services that a wide vaariety of
c
client ardless of the technology that is used to
applicattions can easily access, rega o implement the client
a
application.

n how to creatte a WCF Dataa Service and how to define which entitiies and
IIn this lesson, you will learn
o
operations yo
ou want to exp ow to create a client library and how to cconsume the
pose. You will also learn ho
e
entities operations that you have exxposed.
and o

L
Lesson Ob
bjectives
A
After completting this lesson, you will be able to:
Describe the purpose o
of a WCF Data
a Service.

Define a W
WCF Data Serrvice.

Expose a data model b


by using a WC
CF Data Servicce.
Expose w
web methods b
by using a WC
CF Data Servicce.

Create a cclient library aand reference


e a WCF Data Service.

Retrieve aand manipulaate entities thaat a WCF Dataa Service expo


oses.
8-20 Accessinng Remote Data

W
What Is WC
CF Data Se
ervices?

WC CF Data Servicces enables yo ou to create aand access datta services ovver the web. Yo ou expose your data as
ressources that aapplications caan access by uusing a URI. These resource es are exposed d as sets of en
ntities that
are
e related by associations, thhe same concepts as in an EDM. Howeve er, you can exxpose data froom many
typ
pes of storage e, including daatabases and Common Lan nguage Runtim me (CLR) classses.

WCCF Data Servicces uses URIs to address daata and simplee, well-knownn formats to re
epresent that data, such
as XML and Atoom. This resultts in data bein
ng served as a REST-style re
esource collecction.

REEST has becom me a popular mmodel for imp plementing web services th hat need to acccess data (oth her models,
succh as those baased on the W
WebRequest//WebResponse model desscribed in the previous lesso on, are
mo ore suited to invoking
i remo ote methods). REST describbes a statelesss, hierarchical scheme for reepresenting
ressources and bbusiness objeccts over a netw
work. Resourcces are accesseed through URIs that identify the data
to retrieve. For example,
e Fourth Coffee mig ght choose too make the daata for all of itts sales people
e available
thrrough the folllowing URI:
htttp://FourthCo
offee.com/Sale
esService.svc/SSalesPersons

The data for a specific sales p


person could bbe fetched byy specifying th
he identifier (ssuch as a saless person
nu
umber) for thaat sales personn, like this:
htttp://FourthCo
offee.com/Sale
esService.svc/SSalesPersons//99

Sim
milarly, the de
etails of produ
ucts that it sells might be avvailable throu
ugh the follow
wing URI:

htttp://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:

htttp://FourthCo
offee.com/Sale
esService.svc/Products/25

Note: The e exact URI scheme that a w


web service usses to expose data is a deciision of the
org
ganization tha examples thatt are shown here illustrate a
at implements the web servvice, but the e
common patterrn.

The REST model performs HT TTP GET queriies to retrieve data, but the
e REST model also supportss insert,
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 Accessinng Remote Data

Defining a WCF Data


a Service

Byy using WCF D


Data Services, you can expo ose data from relational datta sources succh as Microsofft SQL
Server through an EDM con nceptual scheema that is cre
eated by usingg the ADO.NEET Entity Frammework, and
you can enable a client appliccation to query and maintaain data by ussing this schem
ma.

Note: WCCF Data Servicces can also exxpose non-relational data, but this requires building
customized classses. WCF Data Services ope erates most naturally with tthe model thaat the ADO.NET
Entity Framework presents.

A WCF
W Data Serrvice is based on the System m.Data.Serviices.DataServ vice generic class.
c This class expects a
typpe parameter that is a colle
ection containning at least one property tthat implemen nts the IQuery yable
ntext class for an entity set that is defined by using the Entity Framework. The
intterface, such aas the DbCon
DaataService typ pe implementts the basic fu
unctionality to
o expose the entities
e in this collection as a series of
REEST resources.
The following co
ode example shows the definition of a W
WCF Data Servvice based on a DbContex
xt class
called FourthCo
offee that is ge
enerated by u O.NET Entity Framework.
using the ADO

efining a Datta Service


De
p
public class FourthCoffe
eeDataServic
ce : DataServ
vice<FourthC
Coffee>
{
...
}

Yo
ou can implem ment methodss in a WCF Data Service thaat specify the e entities to exp
pose from the
e underlying
ED
DM and that configure the ssize of datase
ets that the daata service pre
esents. You can also overrid
de methods
tha
at are inherite
ed from the D mize the way in which the service operate
DataService cllass to custom es.
Byy default, WCFF Data Servicees uses a simple addressing scheme that exposes the e entity sets that are
deefined within tthe specified EEDM. When yyou consume a WCF Data SService, you ad ddress these eentity
ressources as an entity set that contains instances of an e entity type. Fo
or example, su
uppose that th he
folllowing URI (sshown in the pprevious topicc) returns all of
o the SalesPe erson entities that were defined in the
ED
DM that was used to construct a WCF Daata Service:

htttp://FourthCo
offee.com/Sale
esService.svc/SSalesPersons
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 Accessinng Remote Data

Exxposing a Data Mod


del by Usiing WCF Data
D Serviices

For security reassons, WCF Daata Services do


oes not autom matically expo
ose any resourrces, such as e
entity
collections, thatt the EDM imp
plements. You bles or disables access to resources in
u specify a policy that enab
the
e InitializeService method d of your dataa service. This method takess a DataServiiceConfiguration object,
whhich has a SettEntitySetAcccessRule prop perty that youu use to define
e the access p
policy.

The following co
ode example shows how to
o allow accesss to all resourcces that the WCF
W Data Servvice
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 acccess rights
to grant over thhat resource. Y
You can speciffy a resource explicitly, or yyou can use wildcard
w characters. The *
value that is sho
own in the codde example iss a shorthand way of speciffying all resou urces that the WCF Data
Service publishees. The EntitySetRights.Alll value grantss unrestricted access to thesse resources.

Note: Enuumerations an mplemented in an EDM do not propagatte


nd partial classses that are im
thrrough WCF D Data Services. If
I you want too expose enum merations and
d extensions to
o partial classses,
you should incluude these types in a separaate assembly tthat you can rreference in th
he service and d
clie
ent applicatio
on directly.
Additionaal Reading: FFor more inforrmation about defining acccess rules in a WCF Data
Service, see the Configuring the Data Serrvice (WCF D Data Services)) page at
htttp://go.microssoft.com/fwlin
nk/?LinkID=2667817.
Programming in
i Visual C# 8-25
5

E
Exposing Web Metthods by U
Using WCF Data Services

The primary purpose


T p W Data Servvice is to provvide access to data. However, you can also implementt
of a WCF
c
custom operaations that maanipulate data a. A WCF Data a Service operration is simply a method o
of the data
s
service that is visible to thee REST infrastrructure and th
hat can be acccessed by sendding an HTTPP GET, PUT,
P
POST, or DELEETE request.

WCF Data Serrvices operatio


W ons that are aaccessed by ussing a GET req b annotated with the
quest should be
W
WebGet attribute. These o
operations typpically return d
data, although
h they may ruun some busin ness logic thatt
d
does not return a value. Op
perations thatt are accessedd by using PUTT, POST, or DEELETE requestts should be
a
annotated witth the WebInnvoke attributte. These operrations typically modify the
e data that the
e service uses
i some way.
in
SSimilar to entity sets, you m
must explicitlyy enable accesss to operation ns that a WCFF Data Service
e exposes.
Y can do th
You his by calling tthe SetServicceOperationA AccessRule m method of the
D
DataServiceC Configuration n object when n you initialize
e the service. You specify th
he name of thhe operation
a the appro
and opriate accesss rights.

A data service meters and returns one of th


e operation caan take param 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
operationn returns an enumerable co ollection based on an entityy type that the service reco ognizes, a
client app
plication can p perform queriies by specifyiing HTTP URIss in the mann ner shown in tthe previous
topics in tthis lesson. Im
mplementing an a operation that returns aan enumerable e collection in
n this way
gives youu 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 appliccation provide es. The
followingg code example shows an o operation thatt retrieves sale
es people per area.

public class FourthCoffeeDataSService : DaataService<FourthCoffee>


>
{
pub
blic static void InitiallizeService((
DataServiceConfiguratiion config)
{
...
config.SetServiceOperaationAccessRRule("SalesPersonByArea"
",
ServiceOperationRi
ights.ReadMuultiple);
}
...
[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 Accessinng Remote Data

Re
eferencing
g a WCF D
Data Sourcce

The client library for a WCF D Data Service consists of a class that is derrived from the
e DataService eContext
typ
pe that exposes one or more DataServicceQuery obje ects as properties. The name of this classs 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 Datta Service is
based. For exam mple, the FourrthCoffeeDattaService WC CF Data Service uses a DbCo ontext objectt called
Fo
ourthCoffeeEntities to con nnect to the underlying EDM, so the nam me of the DataServiceConttext type
tha
at is generateed for the clien
nt library is alsso FourthCofffeeEntities.
The DataServicceContext class performs a similar role to the DbContext class in tthe Entity Fram mework. A
clie
ent applicatioon connects to o the data sou
urce through a DataService eContext objject and fetches the data
forr the entities tthat the data service exposes by using th
he DataServicceQuery prop perties. Each
DaataServiceQu uery property is a generic ccollection obje m one of the underlying
ect that presents data from
entities that proovides the datta for the WCFF Data Servicee.

The client library also providees definitions of the types tthat each DattaServiceQue ery collection contains. A
ent applicatio
clie on can performm LINQ querie es against the
e DataService eQuery collection propertie es, and the
clie
ent library con
nstructs the appropriate HT TTP request to o fetch the co
orresponding data. The WC CF Data
Service fetches tthe matching data and pop pulates the Da ataServiceQu uery collection. The client aapplication
can then iteratee through this collection and retrieve thee data for each h item.

Yo
ou can generate the client library for a W
WCF Data Servvice by using tthe Add Serviice Reference e dialog
bo
ox in Visual Stu
udio or by usiing the WCF DData Service client
c utility, D
DataSvcUtil, fro
om the comm
mand line.

Ad
dding a Serrvice Refere
ence
Yo
ou can use the e Add Service e Reference dialog
d box in a client appliccation. This dialog box enab bles you to
speecify the URL of the WCF D Data Service to
o connect to. The dialog bo ox sends a me etadata queryy to the
speecified URL, and it uses the
e response to generate the appropriate D DataServiceC Context class that
contains the Da ataServiceQuery properties and the classses for each o of the entitiess that the WCFF Data
Service exposes. The returned d metadata is stored in the client projectt as an .edmx file. This is noot the same
as an .edmx file that is generaated by using
g the ADO.NET T Entity Data Model Design ner (it has a different
forrmat), but you he XML editor or any text editor.
u can view this metadata file by using th
Programming in Visual C# 8-29

To add a data service reference, perform the following steps:

1. If the data service is not part of the solution and is not already running, start the data service and
note its URI.

2. In Solution Explorer, right-click the client project, and then select Add Service Reference.

3. If the data service is part of the current solution, click Discover.


4. 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.

5. 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 Accessinng Remote Data

Re
etrieving aand Updaating Dataa in a WCFF Data Serrvice

Aftter 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 sservice expose
es.

Re
etrieving Data
To
o retrieve dataa from a WCF Data Service by using the client
c library, perform the ffollowing step
ps:

1. Create an in
nstance of thee type that is derived
d from the DataServ viceContext cclass in the client library,
and then coonnect to the WCF Data Se ervice. The con
nstructor for tthis class expe
ects a Uri obje
ect that
contains the
e address of tthe service.

2. Retrieve data by querying the appropriate DataSerrviceQuery co ollection in th


he DataServicceContext
object. Whe en you query a DataServicceQuery colle ection, the clie
ent library con
nstructs an HT
TTP request
that specifie
es the resourcce and any criteria that is re
equired. The qquery is transmmitted to the WCF Data
d the data is returned and used
Service, and u to populate the DataServiceQuery y object.

3. Iterate through the itemss in the DataS


ServiceQuery
y collection an
nd process the
e objects thatt are
returned.

The following co
ode example connects to the FourthCofffeeDataServicce WCF Data SService by using the
Fo
ourthCoffeeEntities type in
n the client libbrary (this is th
he class that is derived from
m DataServicceContext).
The parameter to
t the constru
uctor is the adddress of the sservice. The co ode then queries the SalessPersons
Da
ataServiceQu uery property to fetch all saales 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 servicce operationss that you mayy have expose ed in the
WC CF Data Servicce. You can in
nvoke service operations byy using the Ex xecute metho od of the
DaataServiceContext class. The value that the Execute method returrns is an enum merable collecction. If the
serrvice operatio
on returns a single, scalar vaalue, you shou
uld extract tha
at value from the collection
n by using
ammethod 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 Modiffying Grad
de Data in
n the Clou
ud Lab

I this demon
In nstration, you will learn abo
out the tasks tthat you will p
perform in the
e lab for this module.
m
8-34 Accessinng Remote Data

Lab: R
Retrieving and
d Modiffying Grade Da
ata in tthe Clou
ud

Sccenario
Cu
urrently, the application retrieves data fro
om a local database. Howe ever, you havee 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
Yo e a WCF Data Service for thhe SchoolGrades database
e that will be integrated into
o the
ap
pplication to e
enable access tto the data.

Fin
nally, you have
e been asked to write code
e that displayss student imag
ges by retrievving them from
m across
the
e web.

Ob
bjectives
Aftter 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.

Esttimated Time:: 60 minutes

Virtual Macchine: 20483A


A-SEA-DEV11--08, MSL-TMG
G1

User Name: Student

Password: Pa$$w0rd
P
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. Start the MSL-TMG1 virtual machine if it is not already running.

2. Start the 20483A-SEA-DEV11-08 virtual machine and log on as Student with the password
Pa$$w0rd.

3. Start Visual Studio, and then open the GradesPrototype.sln solution from the
E:\Labfiles\Starter\Exercise 1 folder.
4. Add a Visual C# ASP.NET Empty Web Application project called Grades.Web to the solution.

5. Configure the new project as follows:

a. Start Action: Dont open a page.


b. Servers: Use Local IIS Web server

c. Project Url: http://localhost:1650/

d. Add the Grades.Web project to the list of startup projects for the solution.
e. Save all of the files.

X Task 2: Add a data service to the Grades.Web project


1. Add a new folder named Services to the Grades.Web project.

2. Add a new WCF Data Service named GradesWebDataService to the Services folder.
3. Add a reference to the Grades.DataModel project in the Grades.Web project.

4. 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.
5. 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. In the code in the Grades.WebDataService.svc file, add a using directive to bring the
Grades.DataModel namespace into scope.

2. 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.

2. In this operation, use a LINQ query against the CurrentDataSource object to retrieve and return all
of the students in the class.

3. In the InitializeService method, set the access rule for the StudentsInClass operation to
ServiceOperationRights.AllRead.

X Task 5: Build and test the data service


1. Build the solution, and then resolve any compilation errors.

2. View GradesWebDataService.svc in Windows Internet Explorer.

3. Verify that Internet Explorer displays an XML description of the entities that the data service exposes.

4. Close Internet Explorer.

5. 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. In Visual Studio, open the GradesPrototype.sln solution from the E:\Labfiles\Starter\Exercise 2 folder.

2. In the GradesPrototype project, remove the reference to the Grades.DataModel project.

3. Add a service reference to http://localhost:1650, using the namespace of Grades.DataModel.

4. 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. Add a new folder named DataModel to the GradesPrototype project.

6. Copy the following code files from the Grades.DataModel project to the GradesPrototype\DataModel
folder:

a. Classes.cs

b. customGrade.cs
c. 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. In the Views folder, in StudentsPage.xaml.cs, locate the Refresh method.

4. 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.

6. In LogonPage.xaml.cs, in the Logon_Click method, modify the statement that loads student data to
also load the user and grades data.

7. In the GradesPrototype solution, in the customTeacher.cs file, add a using directive to bring the
GradesPrototype.Services namespace into scope.

8. In the EnrollInClass method, modify the from statement to reference the Students collection in the
SessionContext.DBContext object.

9. 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
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. 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.
3. 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. Build the solution, and then resolve any compilation errors.
2. Log on as vallee with a password of password99.

3. Perform the following tasks to verify that the application still updates the data correctly:

a. Remove Eric Gruber from the class.


b. Enroll Jon Orton into the class.

c. Change the password to password88, and then verify that you can log on with the new
password.
d. Log on as grubere with a password of password.

e. Verify that his student profile appears, and then log off.

4. Close the application.


5. 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. In Visual Studio, open the GradesPrototype.sln solution from the E:\Labfiles\Starter\Exercise 3 folder.

2. In the GradesPrototype project, in StudentsPage.xaml.cs, create a new public class named


ImageNameConverter that implements the IValueConverter interface.

3. In the ImageNameConverter class, define a string constant named webFolder that contains the
string http://localhost:1650/Images/Portraits/.

4. Implement the IValueConverter interface.

5. 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.

6. Build the solution and resolve any compilation errors.

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 clr-
namespace:GradesPrototype.Views namespace. Assign this to xmlns:local. This is the namespace
that contains the ImageNameConverter class.

2. Add an instance of the ImageNameConverter class as a resource to the view.


3. 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:
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).

2. 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.

X Task 4: Add an Image control to the AssignStudentDialog control and bind it to the
ImageName property
1. In the XAML markup for the AssignStudentDialog control, add a reference to the clr-
namespace:GradesPrototype.Views namespace. Assign this to xmlns:local.

2. Add an instance of the ImageNameConverter class as a resource to the view.

3. 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. Build the solution, and then resolve any compilation errors.
2. Log on as vallee with a password of password88.

3. Verify that the students list now includes images.

4. View George Lis profile and verify that his image appears.

5. Remove George Li from the class.

6. 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.
7. Close the application.

8. 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 Accessinng Remote Data

Modu
ule Reviiew and
d Takea
aways

M
Module Revie
ew
In this module, yyou have learrned how to u
use the requesst and response classes in the System.Net
namespace to m manipulate rem mote data sou use WCF Data Services to expose and
urces directly and how to u
consume an enttity data model over the we eb.

Test Your Know


wledge

Q
Question

W
Which of the ffollowing corrrectly describ
bes how to acccess data tha
at is provided
d in an
H
HTTP response?

S
Select the corrrect answer.

Invoke
e the GetResp
ponseStream sstatic method on the HttpW
WebResponse class.

Read tthe ContentLe


ength instance
e property on
n the HttpWeb
bResponse ob
bject.

Invoke
e the GetRequ
uestStream insstance metho
od on the Http
pWebResponsse object.

Invoke
e the GetResp
ponseStream instance meth
hod on the HtttpWebRespon
nse object.

Invoke
e the GetResp
ponseStream instance meth
hod on the HtttpWebRequesst object.

Test Your Know


wledge

Q
Question

W
When you creeate a WCF Da ata Service to
o provide rem
mote access too an EDM, hoow do you
specify which entity sets th
he data servicce should mak
ke available to
t client appliications?

S
Select the corrrect answer.

Do no
othing. All entiity 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 9-2

Lesson 1: Using XAML to Design a User Interface 9-3

Lesson 2: Binding Controls to Data 9-19


Lesson 3: Styling a UI 9-30

Lab: Customizing Student Photographs and Styling the Application 9-39

Module Review and Takeaways 9-52


9-2 Designingg the User Interfacee for a Graphical Appplication

Modu
ule Ove
erview

An
n effective andd easy-to-use user interfacee (UI) is essential for graphical applicatio
ons. In this mo
odule, you
will learn how to
o use Extensibble Application Markup Lan nguage (XAML) and Windo ows Presentatiion
Foundation (WP PF) to create e
engaging UIs.

Ob
bjectives
e, you will be able to:
Aftter completing this module

Use XAML tto design a UI.

Bind a XAM
ML control to d
data.
Apply styless to a XAML UI.
U
Programmingg in Visual C# 9-3
3

Lesson 1
Using
g XAML to De
esign a User In
nterface
e

XAML is a decclarative, XMLL-based marku


X up language that
t you can u
use to create UIs for .NET FFramework
a
applications. D
Defining a UI in declarative
e markup, rathher than impeerative code, mmakes your UI more
f
flexible and portable. Using
g XAML also h helps to separrate your appllication 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 completting this lesson, you will be able to:

ow to use XAML to define the layout of a UI.


Explain ho
Describe some of the ccommon conttrols used by WPF
W applicatiions.

Create co
ontrols and set properties in
n XAML.

Handle evvents for XAM


ML controls.
Use layou
ut controls in X
XAML.

Create usser controls in XAML.


9-4 Designingg the User Interfacee for a Graphical Appplication

In
ntroducing
g XAML

XAAML enables yyou to define UI elements b by using a decclarative, XMLL-based syntaxx. When you u use XAML
in a WPF applicaation, you use e XML elemennts and attribu utes to represent controls aand their propperties. You
can use a varietyy of tools to ccreate XAML ffiles, such as Visual
V Studio, the Microsoftt Expression
suite, and
texxt editors. Wh
hen you build a WPF appliccation, the buiild engine con nverts the decclarative markkup in your
XAAML file into classes
c and ob bjects.

The following exxample showss the basic strructure 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>

XAAML 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 severral attributes. In the previou us example,
thee Window ele ement identiffies various XM ML namespace es that make built-in contrrols available ffor use. It
deefines a title, w
which is displaayed in the titlle bar of the aapplication, an
nd defines thee initial height and width
of the window.

A Window
W elem
ment can conttain a single cchild element that defines tthe content off the UI. In moost
ap
pplications, a U
UI requires mo ore than a single control, so
o WPF defines container coontrols that yoou can use
to combine other lower-levell controls toge ether and lay them out. The most comm monly used co ontainer
control is the Grrid control, an
nd when you add a new W Window to a WWPF project in n Visual Studio o, the
Window templaate automaticcally adds a G Grid control to
o the Windoww.

The Grid contro ol can containn multiple child controls thaat it lays out in
n a grid style. In the examp ple shown
ab
bove, the Grid d control contaains a single B
Button contro ol. The Grid control definess a default layyout that
consists of a single row and a single colum mn, but you ca an customize tthis layout byy defining add ditional
row
ws and colum mns as attributtes 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 alsso nest a grid control inside e a cell if you need to
pro
ovide finer coontrol over thee 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 Designingg the User Interfacee for a Graphical Appplication

Co
ommon C
Controls

The .NET Frameework providees a comprehe ensive collection of controlss that you cann use to imple
ement a UI.
Yo
ou can find the
e complete se
et in the Toolb window. You can also
box that is avaailable when yyou design a w
de
efine your ownn custom userr controls, as d
described in this lesson. The following taable summarizzes some of
the
e most comm monly used conntrols:

C
Control De
escription

B
Button Displays a button that a userr can click to perform an acction.

C
CheckBox En
nables a user to indicate wh
hether an item
m should be selected
s (checcked) or not
(b
blank).

C
ComboBox Displays a drop
p-down list off items from w
which the userr can make a selection.
s

L
Label Displays a piece
e of static texxt.

L
ListBox Displays a scrollable list of items from which the user can make a selection.

R
RadioButton En
nables the use
er to select fro
om a range off mutually excclusive option
ns.

T
TabControl O
Organizes the controls
c in a U
UI into a set o
of tabbed pages.

T
TextBlock Displays a read
d-only block o
of text.

T
TextBox En
nables the use
er to enter and edit text.
Programmingg 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 wayss. Most
c
controls ble you to set simple property values by using attributtes.
enab

T following example sho


The ows how to sett 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 easyy to use and in


T ntuitive for de
evelopers with h XML experieence. Howeve er, this syntax
d
does not provvide the flexib
bility that you need to definne more comp plex property values. Suppo ose that
i
instead of settting 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. YYou cannot de uances of a gradient effectt within an
efine all the nu
a
attribute value. Instead, XA
AML supports an alternative e way of settinng control pro
operties called
d property
e
element synta
ax. Rather thann specifying the Background property aas an inline atttribute of the e Button
e
element, you can add an element named d Button.Bacckground as a child element of the Buttton element,
a then in th
and he Button.Background ele ement, you caan add furtherr child elemen nts to define yyour gradient
e
effect.

The following example sho


T ows how to sett the properties of a button
n control by using
u propertyy element
s
syntax:

U
Using Properrty Element S
Syntax to Sett 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>
Programmingg in Visual C# 9-9
9

H
Handling Events

When you cre


W eate a WPF ap pplication in V each XAML page has a corrresponding code-behind
Visual Studio, e
f For example, the MainWindow.xamll file that Visual Studio creaates by default has a code-behind file
file.
n
named MainWWindow.xaml.cs. You subscribe to event handlers in yo our XAML maarkup and then define yourr
e
event handlerr logic in the ccode-behind ffile.

Note: V Visual Studio includes manyy features thatt make it easyy to create handlers for eveents.
FFor example, if you double e-click a Butto
on control at design
d time, V Visual Studio w
will automaticcally
c
create an event handler stu ub method in the code-beh hind file. It alsso automatically binds the Click
C
e
event of the button
b to the event handler method.

SSuppose you create a simp


ple application
n that consistss of a button aand a label. W
When you clickk the button,
y want an e
you event handlerr to add some abel. To do thiis, you need to do three things:
e text to the la
1
1. Make surre the button and the label include a Name property, so that you ccan reference the controls
in your co
ode.

2
2. Set the Click attribute of the button
n to the name
e of an event h
handler metho
od. This meth
hod runs
when thee Click event ooccurs.

The name of a control should be unique within the window that ho


Note: T olds the contro
ol;
ols in the same window sho
n two contro
no 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 Contrrols

SSupport for reelative positio nciples of WPF. The idea is that your app
oning is one off the core prin plication
s
should renderr correctly reggardless of how the user po ositions or resizes the appliccation windoww. WPF
i
includes severral layout, or container,
c con
ntrols that enaable you to poosition and sizze your child controls in
d
different wayss. The followin ng table show
ws the most co ommon layout controls:

Control Description

Canvas Child conttrols define th


heir own layou
ut by
specifying
g canvas coord dinates.

DockPanel Child conttrols are attacched to the ed


dges of the
DockPane el.

Grid Child conttrols are adde


ed to rows and
d columns
within the
e grid.

StackPanel Child conttrols are stackked either verttically or


horizontallly.

VirtualizingStackPanel Child conttrols are stackked either verttically or


horizontallly. At any one e time, only ch
hild items
that are viisible on the sscreen are created.

WrapPanel Child conttrols are adde


ed from left too right. If
there are too
t many con ntrols to fit on
n a single line,
the contro
ols wrap to thee next line.

T following example sho


The ows how to de
efine a grid wiith two rows aand two colum
mns:

U
Using a Grid Layout
<Grid>
<Grid.RoowDefinition
ns>
<RowD
Definition M
MinHeight="100" MaxHeigh
ht="200" />
<RowD
Definition H
Height="Auto" />
</Grid.RRowDefinitio
ons>
<Grid.CoolumnDefinit
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 0" Grid.Row="0" Grid.Column="0" />
<Label Content="This is Row 0, Column 1" Grid.Row="0" Grid.Column="1" />
<Label Content="This is Row 1, Column 0" Grid.Row="1" Grid.Column="0" />
<Label Content="This is Row 1, Column 1" Grid.Row="1" Grid.Column="1" />
</Grid>

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 fixed-
width 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: Ussing Desig
gn View to
o Create a XAML UII

IIn this demon


nstration, you will create a ssimple WPF ap
pplication thaat 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 demonstrration illustrattes various wa


T ays in which you can createe and configurre XAML files in Visual
S
Studio. It illustrates how yo ou can add controls to the design
d surface
e by double-cclicking a conttrol in the
t
toolbox. It shoows how you can configure e controls thro
ough a combiination of usinng designer toools and
e
editing XAMLL markup direcctly. It also illu
ustrates how VVisual Studio can automatically connect event
h
handlers to yoour controls.

D
Demonstra
ation Steps
1
1. Start the MSL-TMG1 viirtual machine
e if it is not already running
g.
2
2. Start the 20483A-SEA
A-DEV11-09 vvirtual machine.

3
3. Log on to a Student with the passwo
o Windows 8 as ord Pa$$w0rrd.

Note: Iff necessary, click Switch Usser to display the list of use
ers.

4
4. Switch to the Windowss 8 Start wind
dow.

5
5. Click Visu
ual Studio 20
012.
6
6. In Visual Studio, on the
e File menu, p
point to New,, and then clicck Project.

7
7. In the Ne ew Project dia
alog box, in th
he Templatess list, click Vissual C#, and tthen in the Prroject Type
list, click WPF
W Applica ation.
8
8. In the Na
ame box, type
e DesignView
w.

9
9. In the Loccation text bo
ox, set the loccation 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 aattribute to Orrder Your
Coffee H
Here.

1 Add the ffollowing marrkup between the opening and closing Grid
11. 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 code-
behind 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 Conttrols

When you wo
W ork with WPF, you can creatte your own sself-contained d, reusable use er controls in XAML. User
c
controls are soometimes called composite e controls, because they are a composite e of other conntrols. For
e
example, if yo
ou use the sam
me combinatio on of a text box and a buttton multiple times in a UI, iit might be
m
more conveniient to create and use a useer control that consists of tthe text box and the button n.
A
Alternatively, you might creeate a user co
ontrol to enab
ble multiple de evelopers to sshare the samme custom
c
control acrosss multiple asse
emblies.
LLike a regularr XAML windo
ow, user contro onding code-behind file. In
ols consist of a XAML file aand a correspo n
t XAML file, the principal difference is that the top--level elementt is a UserCon
the ntrol elementt 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 Usser Control in
n XAML
<UserControol x:Class="
"DesignView.CoffeeSelecttor"
xmlns="htttp://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/22006"
xmlns:d=""http://schemas.microsof
ft.com/expre
ession/blend/2008"
mc:Ignoraable="d"
d:DesignHHeight="300" d:DesignWid
dth="200">
<Grid>
<Grrid.RowDefinnitions>
<RowDefinition Height="2*"/>
<RowDefinition Height="2*"/>
<RowDefinition Height="2*"/>
<RowDefinition Height="1*"/>
</GGrid.RowDefinitions>
<SttackPanel Grrid.Row="0">
<Label Conntent="Do you want coffe
ee or tea?"/
/>
<RadioButtton x:Name="radCoffee" C
Content="Cof
ffee" HorizontalAlignmennt="Left"
VerrticalAlignment="Top" Ma
argin="5,5,5
5,5" GroupName="Beveragee"
IsCChecked="True" Checked="
"radCoffee_C
Checked" />
<RadioButtton x:Name="radTea" Cont
tent="Tea" HorizontalAl
H ignment="Lef
ft"
VeerticalAlignment="Top" M
Margin="5,5,5,5" GroupName="Beveragge"
Chhecked="radTea_Checked"/
/>
</SStackPanel>
<SttackPanel Grrid.Row="1">
<Label Conntent="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 tto Data

Most applicattions work witth data in one


M e form or anotther. The data a that drives yyour applicatio
on can come
f
from a wide vvariety of sourrces, such as files, databases, or web servvices. Almost e every graphical application
n
n
needs to connnect UI controols to an unde erlying data soource so that users can retrrieve, 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 completting 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 conttrols to collecttions of data.

Create daata templates to specify how data is rend


dered.
9-20 Designing the User Interfacce for a Graphical Application

In
ntroductio
on to Dataa Binding

Da nnecting a data source to a UI element in such a way that if one ch


ata binding is the act of con hanges, the
her must also change. Conceptually, datta binding con
oth nsists of three
e components:

g source. This is the source of your data, and is typically a property of a custom .NET object.
The binding
For example, you might bind a contro ol to the Coun
ntryOfOrigin property of a Coffee objecct.

The bindingg target. This is the XAML e


element you wwant to bind to
o your data soource, and is ttypically a
UI control. Y
You must bind your data so ource to a pro
operty of your target objecct, and that prroperty
must be a ddependency prroperty. For exxample, you mmight bind da
ata to the Conntent property of a
TextBox element.

The binding he Binding object can


g object. This is the object that connects the source to the target. Th
also specifyy a converter, if the source property and the target prooperty are of different dataa types.

Note: A ddependency property is a sp pecial type of wrapper arouund a regular property.


Deependency pro operties are re
egistered withh the .NET Fraamework runttime, which en nables the
runntime to notiffy any interestted parties whhen the value of the underlying propertyy changes. This
ab
bility to notify changes is wh hat makes datta binding wo ork. Most builtt-in UI elemen
nts implemen
nt
de
ependency pro operties and w will support data binding. FFor more information abou ut dependencyy
prooperties, see tthe Dependen ncy Propertiess Overview paage at
htttp://go.microssoft.com/fwlin nk/?LinkID=26 67829.

The following exxample showss a simple datta binding exp


pression:

mple Data Biinding


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 sett to a data bin
nding expression. Note thatt:

The Binding expression is enclosed in n braces. This e


enables you to
t set properties on the Bin
nding
object befo
ore it is evaluated by the Te
extBlock.
The Sourcee property of the
t Binding o object is set to
o {StaticReso
ource coffee1
1}. This is an o
object
instance de
efined elsewheere 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 Details

TwoWay Updates the target property when the source property changes, and
updates the source property when the target property changes.

OneWay Updates the target property when the source property changes.

OneTime Updates the target property only when the application starts or when the
DataContext property of the target is changed.

OneWayToSource Updates the source property when the target property changes.

Default 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 Interfacce for a Graphical Application

Biinding Co
ontrols to Data in XA
AML

Yo
ou can bind coontrols to dataa in various w
ways. If your so
ource data willl not change during the exxecution of
your application
n, you can creeate a static reesource to rep
present your data in XAML. A static resou urce
enables you to create
c instancces of classes. For example, if your assem
mbly contains a class named d Coffee,
you can define a static resourrce to create ana instance off Coffee and set propertiess on it. To create a static
ressource, you m
must:

Add an elem
ment to the R operty of a container contro
Resources pro e top-level Window.
ol, such as the

Set the nam


me of the elem ment to the naame of the claass you want to
t instantiate.. For example,, if you
want to create an instancce of the Cofffee class, creaate an elemen
nt named Cofffee. Use a nam mespace
prefix decla
aration to iden
ntify the nameespace and asssembly that ccontains your class.
Add an x:KKey attribute to the element. This is the id
dentifier by w
which you will specify the sttatic
resource in data binding expressions. You can creatte multiple insstances of a re
esource in a window,
w but
each instance should havve a unique x:Key value.

The following exxample showss how to creatte a static reso


ource for data
a binding:

Creating a Stattic 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 yyou want to bbind an individ


dual UI elemeent to this stattic resource, you can use a binding statement that
spe ecifies both a source and a path. You sett the Source property to th he static resou
urce, and set the
t Path
pro operty to the specific property in the source object too 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 Interfacce for a Graphical Application

Biinding Co
ontrols to Data in Co
ode

In real-world appplications, it is
i unlikely thaat your source
e data will be static.
s It is far more likely th
hat you will
rettrieve data at runtime fromm a database or o a web service. In these sccenarios, you cannot use a static
ressource to reprresent your da ata. Instead, yyou must use ccode to specify the data so ource for any UI bindings
at runtime.

The following exxample showss how to creatte data bindin


ng programm
matically for a T
TextBlock ele
ement
named textblocck1:

Creating a Data
a Binding in Code
p
private void mainWindow_
_Loaded(objeect sender, RoutedEventA
R Args e)
{
// Create a Coffee in
nstance to uuse as a data
a source.
Coffee cof
ffee1 = new Coffee();
coffee1.Na
ame = "Fourt
th Coffee Quuencher";
coffee1.Be
ean = "Arabi
ica";
coffee1.Co
ountryOfOrig
gin = "Venezzuela";
coffee1.St
trength = 3;
;
// Create a Binding o
object that references tthe Coffee i
instance.
Binding co
offeeBinding
g = new Bindding();
coffeeBind
ding.Source = coffee1;
coffeeBind
ding.Path = new ProperttyPath("Name");
// Add the
e binding to
o the Text pproperty of t
the TextBloc
ck.
textblock1
1.SetBinding
g(TextBlock.TextPropertyy, coffeeBin
nding);
}

In many cases yyou can use a mixture of XA


AML binding aand code bind ding. For exammple, you mig ght know
tha
at your UI elements will be bound to a Coffee
C instancce at design time. In this case, you can sp
pecify the
bin
nding paths inn XAML, and then
t set a DattaContext prroperty in codde.
The following exxample showss how to speccify 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 Interfacce for a Graphical Application

Biinding Co
ontrols to C
Collection
ns

want to data bind a control to a collection of objects. W


In many scenarios, you will w WPF includes controls
tha
at are designe
ed to render ccollections, such as the ListtBox control, the ListView control, the C
ComboBox
control, and the
e TreeView co ontrol. These ccontrols all inherit from the
e ItemsContrrol class and, as such,
sup
pport a comm mon approach h to data bind ding.

To
o bind a collecction to an Ite
emsControl in
nstance, you n
need to:

Specify the source data ccollection in the ItemsSourrce 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
Yo n ItemsContrrol instance to o any collectio
on that implem
ments the IEn
numerable intterface.
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 DissplayMemberrPath propertty (or a data ttemplate) in XXAML, and theen to set
the
e ItemsSourcce programma atically at runtime.
The following co
ode example shows how to
o set the Disp
playMemberP
Path propertyy in XAML:

Se
etting the DissplayMemberrPath Properrty
<
<ListBox x:Na
ame="lstCoff
fees" Displa
ayMemberPath=
="Name" />

Ha
aving set the D
DisplayMemb berPath prop
perty in XAMLL, you can now
w set the Item
msSource property in
code to compleete the data biinding.

The following exxample showss how to set the ItemsSource property in code:

Se msSource Property
etting the Item
/
// 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 Interfacce for a Graphical Application

Crreating Daata Templlates

Whhen you use ccontrols that d derive from thhe ItemsConttrol or Conten ntControl control, you can n create a
da
ata template to o specify howw your items are rendered. FFor example, ssuppose you w want to use a ListBox
control to displaay a collection
n of Coffee innstances. Each
h Coffee instance includes several prope erties to
rep
present the na ame of the co e of coffee beaan, the country of origin, and the streng
offee, the type gth of the
coffee. The dataa template spe ecifies how eaach Coffee instance shouldd be rendered, by mapping properties
of the Coffee in
nstance to child controls wiithin the data template. Cre eating a data template give es you
pre
ecise control oover how you ur items are re
endered and sstyled.

The following exxample showss how to defin


ne a data tem
mplate for a LisstBox control:

Creating a Data
a Template
<
<ListBox x:Na
ame="lstCofffees" Width=="200">
<ListBox.I
ItemTemplatee>
<DataTe
emplate>
<Gri
id>
<
<Grid.RowDeffinitions>
<RowDefinnition Heighht="2*" />
<RowDefinnition Heighht="*" />
<RowDefinnition Heighht="*" />
<RowDefinnition Heighht="*" />
<
</Grid.RowDeefinitions>
<
<TextBlock TText="{Binding Path=Namee}" Grid.Row
w="0"
Font
tSize="22" BBackground="B
Black" Foreg
ground="Whit
te" />
<
<TextBlock TText="{Binding Path=Beann}" Grid.Row
w="1" />
<
<TextBlock TText="{Binding Path=CounntryOfOrigin
n}" Grid.Row
w="2" />
<
<TextBlock TText="{Binding Path=Streength}" Grid
d.Row="3" />
>
</Grid>
</DataT
Template>
</ListBox.ItemTemplatte>
<
</ListBox>

Whhen you set th


he ItemsSourrce property o of this ListBox
x to a collection of Coffee objects, the d
data
tem
mplate specifiies how the LiistBox shouldd render each Coffee objecct. In this exam
mple, the dataa template
use
es a simple grrid layout and
d displays the name of the ccoffee with a larger font an
nd a contrastinng
background. Ho owever, you caan make yourr data templattes as comple ex and sophistticated 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 Interfacce for a Graphical Application

Lesson 3
Styling
g a UI

If yyou had to styyle a graphica


al application by setting pro
operties on on ne control at a time, the de
evelopment
pro ocess would qquickly becom me laborious. It
I would also be difficult too maintain youur application, as you
wo ould often nee ed to make thhe same chang ge in multiple
e locations. XA
AML enables yyou to define styles as
reu usable resourcces that you ccan apply to m
multiple contrrols.

In this lesson, yo
ou will learn h
how to use styyles and animaations.

Le
esson Obje
ectives
Aftter completing this lesson, you will be ab
ble to:

Create reussable resource


es in XAML.

Define style
es that apply tto multiple co
ontrols.

Use propertty triggers to apply styles when


w conditio
ons are met.

Use animations to create


e dynamic effe
ects and transsformations.
Programming in
i Visual C# 9-31
1

C
Creating R
Reusable Resourcess in XAMLL

ments, such ass data templates, styles, and


XAML enabless you to creatte certain elem
X d brushes, as reusable
r
resources. This has various advantages wwhen 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 resourcce.

Your XAM
ML files are shorter and easier to read.

Every WPF control has a Re


E esources prop perty to whichh you can addd resources. This is because e the
R
Resources prroperty is defined by the FrrameworkEle ement class from which all WPF elementts ultimately
d
derive. In mosst cases, you d ot element in a file, such as the Window
define resourcces on the roo w element or
t UserConttrol element. The resourcess are then ava
the descendants.
ailable to the rroot element and all of its d
Y can also create
You c resourcces for use across the entire
e application by defining thhem in the Ap pp.xaml file.

Note: Every WPF app plication has aan App.xaml ffile. It is a XAM
ML file that can contain gloobal
rresources used by all windo
ows and contrrols in a WPF application. Itt is also the en ntry point for the
a
application, and defines wh
hich window sshould appear when an app plication startts.

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 aas a window-level resource:

C
Creating and
d Using Resou
urces
<Window x:CClass="DataBBinding.MainW
Window"
xmlns=
="http://schemas.microsooft.com/winf
fx/2006/xaml/presentatio
on"
xmlns:x="http://schemas.microosoft.com/winfx/2006/xaml"
Title=
="Reusable Resources" Heeight="350" Width="525">
<Window..Resources>
<Sol
lidColorBrussh x:Key="MyBrush" Color
r="Coral" />
>

</Windoww.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

IIn many casess, you will wan nt to apply the same prope erty values to multiple conttrols of the sam me type
w
within an appplication. For e
example, if a p
page containss five textboxe es, you will proobably want e each textbox
t have the saame foreground color, backkground color, font size, an
to nd so on. To m make this consistency
e
easier to manage, you can create Style e elements as reesources in XAAML. Style ele ements enable you to
a
apply a collecction of propeerty values to ssome or all co
ontrols of a paarticular type.. To create a sstyle, perform
t following steps:
the
1
1. Add a Sty
yle element to
o a resource ccollection with
hin your appliication (for exxample, the
Window..Resources co ollection or a resource dictionary).

2
2. Use the T
TargetType atttribute of thee Style eleme
ent to specify tthe type of co
ontrol you want the style
to target (for example,, TextBox or Button).

3
3. Use the x
x:Key attributee of the Style
e element to enable
e controls to specify th his style. Alterrnatively, you
can omit the x:Key atttribute and yoour style will aapply to all controls of the sspecified type e.

4
4. Within th
he Style eleme
ent, use Sette
er elements to
o apply specifiic values to sp
pecific propertties.

T following example sho


The ows how to cre
eate a style th
hat targets Tex
xtBlock controls:

C
Creating Stylles
<Window.Res
sources>
<Style TargetType=="TextBlock" x:Key="Bloc
ckStyle1">
<Se
etter Properrty="FontSize" Value="20
0" />
<Se
etter Properrty="Background" Value="
"Black" />
<Se
etter Properrty="Foreground">
<Setter.Va
alue>
<Linea
arGradientBrush StartPoi
int="0.5,0" EndPoint="0.5,1">
<L
LinearGradientBrush.Grad
dientStops>
<GradientStop Offset=
="0.0" Colorr="Orange" />
<GradientStop Offset=
="1.0" Colorr="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 caan specify prooperty values that are only applied when n certain
c
conditions aree true. For exaample, you might want to cchange the fo ont style of a b
button when the t user
h
hovers over itt, or you mighht want to app
ply a highlightting effect to selected itemms in a list boxx.
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 identtifies 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 chhanges to pro
operty values.

The following example sho


T ows how to ma
ake the text o old while the user is hovering over the
on a button bo
b
button:

U
Using a Prop
perty Trigger
<Window.Res
sources>
<Style TargetType=="Button">
<St
tyle.Triggerrs>
<Trigger P
Property="IsMouseOver" V
Value="True"
">
<Sette
er Property="FontWeight"
" Value="Bold" />
</Trigger>
>
</S
Style.Triggeers>
</Style
e>

</Window.Re
esources>
9-36 Designing the User Interfacce for a Graphical Application

Crreating Dy
ynamic Trransforma
ations

Sophisticated grraphical applications often use animatio ons to make thhe user experiience more enngaging.
Annimations are sometimes ussed to make ttransitions bettween states less abrupt. Foor example, if you want
to enlarge or ro
otate a picture
e, increasing th gressively over a short
he size or chaanging the orientation prog
tim
me period can witching from one size or o
n look better tthan simply sw orientation to another.

To
o create and apply an animaation effect in
n XAML, you n
need to do three things:

1. Create an aanimation.
WPPF includes vaarious classes that you can use to create animations in n XAML. The m most common nly used
animation element is Double eAnimation. T The DoubleA Animation ele ement specifie
es how a valuee should
change over tim
me, by specifyiing 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
To mation to an object, you need to wrap yyour animatioon in a Storyb
board element. The
Sto erty you wantt to animate. It does this
oryboard element enabless you to speciffy the object aand the prope
byy providing the
e TargetNamme and TargetProperty atttached properties, which yo ou can set on child
animation elements.
3. gger.
Create a trig

o trigger your animation in response to a property chaange, you nee


To ed to wrap your storyboard d in an
Ev
ventTrigger e element. The E
EventTriggerr element speccifies the conttrol event thatt will trigger tthe
animation. In th
he EventTriggger element, yyou can use a BeginStoryb board elemen nt to launch th he
animation.

Yo
ou can add an EventTrigge er element containing yourr storyboards and animations to the Trig ggers
collection of a Style
S element, or you can add ers collection of an individual control.
a it directly to the Trigge

The following exxample showss how to use an


a animation to rotate and
d expand an im
mage when th
he user
cliccks 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 Interfacce for a Graphical Application

Demonstration: Customizing Student Photograp


P phs and Sttyling the
e
pplication
Ap n Lab

In this demonstration, you wiill learn aboutt the tasks thaat you will perrform in the laab for this mo
odule.
Programming in
i Visual C# 9-39
9

Lab: Custommizing S
Student Photo
ographs and S
Styling tthe
Appllication
n

S
Scenario
Now that you
N u and The Schoool of Fine Arrts are happy with the basicc functionalityy of the appliccation, you
n
need ove the appeaarance of the interface to g
to impro 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 wiill enable you to display ph
hotographs off students in
t student lisst and other views.
the v You also
o decide to crreate a fluid m
method for a tteacher to rem
move a
s
student from their class.

FFinally, you w
want to update
e the look of tthe various vie
ews, keeping their look con
nsistent acrosss the
a
application.

O
Objectives
A
After completting this lab, you
y will be able to:

Create an
nd use user co
ontrols.

Use styless and animatio


ons.
E
Estimated Tim
me: 60 minutes

3A-SEA-DEV11-09, MSL-TM
Virtual Machine: 20483 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. Start the MSL-TMG1 virtual machine if it is not already running.
2. Start the 20483A-SEA-DEV11-09 virtual machine and log on as Student with the password
Pa$$w0rd.

3. Start Visual Studio, and then open the Grades.sln solution from the E:\Labfiles\Starter\Exercise 1
folder.

4. Set the following projects to start without debugging at startup:

a. Grades.Web

b. Grades.WPF

5. Add a new WPF user control named StudentPhoto.xaml to the Controls folder in the Grades.WPF
project.
6. 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.

b. 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.
c. 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
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/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>

7. 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

8. 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.

2. 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 Margin: 0:

o Orientation: Horizontal

o HorizontalAlignment: Center
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. Add an ItemTemplate element to the ItemsControl. This element will specify how each photograph
is displayed and formatted.

4. 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.

2. In the Student_Click method, raise the StudentSelected event.

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.

2. 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}

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. Add a private method named RemoveStudent_MouseLeave that takes an object and a


MouseEventArgs parameter and returns void.

7. 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.
9. 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" />
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. Build the solution and resolve any compilation errors.
2. Run the application.

3. Log on as vallee with a password of password99.

4. Verify that the students list appears with photographs.


5. In the student list, hover over the red x for the student Martin Weber.

6. Verify that the student photograph for Martin Weber becomes transparent and that the red x
becomes opaque.

7. Move the cursor away from the red x and verify that the student photograph becomes opaque and
that the red x becomes transparent.

8. Click the red x for Martin Weber, verify that the Student message box appears, and then click Yes.
9. 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. In Visual Studio, open the Grades.sln solution from the E:\Labfiles\Starter\Exercise 2 folder.

2. Set the following projects to start without debugging at startup:

a. Grades.Web
b. Grades.WPF

3. In the Grades.WPF project, in the Views folder, open LogonPage.xaml.

4. In the LogonPage user control, define a style named LoginTextBoxStyle, based on the
TextBoxStyle style, and targeting text boxes.

5. 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. Add another style named PasswordBoxStyle targeting password boxes.

8. Use the following information to set properties of the style:


Margin: 5

FontSize: 24

MaxLength: 16

9. 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. In the Themes folder, open the Generic.xaml file.

2. Locate the <!-- TODO: Exercise 2: Task 2a: Define the label styling used throughout the application --
> comment near the end of the file.

3. 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

4. Locate the <!-- TODO: Exercise 2: Task 2b: Define the text styling used throughout the application -->
comment.
5. 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. In the Controls folder, open the StudentPhoto.xaml file.

2. 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. 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

5. 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
6. Add another Storyboard that will contain animations that are performed when the mouse leaves the
control; set the x:Key property to sbMouseLeave.

7. 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

8. 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. In the StudentPhoto.xaml.cs file, locate the Storyboard region.

2. 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. Add code to define the OnMouseLeave event handler that triggers the mouse leave animation
(sbMouseLeave).

4. In the Views folder, open the StudentsPage.xaml.cs file.

5. 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. Add another event handler called Student_MouseLeave that forwards the MouseLeave event to the
StudentPhoto control.

7. 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. Build the solution and resolve any compilation errors.

2. Run the application.

3. Log on as vallee with a password of password99.

4. 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. 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
6. 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 Interfacce for a Graphical Application

Modu
ule Reviiew and
d Takea
aways

M
Module Revie
ew
In this module, yyou learned how
h to create engaging UIss for graphical applicationss. You learned how to
usee XAML to creeate windowss and user conntrols and how
w you bind co ontrols to dataa items and co ollections.
Yoou also learned
d how to provvide a consiste
ent user experience by creaating styles ass reusable reso
ources.

Test Your Know


wledge

Q
Question

Y
You want to u
use rows and columns to laay out a UI. W
Which contain
ner control sh
hould you
u
use?

S
Select the corrrect answer.

The Ca
anvas control.

The Do
ockPanel control.

The Grid control.

The SttackPanel control.

The W
WrapPanel con
ntrol.

Test Your Know


wledge

Q
Question

YYou are creating an applicaation that enaables users to


o place orderss for coffees. The
aapplication sh
hould allow ussers to select the drink the
ey want fromm a list. Each liist item
should displayy the name off the coffee, the
t descriptio on, the price, and an image of the
ccoffee. How shhould you prroceed?
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 10-2

Lesson 1: Implementing Multitasking 10-3

Lesson 2: Performing Operations Asynchronously 10-20


Lesson 3: Synchronizing Concurrent Access to Data 10-36

Lab: Improving the Responsiveness and Performance of the Application 10-46

Module Review and Takeaways 10-53


10-2 Improviing Application Perfformance and Respoonsiveness

Modu
ule Ove
erview

Mo odern processsors use threaads to concurrrently run multiple operatio ons. If your ap
pplication perfforms all of
its logic on a sin
ngle thread, yo
ou do not maake the best use of the avaiilable processing resources,, which can
ressult in a poor experience fo
or your users. In this module, you will leaarn how to immprove the perrformance
of your applicattions by distrib
buting your o
operations acrross multiple tthreads.

Ob
bjectives
Aftter completing this module
e, you will be able to:

Use the Tassk Parallel Librrary to implem


ment multitasking.
Perform lon
ng-running op
perations with
hout blocking threads.

Control how
w multiple thrreads can acce
ess resources concurrently..
Programming in
i Visual C# 10-3
3

Lesson 1
Implementiing Multitasking

A typical grapphical applicattion consists o


of blocks of coode that run w
when an evennt occurs; thesse events fire
i response to
in o actions such he mouse, or opening a window. By
h as the user cclicking a buttton, moving th
d
default, this co
ode runs by uusing the UI thhread. Howevver, 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 unresponsivve. Also, runniing all of yourr
c
code on a sing gle thread dooes not make g good use of aavailable processing power in the compu uter; most
m
modern machhines contain multiple proccessor cores, aand running all operations oon a single th
hread will onlyy
u a single p
use processor coree.

The Microsoftt .NET Framework now in


T ncludes the Ta
ask Parallel Lib
brary. This is a set of classess that makes
i easy to distrribute your co
it ode execution n across multip
ple threads. Y
You can run th hese threads ono different
p
processor cores and take advantage of tthe parallelismm that this moodel provides. You can assig gn long-
r
running tasks to a separatee thread, leaving the UI thre
ead free to respond to userr actions.
IIn this lesson, you will learn t Task Paralllel Library to create multithreaded and responsive
n how to use the
a
applications.

L
Lesson Ob
bjectives
A
After completting this lesson, you will be able to:

Create tasks.

how tasks are executed.


Control h

alues from tasks.


Return va

Cancel long-running ta
asks.

Run multiple tasks in p


parallel.

Link taskss together.

Handle exxceptions that tasks throw.


10-4 Improviing Application Perfformance and Respoonsiveness

Crreating Taasks

The Task class lies at the heart of the Taskk Parallel Libraary in the .NETT Framework. As the name suggests,
you use the Tassk class to reppresent a task, or in other words,
w a unit o
of work. The TTask class enables you to
peerform multiplle tasks concuurrently, each on a differentt thread. Behind the sceness, the Task Parallel
Lib
brary manages the thread p pool and assig
gns tasks to th hreads. You caan implementt sophisticated d
mu ultitasking fun
nctionality by using the Tassk Parallel Librrary to chain ttasks, pause taasks, wait for tasks to
complete before e continuing, and perform many other o operations.

Crreating 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
thiis code as a parameter to the constructo
or. You can provide this cod
de in a methood and create an Action
de
elegate that w wraps this meth
hod.

Note: A ddelegate proviides a mechannism for refereencing a blocck of code or a method. Thee
Acction class is a type in the .NET Framewo nvert a method
ork Class Libraary that enables you to con
intto a delegate. The method cannot return n a value, but it can take paarameters. The .NET
Fraamework Classs 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 taskk 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}", DatteTime.Now);
;
}

Ussing an Actionn delegate reqquires that yo


ou have define ed a method that
t contains the code thatt you want
to run in a task. However, if the
t sole purpo ose of this meethod is to pro
ovide the logicc for a task an
nd it is not
reu
used anywherre 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 diffficult. A more common app proach is to use an
anonymous metthod. An anon nymous meth hod is a metho od without a name,
n and yoou 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 Exxecution

The Task Paraallel Library offfers several different appro


T oaches that yo
ou can use to start tasks. Th
here are also
v
various ent ways in which you can pause the exe
differe ecution of you
ur code until one
o or more ttasks have
c
completed.

S
Starting Ta
asks
When your co
W ode starts a taask, the Task P
Parallel Libraryy assigns a thrread to your ttask and startss running thatt
t
task. The task runs on a sep parate thread,, so your code e does not need to wait forr the task to complete.
I
Instead, the taask and the coode that invokked the task ccontinue to ru un in parallel.

I you want to
If o queue the taask 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 tthe static Task


A kFactory class to create an
nd queue a tassk with a single line of
c
code. The TasskFactory class is exposed through the sstatic Factory y property of the
t Task classs.

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.Facttory.StartNew
T w method is highly configuurable and acccepts a wide range of para ameters. If
y simply waant to queue some code with the default scheduling o
you options, you ccan use the sttatic
T
Task.Run method as a shoortcut 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 forr Tasks
IIn some casess, you may nee ed to pause the execution of your code until a particu
ular task has ccompleted.
T
Typically you do this if your code depennds on the result from one or
o more taskss, or if you neeed to handle
e
exceptions thaat a task may throw. The Task class offers various me
echanisms to ddo 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 ffrom a Task

FFor tasks to be effective in real-world sceenarios, you nneed to be abble to create taasks that can return values,,
o results, to tthe code that initiated the ttask. The regu
or ular Task classs does not enable you to do this.
H
However, the Task Parallel Library also in
ncludes the geeneric Task<T TResult> classs 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 ttype of the
r
result that the
e task will retu
urn. The Task<TResult> class exposes a read-only prroperty named d Result.
A
After the task has finished eexecuting, you can use thee Result propeerty to retrievve the return vvalue of the
t
task. The Resu ult property iss the same type as the taskks type param
meter.

T following example sho


The ows how to use the Task<T
TResult> classs.

R
Retrieving a Value from a Task
// Create a
and queue a task that returns the dday 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);

IIf you access the


t Result prooperty 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 Improoving Application Performance and Respponsiveness

Caancelling Long-Run
nning Task
ks

Tasks are often used to perfo orm long-runn ning operation ns without bloocking the UI thread, becau use of their
asyynchronous nature. In some cases, you w will want to giive your userss the opportunnity to cancel a task if
theey are tired off waiting. How
wever, it would be dangero ous to simply aabort the taskk on demand, because
thiis could leave your applicattion data in an unknown sttate. Instead, tthe Task Paralllel Library use
es
canncellation tokkens to supporrt a cooperativve cancellatio
on model. At a high level, thhe cancellatio
on process
woorks as followss:
1. When you create
c a task, you also create a cancellattion token.

2. You pass th
he cancellation
n token as an argument to your delegate method.

3. On the threead that created the task, you request cancellation by calling the Ca
ancel method
d on the
cancellation
n token sourcee.

4. In your taskk method, youu can check thhe status of th n token at anyy point. If the instigator
he cancellation
has requestted that the taask be cancelled, you can teerminate your task logic grracefully, posssibly rolling
back any ch hanges resulting from the wwork that the task has perfoormed.

Typically, you w
would check wwhether the caancellation tokken has been set to cancele ed at one or mmore
convenient poinnts in your tassk logic. For exxample, if you
ur task logic itterates over a collection, yo
ou might
check for cancellation after e
each iteration.

The following co
ode example shows how to
o cancel a taskk.

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 Improoving Application Performance and Respponsiveness

Ru
unning Taasks in Parrallel

The Task Paralle


el Library inclu
udes a static class
c named Parallel.
P The P
Parallel class p
provides a ran
nge of
meethods that yo
ou can use to execute taskss simultaneou usly.

Ex
xecuting a S
Set of Task
ks Simultane
eously
un a fixed set of tasks in paarallel, you can use the Parrallel.Invoke m
If yyou want to ru method. Whe en you call
thiis method, you use lambdaa expressions tto specify the tasks that you want to run n simultaneouusly. You do
noot need to expplicitly create each
e taskth he tasks are created implicittly from the d
delegates that you supply
to the Parallel.IInvoke metho od.

The following co
ode example shows how to
o use the Para
allel.Invoke m
method to run
n several taskss in parallel.

Ussing 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 tthat you can use
u to run forr and foreach loop iteration ns in
parallel. Clearly it will not alw
ways be appro ns in parallel. For example, if you want
opriate to run loop iteration
to compare sequential valuess, you must ru un your loop iterations sequuentially. How wever, if each loop
ite
eration represeents an independent opera ation, running loop iterations in parallel enables you tto maximize
your use of the available proccessing power.

o run for loop iterations in parallel, you ccan use the Pa


To arallel.For meethod. This m
method has sevveral
ovverloads to catter to many different scenaarios. In its sim
mplest form, th
he Parallel.Fo
or method takkes three
parameters:

An Int32 paarameter thatt represents th


he start index for the operaation, inclusive
e.

An Int32 paarameter thatt represents th


he end index ffor the operattion, exclusive
e.

An Action<
<Int32> deleg
gate that is exxecuted once per iteration..

The following co ode example shows how to o use a Parallel.For loop. Inn this example
e, each elemeent of an
arrray is set to th
he square roott of the indexx value. This is a simple exam
mple of a loop in which the
e order of
thee iterations dooes not matteer.
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 Taasks

SSometimes it is useful to seequence tasks. For example e, you might require that if a task comple etes
s
successfully, aanother task iss run, or if the
e task fails, a different
d task iis run that possibly needs tto perform
s
some kind of recovery proccess. 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 tassks if the workk that it needss to perform is also multith
A hreaded in
n
nature. The paarent task (thee task that spa awned the neew or nested taasks) can waitt for the neste
ed tasks to
c
complete befoore it finishes itself, or it can return and let the child tasks continue
e running asyn nchronously.
T
Tasks use the parentt task to wait are called chiild tasks.
that cau

C
Continuatio
on Tasks
Continuation tasks enable yyou to chain multiple
C m taskss together so tthat they execcute one afterr another.
T task that invokes anoth
The her task on co
ompletion is kknown as the antecedent,
a an
nd the task th
hat it invokes
i known as th
is he continuatio
on. You can paass data from the antecede ent to the conntinuation, andd you can
c
control the exxecution of the task chain in various wayys. To create a basic continuuation, you usse the
T
Task.Continu ueWith metho od.

T following code example shows how to create a taask continuatiion.


The

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 creatte the continu
uation task, yoou are providiing 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 Improoving Application Performance and Respponsiveness

Handling T
Task Excep
ptions

Wh hen a task thrrows an excep ption, the exce pagated back to the thread that initiated
eption is prop d the task
he joining threead). The task might be linkked to other taasks through continuationss or child taskks, so
(th
muultiple exceptions may be tthrown. To en nsure that all e
exceptions are
e propagated back to the jo oining
thrread, the Taskk Parallel Libraary bundles an
ny exceptionss together in aan Aggregate
eException o object. This
obbject exposes aall of the exceeptions that o
occurred throu ugh an InnerEExceptions co
ollection.

To
o catch excepttions on the jo
oining thread,, you must wa e. You do this by calling
ait for the taskk to complete
the
e Task.Wait mmethod in a try block and then catching g an Aggrega ateException exception in n the
corresponding ccatch block. A common exxception-hand dling scenario is to catch the
Ta
askCanceledE Exception excception that is i thrown wheen you cancel a task.
The following co
ode example shows how to
o handle task exceptions.

Ca
atching Task Exceptions
s
static void MMain(string[
[] args)
{
// Create a cancellattion token s
source and obbtain a canc
cellation to
oken.
CancellatiionTokenSour
rce cts = ne
ew CancellatiionTokenSour
rce();
CancellatiionToken ct = cts.Token
n;
// Create and start a long-running task.
var task1 = Task.Run((() => doWor
rk(ct),ct);
// Cancel the task.
cts.Cancell();
// Handle the TaskCannceledExcept
tion.
try
{
task1.W
Wait();
}
catch(AggregateExcepttion ae)
{
foreach
h(var inner in ae.Inner
rExceptions)
{
if(i
inner is Tas
skCanceledEx
xception)
{
C
Console.Writ
teLine("The task was canncelled.");
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 Improoving Application Performance and Respponsiveness

Lesson 2
Perforrming Operati
O ions Assynchro
onously
y

An
n asynchronouus operation is an operation that runs onn a separate thread; the thrread that initiaates an
operation doess not need to wait for that operation to complete beffore it can con
asyynchronous o ntinue.

Asynchronous o operations aree closely relate


ed to tasks. Th
he .NET Frame ework 4.5 inclludes some ne ew features
tha
at make it eassier to perform
m asynchrono ous operationss. These operaations transpaarently create new tasks
and coordinate their actions, enabling you u to concentraate on the bussiness logic off your application. In
particular, the a
async and awa ait keywords enable you to o invoke an assynchronous operation
o andd wait for
the
e result within
n a single metthod, without blocking the thread.

In this lesson, yo
ou will learn vvarious techniq
ques for invokking and man
naging asynch
hronous operaations.

Le
esson Obje
ectives
Aftter completing this lesson, you will be ab
ble to:
Use the Disspatcher obje
ect to run code on a specific thread.

Use the asy


ync and awaitt keywords to
o run asynchro
onous operations.

Create methods that are compatible with


w the awaitt operator.
Create and invoke callbaack methods.

hronous Programming Mod


Use the Tassk Parallel Librrary with traditional Asynch del (APM)
implementaations.
Handle exce
eptions that aasynchronous operations th
hrow.
Programming in Visual C# 10-21
1

U
Using the
e Dispatcher

IIn the .NET Frramework, eacch thread is asssociated withh a Dispatche er object. The dispatcher is responsible
f maintainin
for ng a queue off work items fo or the thread.. When you work
w across muultiple threads, for
e
example, by running asynchronous taskss, you can use e the Dispatch her object to invoke logic ono a specific
t
thread. You tyypically need to do this when you use assynchronous o operations in graphical app plications. For
e
example, if a user
u button in a Wiindows Pressentation Foundation (WPFF) application,, the click
clicks a b
e
event handlerr runs on the UI thread. If the event hand dler starts an asynchronouss task, that tassk 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 thhe UI thread.

Consider a sim
C mple WPF app plication that consists of a b
button namedd 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 many scenarios, your applications might retrieve data
perty, but in m
f
from web servvices or datab
bases in response to activityy on the UI.

T following code example shows how you might atttempt to upd


The om your task llogic.
date the UI fro

T Wrong Way
The W to Update a UI Objecct
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;
}

IIf you were to


o run the precceding code, yyou would gett an InvalidO OperationExce eption excepttion with the
m
message Thee calling thread cannot acce d owns it. This is because
ess this objectt because a diifferent thread
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 conttents of the lb y must run the SetTime method on the UI thread.
blTime label, you
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 keywwords were inttroduced in thhe .NET Frame ework 4.5 to make
m it easier to perform
a
asynchronouss operations. Y
You use the async modifierr to indicate tthat a method d is asynchron nous. Within
t async me
the ethod, you use e the await opperator to ind
dicate points aat which the execution
e he method
of th
c be suspen
can nded while yoou wait for a lo
ong-running o operation to return. While the method is suspended
a an await point, the threa
at ad that invokeed the metho od can do othe er work.

Unlike other aasynchronous programming techniques,, the async an


U words enable you to run
nd await keyw
l
logic asynchroonously on a ssingle thread.. This is particularly useful w
when you wannt to run logicc on the UI
t
thread, becau
use it enables yyou to run loggic asynchron nously on the same thread without blockking the UI.

Consider a sim
C mple WPF app plication that consists of a b
button named d btnLongOp peration and a label
n
named lblRessult. When the user clicks tthe button, the event handler invokes a llong-running operation. In n
t example, it simply sleeps for 10 seco
this onds and then n returns the rresult Operattion 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 iss
c
complete, thee event handle
er updates the e lblResult label with the rresult of the o
operation.

The following code example shows an application thaat performs a synchronous long-running
T 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;
}

IIn this example, the final sttatement in thhe event hand dler blocks the
e UI thread unntil the result o
of the task is
a
available. Thiss means that tthe UI will effe
ectively freeze
e, and the use
er will be unab
ble to resize thhe window,
m
minimize the window, and so on. To enaable the UI to remain respo onsive, you can convert the e event
h
handler into aan 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 Methodss

The await operator is always used to aw


T wait the completion of a Task instance in
n a non-blockking manner.
I you want to
If o create an asyynchronous mmethod that yyou can wait fo
or with the aw
wait operatorr, your
m
method must return a Taskk object. Whe en you convert a synchronoous method to an asynchro onous
m
method, use tthe following guidelines:

If your synchronous method returnss 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> objectt.

An asynchron
A nous method ccan return void; however, this
t is typicallyy only used fo
or event hand
dlers.
W
Wherever posssible, you sho
ould return a T
Task object to
o enable calle
ers to use the await operattor 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<striing>.

Modify th
he method log
gic to use the
e await operattor 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 aand Invok
king Callbaack Metho
ods

IIf you must ru


un complex lo
ogic when an asynchronous
a s method commpletes, you can configure your
a
asynchronous s method to innvoke a callbaack method. The
T asynchron nous method passes data to o the callbackk
m
method, and the callback m
method proce esses the data. You might aalso use the caallback metho
od to update
t UI with th
the he processed rresults.

To configure aan asynchronous method tto invoke a caallback method, you must include a delegate for the
T
c
callback methhod as a param
meter to the aasynchronous method. A caallback metho od typically acccepts one or
m
more argume ents and does not return a value.
v This maakes the Actio
on<T> delegate a good ch hoice to
r
represent a caallback metho
od, where T is the type of your argumentt. If your callb
back method requires
r
m
multiple arguments, there aare versions o
of the Action delegate thatt accept up too 16 type paraameters.
Consider a WPF application
C n that consistss of a button named btnGe etCoffees andd a list namedd lstCoffees.
W
When the use
er clicks the bu
utton, the eve
ent handler invokes an asynnchronous me ethod that rettrieves a list off
c
coffees. When n the asynchroonous data reetrieval is com
mplete, the me
ethod invokes a callback me ethod. The
c
callback methhod removes aany duplicatess from the ressults and thenn displays the updated resuults in the
l
listCoffees lisst.

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 Fraamework classses that supp


M port asynchron
nous operatioons do so by immplementing a design
p
pattern known as APM. The e APM pattern is typically implemented as two metho ods: a
B
BeginOperati ionName metthod that startts the asynchrronous operattion and an En ndOperationNName
m
method that p
provides the rresults of the asynchronouss operation. Y
You typically call the EndOp
perationNamee
m
method from within a callbback method. For example, the HttpWeb bRequest class includes methods
n
named BeginnGetResponse e and EndGettResponse. The BeginGetResponse me ethod submitss 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 Intternet resourcce 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 returnns an IAsyncRResult objectt, and the
E
EndOperation nName metho od includes an
n IAsyncResuult parameter.

The Task Paraallel Library makes it easier to work with classes that im
T mplement the
e APM pattern n. Rather than n
i
implementing g a callback mmethod to call the EndOperrationName m method, you caan use the
T
TaskFactory. FromAsync m method to invvoke the operration asynchrronously and return the ressult in a single
e
s
statement. he TaskFactorry.FromAsyncc method includes several overloads to accommodate APM
Th
m
methods that take varying numbers of arguments.
a

Consider a WPF application


C n that verifies URLs that a u
user provides. The applicatiion consists off a box
n
named txtUrll, a button named btnSubm mitUrl, and a label named lblResults. T The user types a URL in the
b and then clicks the buttton. The clickk event handle
box er for the buttton submits aan asynchrono ous web
r
request to the
e URL and theen displays the e status code of the respon
nse in the labeel. 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 enttire operationn.

The following code example shows how to use the Ta


T askFactory.FrromAsync me
ethod to subm
mit an
a
asynchronouss web request and handle tthe 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: Ussing the T
Task Parallel Library
y to Invoke
e APM Op
perations

This demonstration explain


T ns how to convert an appliccation that use es a traditiona
al APM implementation to
u the Task P
use Parallel Libraryy instead. The
e demonstration illustrates how the Taskk Parallel Libra
ary approach
r
results in shorrter and simpller code.

D
Demonstra
ation Steps
1
1. Start the MSL-TMG1 viirtual machine
e if it is not already running
g.

2
2. Start the 20483A-SEA
A-DEV11-10 vvirtual machine.
3
3. Log on to
o Windows 8 as
a Student with the passwo
ord Pa$$w0rrd.

Note: Iff necessary, click Switch Usser to display the list of use
ers.

4
4. Switch to the Windowss 8 Start wind
dow.

5
5. Click Visu
ual Studio 20
012.

6
6. In Microssoft Visual Studio, on the File menu, po
oint to Open,, and then clicck Project/So
olution.
7
7. In the Op
pen Project dialog box, bro
owse to the E::\Democode\\Starter folde
er, click APMT
Tasks.sln,
and then click Open.

8
8. On the Build menu, click Build Solu
ution.
9
9. On the D
Debug menu, cclick Start Wiithout Debug
gging.

1 In the texxt box, type htttp://www.co


10. ontoso.com, and then click Check URL.

1 Notice th
11. hat the label d
displays the message The URL ng status code: OK.
U returned the followin
1 Close the
12. e MainWindo
ow window.

1 In Solutio
13. on Explorer, exxpand MainW
Window.xamll, and then do ainWindow.x
ouble-click Ma xaml.cs.

1 Review th
14. he code in the
e MainWindo
ow class:
a. Noticce that the bttnCheckUrl_C
Click method creates an HtttpWebReque
est object and
d then calls
the B
BeginGetResp ponse method.
10-32 Improving Application Performance and Responsiveness

b. Notice that the BeginGetResponse method specifies the ResponseCallback method as an


asynchronous callback method.

c. 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 keywordds, you can haandle
e
exceptions in the same wayy 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 thatt 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;
}
}
}

IIn the previou us example, th he click event handler for a button calls the
t
W
WebClient.D ownloadStringTaskAsyncc method asynchronously b by using the a
await operatoor. The URL
t
that is provide ed is invalid, sso the methodd throws a We ebException exception. Evven though th he operation
i asynchrono
is ous, control returns to the b btnThrowErro or_Click methhod when the asynchronou us operation iss
c
complete andd the exceptio on is handled correctly.
c Thiss works becauuse behind thee scenes, the T
Task Parallel
L
Library is catcching the asyn nchronous excception and re e-throwing it on the UI thre
ead.

U
Unobserved
d Exception
ns
When a task rraises an exception, you can
W 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 Taask.Wait meth hod. If the join
ning thread
n
never accessees the task, the
e exception w will remain uno observed. Whe en the .NET Frramework garrbage
c
collector (GC)) detects that a task is no lo
onger required d, the task schheduler will th
hrow an excep ption if any
t
task exceptionns remain uno observed. By d default, this exxception is ignored. Howevver, you can im mplement an
e
exception han
ndler of last re
esort by subsccribing to the TaskScheduller.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 Improoving Application Performance and Respponsiveness

Lesson 3
Synch
hronizin
ng Conccurrentt Accesss to Data

Inttroducing multithreading in many advantages in terms of


nto your applications has m o performancce and
ressponsiveness. However, it also
a introduce es new challen ou can simultaaneously updaate a
nges. When yo
ressource from m
multiple threads, the resourrce can becom
me corrupted or can be leftt in an unpred
dictable
staate.

In this lesson, yo how to use various synchronization techn


ou will learn h niques to ensu
ure that you aaccess
ressources in a th
hread-safe maannerin oth her words, in a way that pre
events concurrent access fro
om having
unnpredictable e effects.

Le
esson Obje
ectives
Aftter completing this lesson, you will be ab
ble to:

atements to prevent
Use lock sta p concu
urrent access tto code.
Use synchro
onization prim
mitives to restrict and contrrol access to re
esources.

Use concurrent collection


ns to store daata in a thread
d-safe way.
Programming in Visual C# 10-37
7

U
Using Loccks

When you inttroduce multitthreading into


W o your applicaations, you can often encouunter situationns in which a
r
resource is sim
multaneously accessed fromm multiple thrreads. If each of these threaads can alter tthe resource,
t resource ccan end up in an unpredicttable state. Fo
the or example, suuppose you crreate a class thhat manages
s
stock levels off coffee. When you place an order for a number of co offees, a method in the classs will:

1
1. Check the
e current stocck level.

2
2. If sufficien
nt stock existss, make the co
offees.
3
3. Subtract tthe number o
of coffees from
m the current stock level.

IIf only one thread can call tthis method aat any one tim
me, everythingg 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 stepps 1 and 2, orr
b
between steps 2 and 3, making it impossible to keep track of the current stock level and establish whetherr
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 critiical sections
o code. A mu
of utual-exclusion lock means that if one th
hread is accesssing the critical section, all other threadss
a locked out. To apply a lock, you use the following
are g syntax:

l
lock (object) { statement bllock }

The first thing


T g to notice is tthat you applyy the lock to aan object. This is because the lock workss by ensuring
t
that only one thread can acccess that objject 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 locck keyword too make
m
mutually excluusive. Next, yoou put your critical section of code insidde the lock bloock. While thee lock
s
statement is in
n scope, only one thread caan enter the ccritical sectionn at any one time.

The following code example shows how to use the lo


T ock keyword to ncurrent accesss 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: Ussing Lock Statemen
nts

ock statement prevents concurrent acce


This demonstration illustrattes how the lo
T ess to critical ssections of
c
code. monstration solution contains a class nam
The dem med Coffee tthat includes a method nam med
M
MakeCoffees s. The MakeC Coffees metho od does the fo
ollowing:
1
1. Checks th
he current cofffee stock leve
el.

2
2. Fulfills the
e order, if the
e current stockk level is sufficcient.

3
3. Subtractss the number of coffees ord
dered from the current stocck level.
IIn the Progra
am class, a Parallel.For loop creates 100 parallel operation places
0 parallel operrations. Each p
a order for b
an between one aand 100 coffe ees at random
m.

When you use


W e a lock statement to applyy a mutual-exxclusion lock tto the critical section of cod
de in the
M
MakeCoffees s method, thee method will always functio on correctly. However,
H if yo
ou remove the e lock
s
statement, the
e logic can faiil, the stock le
evel becomes negative, andd the applicatiion throws ann exception.

D
Demonstra
ation Steps
1
1. Start the MSL-TMG1 viirtual machine
e if it is not already running
g.

2
2. Start the 20483A-SEA
A-DEV11-10 vvirtual machine.

3
3. Log on to
o Windows 8 as
a Student with the passwo
ord Pa$$w0rrd.

Note: Iff necessary, click Switch Usser to display the list of use
ers.

4
4. Switch to the Windowss 8 Start wind
dow.
5
5. Click Visu
ual Studio 20
012.

6
6. In Visual Studio, on the
e File menu, p n, and then click Project/Solution.
point to Open

7
7. In the Oppen Project dialog box, bro er, click Locking.sln, and
owse to the E::\Democode\\Starter folde
then clickk Open.

8
8. In Solutio
on Explorer, do
ouble-click Co
offee.cs.

9
9. Review th
he Coffee classs, paying parrticular attentiion 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
nchronizattion Primiitives with
h the Task
k Parallel LLibrary

A synchroniza
ation primitivee is a mechanism by which aan operating system enables its users, in n this case the
e
.
.NET runtime, to control the synchronizaation of threadds. The Task P
Parallel Libraryy supports a w
wide range off
s
synchronizatio
on primitives that enable yyou to control access to reso
ources in a vaariety of ways.. These are
t most com
the mmonly used ssynchronizatio on primitives:

The ManualResetEven ntSlim class enables


e one or more threadds to wait for an event. A
ManualR ResetEventSliim object can be in one of two states: sig gnaled and un nsignaled. If a thread calls
the Wait method and the ManualR ResetEventSliim object is unsignaled, thee thread is bloocked until
the Manu ualResetEven ntSlim object state changes to signaled. In your task logic, you can n call the Set
or Reset methods on tthe ManualRe esetEventSlimm object to ch
hange the staate to signaledd or
unsignaleed respectivelyy. You typically use the Ma
anualResetEv ventSlim classs to ensure thaat only one
thread caan access a ressource at any one time.

Referennce Links: Forr more informmation about tthe ManualRe esetEventSlim


m class, see th
he
ManualResetEEventSlim Classs page at http://go.microssoft.com/fwlin
M nk/?LinkID=2667850.

The Sema aphoreSlim cclass enables yyou to restrictt access to a resource,


r or a pool of resou
urces, to a
limited nu
umber of concurrent threads. The Sema aphoreSlim cllass uses an in nteger counteer to track the
number o of threads thaat are currentlyy accessing a resource or a pool of resou urces. When yyou create a
Semapho oreSlim objecct, you specifyy an initial value and an optional maximu um value. Whhen a thread
wants to access the pro otected resouurces, 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 decremmented and tthe thread is
granted aaccess. When the thread ha as finished, it should
s call the
e Release me ethod on the
Semapho oreSlim objecct, and the counter is increm mented. If a thread calls the Wait metho od and the
counter iss zero, the thrread is blocke
ed until anothe er thread callss the Releasee method. For example, if
your coffeee shop has three coffee m machines and e each can onlyy process one order at a tim me, you mightt
use a SemmaphoreSlim m object to preevent more th han three thre eads simultane eously orderin
ng a coffee.

Additio
onal Reading: For more infformation abo out the SemaphoreSlim class, see the
SSemaphoreSliim Class page
e at http://go.microsoft.com
m/fwlink/?LinkkID=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 Frameworkk are, by default, not thread-safe. When you access
T
c
collections fro
om tasks or otther multithreeading techniq ques, you musst ensure thatt you do not ccompromise
t integrity o
the of the collectio
ons. One wayy 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, tthe .NET Frammework also
i
includes a set of collectionss that are specifically designed for thread-safe access.. The following table
d
describes som
me of the classses and interfaaces that the SSystem.Colleections.Concu urrent namesspace
p
provides.

Class or inte
erface Descriptiion

ConcurrentBag<T> This classs provides a tthread-safe way to store


an unord dered collection of items.

ConcurrentDictionary<TK
Key, TValue> This classs provides a tthread-safe alternative to
the Dicttionary<TKey y, TValue> class.

ConcurrentQ
Queue<T> This classs provides a tthread-safe alternative to
the Que eue<T> class.

ConcurrentSStack<T> This classs provides a tthread-safe alternative to


the Stacck<T> class.

IProducerCo
onsumerColle
ection<T> This inte
erface defines methods for
impleme enting classes that exhibit
produce er/consumer behavior;
b in otther words,
classes that distinguissh between prroducers who
add itemms to a collecttion and consu umers who
read item
ms from a collection. This distinction
d is
importan nt because these collection ns need to
impleme ent a read/wriite locking pattern, where
the colle
ection can be locked either by a single
writer orr by multiple readers.
r The
ConcurrrentBag<T>, ConcurrentQ Queue<T>,
and Con ncurrentStack k<T> classes all
impleme ent this interfaace.
10-44 Improving Application Performance and Responsiveness

Class or interface Description

BlockingCollection<T> 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

Demonstrration: Im
D mproving tthe Respo
onsivenesss and Perfformance of the
A
Applicatio
on

I this demon
In nstration, you will learn abo
out the tasks tthat you will p
perform in the
e lab for this module.
m
10-46 Improoving Application Performance and Respponsiveness

Lab: Im
mproving the Responsivene
ess and Perforrmance of
the Appplicatiion

Sccenario
Yo
ou have been asked to updaate the Grade es application to ensure thaat the UI remaains responsivve while the
use
er is waiting ffor operationss to complete.. To achieve th his improvemment in respon nsiveness, you decide to
convert the logiic that retrievees the list of students
s for a teacher to usse asynchrono ous methods. Y You also
de
ecide to provid de visual feedback to the u user to indicate when an op peration is takking place.

Ob
bjectives
Aftter completing this lab, you
u will be able to:
ync and awaitt keywords to
Use the asy o implement asynchronous
a methods.

Use events and user conttrols to provid


de visual feedback during long-running operations.

Esttimated Time:: 75 minutes


Virtual Macchine: 20483A
A-SEA-DEV11--10, MSL-TMG
G1

User Name: Student

Password: Pa$$w0rd
P
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. Start the MSL-TMG1 virtual machine if it is not already running.
2. Start the 20483A-SEA-DEV11-10 virtual machine and log on as Student with the password
Pa$$w0rd.

3. Start Visual Studio, and then open the Grades.sln solution from the E:\Labfiles\Starter\Exercise 1
folder.

4. Set the following projects to start without debugging at startup:

a. Grades.Web
b. Grades.WPF

5. Build the solution, and then resolve any compilation errors.

6. Run the application.


7. Log on as vallee with a password of password99.

8. 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).
9. Close the application.

X Task 2: Modify the code that retrieves teacher data to run asynchronously
1. In the Grades.WPF project, in the Services folder, open ServiceUtils.cs.

2. Modify the GetTeacher method declaration so that it:


a. Runs asynchronously.

b. Returns a Task<Teacher> object.

3. 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. In the MainWindow class, modify the Refresh method declaration so that the method runs
asynchronously.

5. 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. In the StudentsPage class, modify the Refresh method declaration so that the method runs
asynchronously.

2. In the Refresh method, in the Callbacks region, locate the code that iterates through the returned
set of students and updates the UI.
3. Factor out this code into a new method named OnGetStudentsByTeacherComplete. This method
should:

a. Accept a single argument of type IEnumerable<Student>.

b. Return void.

c. Use a Dispatcher object to update the UI.

4. In the ServiceUtils class, modify the GetStudentsByTeacher method declaration so that it:

a. Runs asynchronously.

b. Returns a Task object.

c. Accepts a delegate argument that can represent the OnGetStudentsByTeacherComplete


callback method.

5. Modify the GetStudentsByTeacher method so that it returns without passing a value if the call to
IsConnected returns false.
6. In the GetStudentsByTeacher method, use the await operator to run the LINQ query
asynchronously and return a Task<Student> object.

7. Modify the GetStudentsByTeacher method so that it invokes the callback method delegate
asynchronously rather than returning the results.

8. In the StudentsPage class, modify the Refresh method so that it:

a. Calls the GetStudentsByTeacher method asynchronously.


b. Passes the OnGetStudentsByTeacherComplete method as the second argument.

X Task 4: Build and test the application


1. Build the solution and resolve any compilation errors.

2. Run the application.


3. Log on as vallee with a password of password99.

4. Verify that the application is more responsive than before while fetching the list of students for Esther
Valle.
5. 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. Start the MSL-TMG1 virtual machine if it is not already running.

2. Start the 20483A-SEA-DEV11-10 virtual machine and log on as Student with the password
Pa$$w0rd.
3. Start Visual Studio, and then open the Grades.sln solution from the E:\Labfiles\Starter\Exercise 2
folder.

4. Set the following projects to start without debugging at startup:

a. Grades.Web

b. Grades.WPF

5. Build the solution.


6. In the Grades.WPF project, create a new user control named BusyIndicator.xaml.

7. 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. Ensure that the user control does not specify dimensions by deleting the DesignWidth and
DesignHeight properties.

9. 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. Set the corner radius to 6 units.


b. Set the horizontal and vertical alignments to Center.
Programming in Visual C# 10-51

c. Set the background to a horizontal linear gradient from light gray to dark gray.

d. Add a drop shadow effect with opacity of 0.75.


11. In the Border element, add a Grid element with the following characteristics:

a. Set the margin to 10 units.

b. 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. Set the width to 200 units.

b. Set the height to 25 units.

c. Set the margin to 20 units.

d. Set the name of the control to progress.

e. 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. Set the font size to 14 points.


b. Apply the Verdana font.

c. Set the text alignment to Center.

d. Display the message Please Wait


e. 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. Set the margin to 0.

b. Set the visibility to Collapsed.


c. Set the name of the control to busyIndicator.

d. 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. Return void.

b. Accept two arguments, of type object and EventArgs respectively.

2. In the StartBusy method, make the busyIndicator control visible.

3. In the MainWindow class, add a private method named EndBusy. The method should:

a. Return void.

b. 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. Add a public event named EndBusy.

3. Add a method named StartBusyEvent that takes no arguments and returns void.
4. In the StartBusyEvent method, raise the StartBusy event.

5. Add a method named EndBusyEvent that takes no arguments and returns void.

6. In the EndBusyEvent method, raise the EndBusy event.

7. In the MainWindow.xaml file, in the StudentsPage element, associate the StartBusy event handler
method with the StartBusy event.

8. In the StudentsPage element, associate the EndBusy event handler method with the EndBusy event.
9. 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. Build the solution and resolve any compilation errors.

2. Run the application.

3. Log on as vallee with a password of password99.


4. Verify that the application displays the busy indicator while waiting for the list of students to load.

5. 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
IIn this module
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 Liibrary, how to
o use the asyn
nc and await keywords, andd how to use
s
synchronizatio
on primitives.

T
Test Your Kno
owledge

Question

You create aand start threee tasks name ed task1, task


k2, and task3. You want to block the
joining thre
ead until all off these tasks are completee. Which codee example shoould you use
to accomplish this?

Select the correct answerr.

taskk1.Wait();
taskk2.Wait();
taskk3.Wait();

Taskk.WaitAll(task1
1, task2, task3
3);

Taskk.WaitAny(task1, task2, taskk3);

Taskk.WhenAll(taskk1, task2, taskk3);

Taskk.WhenAny(taask1, task2, tassk3);

T
Test Your Kno
owledge

Question

You have a ssynchronous method with h the followin


ng signature:
public IEnum
merable<strin ng> GetCoffeees(string cou
untry, int stre
ength)
You want too convert thiss 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 11-2

Lesson 1: Creating and Using Dynamic Objects 11-3

Lesson 2: Managing the Lifetime of Objects and Controlling Unmanaged


Resources 11-12

Lab: Upgrading the Grades Report 11-20

Module Review and Takeaways 11-25


11-2 Integratting with Unmanageed Code

Modu
ule Ove
erview

Software systemms can be commplex and mayy involve applications that are implemen nted in a varie
ety of
tecchnologies. Fo ome applications may be m
or example, so managed Micrrosoft .NET Framework ap pplications,
whhereas others may be unmaanaged C++ aapplications. Y You may wantt to use functionality from one
pplication in another or use functionality that is exposed through Component Ob
ap bject Model (COM)
asssemblies, such
h as the Micro
osoft Word 144.0 Object Library assemblyy, in your appllications.

In this module, yyou will learn how to intero


operate unmaanaged code in your appliccations and ho
ow to
ensure that your code release es any unmannaged resourcces.

Ob
bjectives
Aftter completing this module
e, you will be able to:

Integrate unmanaged co
ode into a Miccrosoft Visual C# applicattion by using the Dynamic Language
Runtime (DDLR).

e lifetime of un
Control the nmanaged ressources and ensure
e that yo
our application
n releases reso
ources.
Programming in
i Visual C# 11-3
3

Lesson 1
Creatting an
nd Using
g Dyna
amic Ob
bjects

There are man


T ny different programming
p languages avvailable, each w with its own sset of advantaages and
d
disadvantages s and scenarioos where it is better suited. Having the aability to consume components that are
i
implemented in other languages enable es you to reusee functionalityy that may alrready exist in your
o
organization.

I this lesson, you will learn


In t DLR to intteroperate witth unmanaged code.
n how to use the

L
Lesson Ob
bjectives
A
After completting 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 objecct.
11-4 Integratting with Unmanageed Code

W
What Are Dynamic
D O
Objects?

Vissual C# is a strongly typed static languag


ge. When you u create a variable, you specify the type ofo that
variable, and yo ou can only invvoke methods and access mmembers thatt this type deffines. If you trry to call a
me ethod that the e type does not implementt, your code w od because the compile
will not compile. This is goo
tim
me checks catcch a large num mber of possible errors eve
en before you run your cod de.

The .NET Frame ework providees dynamic ob bjects so that you


y can define objects thatt are not consstrained by
the
e static type system
s in Visual C#. Instead
d, dynamic objbjects are not ttype checked until run time
e, which
enables you to write
w code quuickly without worrying abo out defining eevery memberr until you nee ed to call
the
em in your co ode.

Yoou can use dyn


namic objectss in your .NET Framework aapplications to
o take advanta
age of dynam
mic
lan
nguages and unmanaged
u c
code.

Dy
ynamic Lan
nguages
Languages suchh as IronPythoon and IronRuby are dynammic and enablee you to write
e code that is not
compiled until rrun 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 orr compile pro
ocess.

They have increased flexibility over staatic languagess because the


ere are no stattic types to wo
orry about.

ot have a stron
They do no ngly typed objject model to
o learn.

Dyynamic languaages do sufferr from slower execution tim


mes in comparrison with com
mpiled languaages,
be
ecause any optimization steeps that a com
mpiler may takke when comp de are left out of the
piling the cod
bu
uild process.

Un
nmanaged Code
Vissual C# is a managed
m languuage, which m
means that the e Visual C# co
ode you write is executed bby a
runntime environ nment known as the Comm mon Language e Runtime (CLLR). The CLR pprovides otherr benefits,
succh as memoryy managemen nt, Code Access Security (CAAS), and exception handlinng. Unmanage ed code
succh as C++ exe ecutes outside
e the CLR and
d in general be on times and being
enefits from ffaster executio
exttremely flexib
ble.

Whhen you build


d applications by using the .NET Framew
work, it is a com
mmon use casse 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 Integratting with Unmanageed Code

W
What Is the
e Dynamicc Languag
ge Runtim
me?

The .NET Frame ework provide es the DLR, wh


hich contains tthe necessaryy services and components to support
dyynamic langua ages and provvides an approoach for intero
operating with unmanaged d componentss. The DLR
is responsible
r fo
or managing tthe interaction
ns between th he executing assembly
a and the dynamic object, for
exaample, an objject that is implemented in IronPython o or in a COM assembly.

The DLR simpliffies interoperaating with dyn


namic objects in the followiings ways:

It defers typ
pe-safety checcking for unm
managed resouurces until run
n time. Visual C# is a type-ssafe
language and, by defaultt, the Visual C
C# compiler pe
erforms type--safety checking at compile e time.

Note: Typ pe safety reliess on the comppiler being abble to compile


e or interpret e
each of the
components thaat the solutionn references. When
W interopperating with unmanaged ccomponents, tthe
compile-time tyype-safety cheeck is not alwa
ays possible.

It abstracts the intricate details


d of inte
eroperating wiith unmanage
ed componen
nts, including marshaling
m
data between the manag ged and unmaanaged enviro onments.

The DLR does not provide functionality thaat is pertinentt to a specific language butt provides a set of
lannguage binde ers. A language binder conttains instructio
ons on how to o invoke methhods and marrshal data
beetween the un nmanaged language, such aas IronPython, and the .NET T Framework. The language binders
alsso perform run-time type cchecks, which include checkking that a me given signature actually
ethod with a g
exists in the object.

Additionaal Reading: FFor more inforrmation about the DLR, see


e the Dynamicc Language
Ru
untime Overview page at htttp://go.micro
osoft.com/fwliink/?LinkID=2
267858.
Programming in
i Visual C# 11-7
7

C
Creating a Dynamicc Object

namic keyword to enable you to define d


The DLR infrastructure provvides the dyn
T dynamic objects in your
a
applications. W
When you use namic object, it has the following
e the dynamiic keyword to declare a dyn
i
implications:
It defines a variable of type object. You can assig
gn any value tto this variable
e and attemptt to call any
methods.. At run time, the DLR will uuse the languaage binders too type check yyour dynamicc code and
ensure thhat the member you are tryying to invoke e exists.

It instructts the compile


er not to perfo
orm type checcking on any dynamic code
e.

It suppressses the Micro


osoft IntelliSen
nse feature because IntellliSense is una
able to provide syntax
assistance
e for dynamicc objects.
To create a dyynamic objectt to consume the Microsoftt.Office.Intero
T op.Word COM
M assembly, pe
erform the
f
following step
ps:

1
1. In your .N
NET Frameworrk project, add
d a reference to the Microssoft.Office.Inte
erop.Word CO
OM assembly..
2
2. 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.Offfice.Interop..Word namesspace by using
g the dynamic keyword.

D
Dynamic Varriable Declara
ation
using Micro
osoft.Office
e.Interop.Word;
...
dynamic wor
rd = new App
plication();

After you havve created an iinstance of th


A he class, you can use the me
embers that itt provides in tthe same wayy
y would witth any.NET Frramework classs.
you

Additio
onal Reading: For more infformation abo
out the dynam mic keyword, see the Using
g
T
Type dynamicc (C# Program
mming Guide) page at http:://go.microsoft.com/fwlink//?LinkID=267
7859.
11-8 Integratting with Unmanageed Code

In
nvoking M
Methods on a Dynam
mic Objecct

Aftter you have instantiated


i a dynamic objeect by using tthe dynamic keyword, you can access th
he
pro
operties and mmethods by u using the stand
dard Visual C# # dot notation.

The following co ode example shows how yoou can use the Add metho ument class in the Word
od of the Docu
intterop library tto create a new
w Word docu
ument.

Inv
voking a Metthod on a Dy
ynamic Objecct
/
// 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 parameterss to dynamic object metho
od calls as you
u would with aany .NET Fram
mework
ob
bject.
ode example shows how yo
The following co ou can pass a string variablle to a method that a dynamic object
exposes.

assing Parameters to a Me
Pa ethod
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);

Traaditionally wh
hen consuming a COM asse embly, the .NEET Frameworkk required you u to use the reef keyword
and pass a Type e.Missing objject to satisfy any optional parameters th hat a method contains. Also, any
parameters thatt you pass mu ust be of type object. This ccan result in simple method d calls requirin
ng a long
listt of Type.Misssing objects and code thatt is verbose annd difficult to
o read. By usin
ng the dynam mic
keyyword, you caan 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 Integrrating with Unmanagged Code

Demonstration: Inte
eroperatin
ng with Microsoft W
Word

In this demonstration, you wiill use dynamiic objects to cconsume the M


Microsoft.Offiice.Interop.Wo
ord COM
asssembly in an existing
e .NET Framework ap pplication.

The application will use the WWord object m model to combine several text files that ccontain excep
ption
infformation into
o an exception n report in Word format. The code uses the Word objject model to add data
om the text files, line breakss, and formattting to generaate the final document.
fro d

De
emonstration Steps
1. Start the MSL-TMG1 virtual machine if it is not already running.

2. 0483A-SEA-DEEV11-11 virtual machine.


Start the 20

3. Log on to W
Windows 8 as
a Student with the passwo
ord Pa$$w0rrd.

Note: If necessary, clickk Switch Userr to display th


he list of userss.

4. Switch to th
he Windows 8 Start window
w.
5. Click Visual Studio 2012.

6. udio, on the F
In Visual Stu a then clickk Project/Solution.
File menu, point to Open, and

7. In the Open n Project diallog box, brow Democode\Staarter\FourthCoffee.Exceptio


wse to the E:\D onLogger
folder, clickk FourthCoffeee.ExceptionLogger.sln, aand then click Open.

8. In the Soluttion Explorer window,


w rightt-click the Fou
urthCoffee.ExcceptionLogge
er project, and
d then click
Add Reference.
9. In the Reference Manag ger FourthC
Coffee.Excep
ptionLogger d erform the following
dialog box, pe
steps, and tthen click OK::

a. Expand
d COM, and th
hen click Type
e Libraries.
b. In the S
Search box, tyype Word.

c. In the aassembly list, select Microso


oft Word 14.0
0 Object Library, and then sselect the Miccrosoft
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.
b. The AppendText method adds text to the end of the document, in the bold and/or italic style.

c. The InsertCarriageReturn method inserts a carriage return at the end of the document.

d. The Save method deletes any file with the same name and then saves the current Word
document.

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 Integrrating with Unmanagged Code

Lesson 2
Managing th
he Lifetime of Objectts and Control
C ling
anaged Resourrces
Unma

Wh hen interoperrating with un


nmanaged ressources, it is im
mportant thatt you manage and release tthese
ressources when you are no loonger using th
hem.

In this lesson, yo
ou will learn aabout the life cycle of a typical .NET Fram
mework objecct and how to ensure that
obbjects release the
t resources that they havve been using when they are destroyed.

Le
esson Obje
ectives
Aftter completing this lesson, you will be ab
ble to:

Describe the life cycle off a .NET Frame


ework object.

Implement the dispose pattern.


p
Manage the
e lifetime of aan object.
Programming in Visual C# 11-13
3

T Objecct Life Cyccle


The

The life cycle of an object h


T has several staages, which sttart at creation
n of the objecct and end in its
d
destruction. T
To create an object
o in your application, yyou use the neew keyword. W When the CLR R executes
c
code to createe a new objecct, it performss the followingg steps:
1
1. It allocate
es a block of m
memory large
e enough to h
hold the objecct.

2
2. It initializes the block o
of memory to the new obje
ect.

The CLR hand


T dles the allocation of memoory for all man
naged objectss. However, when you use uunmanaged
o
objects, you m
may need to write
w code to aallocate mem
mory for the un
nmanaged ob bjects that you
u create.

When you havve finished wiith an object, you can dispo


W ose of it to release any reso
ources, such aas 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 garrbage collecto
or (GC) to perfform the follo
owing steps:

1
1. The GC re
eleases resourrces.

2
2. The mem
mory that is allocated to the
e object is recllaimed.
The GC runs aautomatically in a separate thread. When
T n the GC runss, other thread
ds in the appliication are
h
halted, because the GC may move objeccts in memoryy and thereforre must updatte the memorry pointers.

Additio
onal Reading: For more infformation abo
out GC, see th
he Garbage Co
ollection page
e at
http://go.micrrosoft.com/fw
h wlink/?LinkID=
=267861.
11-14 Integrrating with Unmanagged Code

Im
mplementing the Dispose Patttern

The dispose patttern is a desig


gn pattern thaat frees resources that an o
object has used. The .NET Framework
pro
ovides the IDisposable interface in the System name espace to enable you to im
mplement the d dispose
pattern in your applications.
The IDisposable interface de efines a single
e parameterlesss method named Dispose e. You should use the
Dispose method to release aall of the unmanaged resou urces that your object consu umed. If the o
object is
part of an inherritance hierarcchy, the Dispoose method can also releasse resources th hat the base ttypes
consumed by caalling the Disp pose method on the paren nt type. Invokiing the Dispo ose method does not
de
estroy an object. The objectt remains in memory
m until tthe final reference to the object is removved and the
GC
C reclaims anyy remaining re esources.
Maany of the classes in the .NET Frameworkk that wrap unnmanaged resources, such as the StreammWriter
cla
ass, implemen e. You should also impleme
nt the IDispossable interface ent the IDispo
osable interfaace when
you create yourr own classes that
t referencee unmanaged types.

Im
mplementin
ng the IDisp
posable Inte
erface
To
o implement the IDisposab
ble interface in
n your applicaation, perform
m the following steps:

1. Ensure thatt that the Systtem namespaace is in scope


e.

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 privaate field to the


e class, which you can use tto track the disposal status of the objectt, and check
whether thee Dispose me ethod has alreeady 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 Lifettime of an
n Object

Using types th
U hat implemen nt the IDispossable interface
e is not sufficiient to manag
ge resources. Y
You must
a remembe
also er to invoke thhe Dispose method
m ur code when you have finisshed with the object. If you
in you u
c
choose not to
o implement a destructor th hat invokes th
he Dispose method when tthe GC processses the
o
object, you caan do this in a number of oother ways.

O approach
One h is to explicittly invoke the Dispose metthod after anyy other code tthat 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();

IInvoking the Dispose


D methhod explicitly after code that uses the ob
bject is perfecctly acceptable
e, but if your
c
code throws aan exception before
b the call to the Dispoose method, tthe Dispose m method will n
never be
i
invoked.

A more reliabble approach is to invoke th


he Dispose method in the finally
f block o
of a try/catch
h/finally or a
t
try/finally staatement. Any code in the sccope of the fiinally block w
will always exe
ecute, regardle
ess of any
e
exceptions thaat might be th
hrown. Thereffore, with thiss 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 blocck.

I
Invoking the
e Dispose Me
ethod in a finally Block
var word = default(MannagedWord);
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 tthat you will p
perform in the
e lab for this module.
m
11-20 Integrrating with Unmanagged Code

Lab: U
Upgradiing the
e Grade
es Report

Sccenario
Yo
ou have been asked to upgrade the graddes report functionality to g
generate repoorts in Word fo
ormat. In
Moodule 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 Worrd document.

Ob
bjectives
Aftter completing this lab, you
u will be able to:
Use dynamic types.

bject lifetime aand resourcess.


Manage ob

Esttimated Time:: 75 minutes


Virtual Macchine: 20483A
A-SEA-DEV11--11, MSL-TMG
G1

User Name: Student

Password: Pa$$w0rd
P
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. Start the MSL-TMG1 virtual machine if it is not already running.

2. Start the 20483A-SEA-DEV11-11 virtual machine and log on as Student with the password
Pa$$w0rd.
3. Start Visual Studio and open the Grades.sln solution from the E:\Labfiles\Starter\Exercise 1 folder.

4. Set the following projects to start without debugging at startup:

a. Grades.Web
b. Grades.WPF

5. In the Grades.Utilities project, review the contents of the WordWrapper.cs file.

6. In the WordWrapper class, add code to create a dynamic variable named _word for activating Word.
7. 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.

8. In the CreateBlankDocument method, add code to create a new Word document and then activate
the new document.

9. In the SaveAs method, add code to do the following:

a. Save the active Word document using the file name that is passed to the method.
b. 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. In the Utility and Helper methods region, locate the GenerateStudentReport method.

3. In this method, add code to do the following:


a. Call the CreateBlankDocument method of the Wrapper object.

b. Add the heading Grade Report: and the students name to the blank document followed by two
blank lines.
c. Add the details of each grade for that student to the document, including:

Subject name

Assessment
Date

Comment

d. 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. Build the solution and resolve any compilation errors.

2. Run the application.

3. Log on as vallee with a password of password99.


4. 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.

5. 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. In Visual Studio, open the Grades.sln solution from the E:\Labfiles\Starter\Exercise 2 folder.

2. Set the following projects to start without debugging at startup:

a. Grades.Web
b. Grades.WPF

3. Build the solution and resolve any compilation errors.

4. Run the application.


5. Log on as vallee with a password of password99.

6. Generate a grade report for Kevin Liu, save the report in the E:\Labfiles\Starter\Exercise 2 folder, and
then close the application.
7. Use File Explorer to verify that the report has been generated.

8. Open Task Manager, and then verify that Word is still running.

9. In Task Manager, end the Word task, and then close Task Manager.

X Task 2: Update the WordWrapper class to terminate Word correctly


1. In the Grades.Utilities project, open WordWrapper.cs.

2. Modify the definition of the WordWrapper class so that it implements the IDisposable interface.

3. In the WordWrapper class, create a protected virtual void method named Dispose that takes a
Boolean parameter.

4. Add code to this method to do the following:


11-24 Integrating with Unmanaged Code

a. Check that the class is not yet disposed of.

b. Check whether the Boolean parameter that is passed to the method is true.
c. Check whether the _word variable is not null.

d. If all of these checks are valid, use the Quit method of the Word object to release the managed
resources.
e. If the _word variable is still not null, use the ReleaseComObject method to release the
unmanaged resources.

f. Set the isDisposed property to true.


5. In the WordWrapper class, create a public method named Dispose.

6. Add code to the method to do the following:

a. Call the Dispose method, passing true as a parameter.


b. 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. In the Grades.WPF project, in the Views folder, open StudentProfile.xaml.cs.

2. In the Utility and Helper methods region, locate the GenerateStudentReport method.

3. 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. Build the solution and resolve any compilation errors.

2. Open Task Manager.


3. Run the application.

4. Log on as vallee with a password of password99.

5. View George Lis grade report.


6. 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.
7. Close Task Manager, close the application, and then in Visual Studio, close the solution.

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
IIn this modulee, you have leearned how too interoperate
e with COM asssemblies and
d how to ensure that your
o
objects disposse 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 answerr.

It de
efines an obje
ect of type objject and instru
ucts the comp
piler to perforrm type
checcking.

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 objject and instru
ucts the comp
piler to defer type
t
checcking.

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 rright.

Statement Answer

You can usee a using statement to imp


plicitly invoke the Dispose method on
an object th
hat implements the IDisposable pattern n.

12-1

Module 12
Creating Reusable Types and Assemblies
Contents:
Module Overview 12-2

Lesson 1: Examining Object Metadata 12-3

Lesson 2: Creating and Using Custom Attributes 12-16


Lesson 3: Generating Managed Code 12-26

Lesson 4: Versioning, Signing, and Deploying Assemblies 12-36

Lab: Specifying the Data to Include in the Grades Report 12-49


Module Review and Takeaways 12-56
12-2 Creatingg Reusable Types annd Assemblies

Modu
ule Ove
erview

Sysstems often consist of manny componentts, some of wh hich may be shared


s with otther applicatio
ons in your
org
ganizations in
nfrastructure. When you de esign applicattions, it is important to thin
nk about reuse e and
consider how thhe functionalitty you are imp
plementing might
m be usefuul in other app
plications.

In this module, yyou will learn how to consuume existing aassemblies byy using reflecttion and how to add
additional metaadata to typess and type me embers by usin ng attributes. You will also learn how to generate
code at run time e by using thee Code Documment Object M Model (CodeD DOM) and how w to ensure th
hat your
asssemblies are ssigned and veersioned, and available to o
other applicatiions, by using the global asssembly
cacche (GAC).

Ob
bjectives
Aftter 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 deployy your assemb
blies to the GA
AC.
Programming in
i Visual C# 12-3
3

Lesson 1
Exam
mining O
Object Metadata

SSometimes ap pplications ne
eed to load ann existing com
mpiled assemb bly, view its co
ontents, and exxecute
f
functionality. For example, a unit testing
g utility may re
equire the ability to obtain a reference tto a type and
e
execute somee of the publicc methods thaat it exposes. R
Reflection pro
ovides a way ffor you to exaamine the
t
types in a com
mpiled assemb bly.

IIn this lesson, you will learn


n how to use reflection
r to e metadata of objects and execute
examine the m
f
functionality tthat the objecct exposes.

L
Lesson Ob
bjectives
A
After completting this lesson, you will be able to:

Describe the purpose o


of reflection.

Load an aassembly.
Examine tthe metadata of an existing
g type.

Invoke th
he members th
hat an assemb
bly exposes.
12-4 Creatingg Reusable Types annd Assemblies

W
What Is Refflection?

Re
eflection is a p
powerful featu
ure that enables you to insp
pect and perfo
orm dynamic manipulation
n of
asssemblies, type
es, and type m
members at ruun time.

Re
eflection is use
ed throughout the Microso oft .NET Frammework. Refle ection is used by some of thhe classes
tha
at the base cla
ass library pro
ovides and som me of the utilities that ship
p with Microsooft Visual Stud
dio. For
exaample, the serialization classes in the Sy
ystem.Runtim me.Serializatio on namespace use reflectio on to
etermine which type memb
de bers should bee serialized wh
hen serializingg types.

Re
eflection Ussage Scenarios
The following taable describess some of the possible usess for reflection
n in your applications.

U
Use Scenario

Examining me
E etadata and You might
m choose to do this if you
y are consuming an unkn nown
d
dependencies
s of an assemb
bly. assem
mbly in your application and d you want to
o determine w
whether
your aapplication sa
atisfies the unknown assem
mblys dependeencies.

FFinding memb bers in a type


e You might
m choose to do this if you
y are implem menting a generic
t
that have bee en decorated with
w storag
ge repository,, which will inspect each typ
pe and determ
mine which
a particular atttribute. memb bers it needs tto persist.

Determining whether
D w a typ
pe You might
m choose to do this if you
y are creatin ng a pluggable
i
implements a specific appliccation that en nables you to include new aassemblies at run time,
i
interface. but yoou only want your applicattion to load tyypes that implement a
speciffic interface.

Defining and executing a


D You might
m choose to do this if you
y are implem menting a virttualized
m
method at run
n time. platfo
orm that can rread types and d methods that are implem mented in a
languuage such as JavaScript, and d then creatin
ng managed
impleementations thhat you can e execute in youur .NET Framew work
appliccation.

Exe
ecuting code by using refleection is margginally slower than executin
ng static Micro
osoft Visual C# code,
so you should o
only use reflecction to create
e and executee code when yyou really havee to and not jjust
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 Creatingg Reusable Types annd Assemblies

Lo
oading Asssemblies by Using Reflection
n

The System.Refflection name espace provid


des the Assem
mbly class, wh hich enables yyou to encapsu ulate an
asssembly in you
ur code so thaat you can insp
pect any metaadata that is aassociated witth that assemb
bly.

The Assembly cclass providess a number off static and insstance membeers that you ccan use to load
d and
exaamine the con
ntents of asseemblies. There
e are two wayss that you can
n load an asseembly into youur
ap
pplication by using
u reflectio
on:

Reflection-o
only context, in which you can view the metadata thaat is associated
d with the asssembly and
not executee code.

Execution ccontext, in which you can exxecute the loa


aded assemblly.

Loading an asse embly in reflecction-only con


ntext can impprove perform
mance; howeveer, if you do trry to
exe
ecute it, the C
Common Lang guage Runtim me (CLR) will th
hrow an InvallidOperation
nException exxception.

To
o load an assem
mbly, the Asssembly class p hich include the
provides a number of staticc methods, wh
folllowing:
LoadFrom.. This method enables you to load an asssembly in exeecution contexxt by using an
n absolute
file path to the assemblyy. The followin
ng code example shows how
w to load the
FourthCofffee.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. Thhis method ennables you to load an assemmbly in reflecttion-only conttext from a
binary large
e object (BLOB) that repressents the assem
mbly. The following code example
e show
ws how to
load the FoourthCoffee.SService.Excep ptionHandlin ng assembly frrom a byte array.

var assem
mblyPath =
"C:\\F
FourthCoffee
e\\Libs\\FourthCoffee.Se
ervice.ExcepptionHandling
g.dll";
var rawBy
ytes = File.ReadAllBytes(assemblyPa
ath);
var assem
mbly = Assem
mbly.ReflectionOnlyLoad(
(rawBytes);

ReflectionOOnlyLoadFro om. This method enables yo ou to load an assembly in rreflection-onlyy context


by using an
n absolute file path to the assembly.
a The following cod
de example sh hows how to load the
FourthCofffee.Service.Ex xceptionHan ndling assembbly.
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 Creatingg Reusable Types annd Assemblies

Exxamining Types by Using Refflection

Re
eflection enables you to exaamine the deffinition of anyy type in an asssembly. Depe
ending on whether you
are
e looking for a type with a specific name
e or you want to iterate thrrough each tyype in the asse
embly in
seq
quence, you ccan use the GeetType and G GetTypes metthods that the e Assembly class provides.
The following co
ode example shows how to o load a type by using the GetType
G metthod, passing the fully
qu
ualified name of the type ass a parameterr 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 yyou use the G


GetType methhod and speciffy a name of a type that do
oes not exist in the assembly, the
GeetType 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 methodd 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 = FourthCofffeeServices
s.GetAssembly
y();
...
f
foreach (var type in asssembly.GetTy
ypes())
{
// Code to
o process ea
ach type.
var typeNa
ame = type.F
FullName;
}

Aftter you have created


c an insstance of the T
Type class, yo
ou can then use any of its m
members to innspect the
typ
pes definition
n. The followin
ng list describ
bes some of thhe key membe ers that the Ty
ype class provvides:
GetConstruuctors. This m
method enable es you to get all of the con
nstructors thatt exist in a typ
pe. The
GetConstruuctors metho od returns an aarray that con
ntains ConstruuctorInfo objjects. 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 encapsulatte. Invoking an object by using reflection n follows the
s
same pattern that you use to invoke an object in Visuual C#, which ttypically invollves the follow
wing steps:
1
1. Create an
n instance of tthe type.

2
2. Invoke methods on the
e instance.

3
3. Get or sett property vallues on the instance.
When you invvoke static me
W 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 ttype by using reflection, yo
T ou need to get a reference to a constructtor that the
t
type exposes and then use the Invoke m method. To instantiate a typpe by using th
he Constructo orInfo class,
p
perform the fo
ollowing step
ps:
1
1. Create an uctor you will use to
n instance of tthe ConstructtorInfo class tthat represents the constru
initialize an
a instance off the type. The
e following co
ode example sshows how to o initialize an o
object by
using the e default consttructor.

var typ
pe = FourthCoffeeService
es.GetHandle
eErrorType();
...
var con
nstructor = type.GetCons
structor(new
w Type[0]);

Note: TTo get the default constructtor, you pass an


a empty arraay of type Typpe to the
GetConstructtor method call. If you wan
G nt to invoke a constructor tthat accepts p
parameters, yo
ou
m
must pass a T
Type array tha
at contains the
e types that thhe constructo
or accepts.

2
2. Call the In
nvoke metho od on the ConnstructorInfoo object to inittialize an instaance of the tyype, passing
an objectt array that represents any parameters thhat the constrructor call exppects. 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 Asssemblies

In this demonstration, you wiill create a too


ol that you can use to inspe
ect the conten
nts of an assembly.

The application will use the S


System.Reflecction classes tto load an asssembly, get alll of the types in that
asssembly, and then for each ttype, get all o
of the properties and methoods.

De
emonstration Steps
1. Start the MSL-TMG1 virtual machine if it is not already running.

2. 0483A-SEA-DEEV11-12 virtual machine.


Start the 20

3. Log on to W a Student with the passwo


Windows 8 as ord Pa$$w0rrd.

Note: If necessary, clickk Switch Userr to display th


he list of userss.

4. he Windows 8 Start window


Switch to th w.

5. Click Visual Studio 2012.

6. udio, on the F
In Visual Stu a then clickk Project/Solution.
File menu, point to Open, and

7. In the Openn Project diallog box, brow


wse to E:\Demo
ocode\Starterr\FourthCoffe
ee.TypeInspecttor folder,
click Fourth
hCoffee.Type eInspector.sln, and then click Open.

8. In Solution Explorer, righ


ht-click Fourth
hCoffee.Type
eInspector, and then click Set as StartU
Up Project.
9. On the Builld menu, clickk Build Solutiion.

0. In Visual Stu
10 View menu, click Task List.
udio, on the V

11. In the Task gories list, click Commentss.


k List window,, in the Categ
12. Double-clicck the TODO: 01: Bring the System.Reflecction namespace into scope. task.

13. In the code


e editor, click iin the blank line below the comment, an
nd then type tthe following code:

using System.Reflecti
ion;

4. In the Task List window, double-click the


14 t TODO: 02
2: Create an Assembly objecct. task.
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
Creatiing and
d Using Custom
m Attributes

The .NET Frame


ework uses atttributes to pro nal metadata aabout a type or type memb
ovide addition ber. The
.NET Frameworkk provides maany attributes out of the bo
ox that you ca
an use in yourr applications.

In this lesson, yo
ou will learn h
how to create your own cusstom attribute
es and read th
he metadata tthat is
encapsulated in n custom attribbutes at run time by using reflection.

Le
esson Obje
ectives
Aftter completing this lesson, you will be ab
ble to:

Describe the purpose of attributes.


Create and use custom aattributes.

Process cusstom attribute


es by using refflection
Programming in Visual C# 12-17
7

W
What Are Attribute
es?

Attributes pro
A ovide a mechaanism that usees the declaraative programming model tto include add ditional
m
metadata abo
out elements, such as typess, properties, aand methods, in your application. Your aapplication
c use the ad
can ovide to control application
dditional information that attributes pro n behavior and d how data is
p
processed r time. You can also use the information that attrib
at run butes encapsulate in case toools and
o
other development process, such as unit test frrameworks.
utilities that aid the d

The .NET Fram


T mework make es extensive usse of attribute
es throughoutt the base classs library. The following listt
d
describes som
me of the attributes that the
e .NET Framew work providess:

The Obso
olete attribute
e in the Syste
em namespace e, which you ccan use to ind
dicate that a ttype or a type
e
member has been supe erseded and isi only there tto ensure backkward compatibility.
The Seria
alizable attrib
bute in the Sysstem namesppace, which yo ou can use to indicate that an
IFormattter implementtation can serrialize and desserialize a type.

The NonS Serialized atttribute in the System nameespace, whichh you can use to indicate th
hat an
IFormattter implementtation should not serialize or deserialize a member in a type.

The DataaContract attrribute in the S


System.Runtiime.Serialization namespaace, which you can use to
ontractSerialiizer object can serialize and
indicate tthat a DataCo d deserialize a type.
The QuerryInterceptorr attribute in tthe System.D
Data.Services namespace, w
which you can n use to
control acccess to an en
ntity in Windo
ow Communiccation Foundaation (WCF) D
Data Services.

The ConffigurationPro
operty attribu
ute in the Systtem.Configuration namesspace, which you
y can use
to map a property mem
mber to a secction in an app
plication conffiguration file.

All attributes in the .NET Frramework derrive either dire


A ectly from the
e abstract Attribute base cclass in the
S
System nameespace or fromm another attrribute.

A
Applying A
Attributes
T use an attrribute in your code, perform
To m the followin
ng steps:

1
1. Bring the namespace tthat contains tthe attribute you
y want to use
u into scope
e.
2
2. Apply the
e attribute to the code elem
ment, satisfyin
ng any parame
eters that the constructor e
expects.

3
3. Optionally set any of the named parameters thatt 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 aand Using
g Custom A
Attributess

The .NET Fram


T mework provid des an extensive set of attrributes that yo
ou can use in yyour applications.
H
However, therre will be a tim
me when you need an attribute that the .NET Framew work does not provide. For
e
example, mayybe you want to include infformation abo out the develooper who auth hored the souurce code for
a application
an n, or maybe yo ou need some e additional ddata for a custtom testing framework you u are using to
t
test the appliccation.

T create an aattribute, perfform the following steps:


To

1
1. Create a ttype that deriives from the Attribute base class or ano
other existing
g attribute typ
pe.

2
2. Apply thee AttributeUssage attribute
e to your custom attribute class to describe which elements you
can applyy this attribute
e to.

n attribute to an element th
Note: Iff you apply an with the value of the
hat conflicts w
AttributeUsa
A age attribute, the compiler will throw an error at buildd time.

3
3. Define a cconstructor to
o initialize the
e custom attrib
bute.

4
4. Define anny properties tthat you wantt to enable ussers of the attribute to optionally provide
e
information. Any properties that you u define that have a get acccessor will bee exposed throough the
attribute as a named pparameter.
The code exam
T mple shows h
how to create an attribute tthat encapsulaates metadataa 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 string EmailAddress


{
get { return this._emailAddress; }
}
public int Revision
{
get { 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 Attributtes by Using Reflecttion

IIf you use thee existing attributes that thee .NET Framewwork providess, they normally have a purrpose other
t
than just to exxist in your co
ode. For exammple, the IForm
matter serializzers use the S
Serializable atttribute
d
during the serrializing and ddeserializing p
processes.
SSimilarly, you can use attrib
butes to encap
psulate metad
data about ann element in yyour code. Forr example, if
y create an attribute that provides infformation abo
you out the develo
oper who auth hored the elem ment, you
m want a way
may w to extract this informatiion so that yo
ou can producce a documen nt listing all off the
d
developers wh
ho were involved in develooping the application.

SSimilar to acce
essing other ttype and mem
mber informattion, you can aalso use reflecction to proce
ess attributes.
T System.R
The Reflection namespace provvides a collecttion of extenssion methods that you can use to access
a
attributes and
d the metadatta they encapssulate. The following list de
escribes some
e of these metthods:

GetCusto omAttribute. This method enables you to get a speciific attribute tthat was used on an
element. The following
g code examp
ple shows howw to get a DevveloperInfo 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 getInheriteedAttributes p
parameter insttructs the GettCustomAttriibute method d call
t return eithe
to er only attribu
utes that havee been explicittly applied to the current tyype, or attribu
utes
t
that have bee
en either explicitly applied o
or inherited frrom any paren nt type.

GetCusto omAttribute. This generic method also enables you tto get a speciffic attribute thhat was used
on an ele ement. This is a generic metthod, so you ccan specify th
he type of attribute you wan
nt the
GetCusto omAttribute method to re eturn. This me
eans that you ddo not have tto write conditional logic
to filter an array of objjects to determ
mine the type
e of an attribu
ute and perforrm any casting
g. The
following g code example shows how w to get a Dev
veloperInfo attribute that hhas 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 Atttributes by
b Using R
Reflection
n

In this demonstration, you wiill use reflectio e DeveloperInfo attributess that have be
on to read the een used to
pro
ovide addition
nal metadata on types and type membe ers.

The application uses the GetCCustomAttribute generic method that the Type and d MemberInffo classes
pro
ovide to extra
act any additio
onal information that a cusstom Develop
perInfo attribute encapsulaates.

De
emonstration Steps
1. Start the MSL-TMG1 virtual machine if it is not already running.
2. 0483A-SEA-DEEV11-12 virtual machine.
Start the 20

3. Log on to W
Windows 8 as Student with
h the password Pa$$w0rd.

Note: If necessary, clickk Switch Userr to display th


he list of userss.

4. he Windows 8 Start window


Switch to th w.

5. Click Visual Studio 2012.


6. In Visual Stu File menu, point to Open, and
udio, on the F a then clickk Project/Solution.

7. In the Open n Project diallog box, brow


wse to E:\Demoocode\Starterr\FourthCoffe
ee.MetadataExxtractor
folder, clickk FourthCoffeee.MetadataE Extractor.sln, and then clicck Open.
8. In Solution Explorer, righ
ht-click Fourth
hCoffee.MetaD
DataExtractor,, and then clicck Set as StarttUp Project.

9. In Visual Stu
udio, on the V
View menu, click Task List.

0. In the Task
10 k List window,, in the Categ
gories list, click Commentss.
11. Double-clicck the TODO: 01: Invoke the
e Type.GetCustomAttribute
e method. tassk.

12. In the code


e editor, click iin the blank line below the comment, an
nd then type tthe following code:

var typeAttribute = t
type.GetCust
tomAttribute<
<DeveloperIn
nfo>(false);

13. In the Task List window, double-click the


t TODO: 02
2: Invoke the M
MemberInfo.G
GetCustomAtttribute
method. tassk.
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
Generrating M
Manage
ed Code

Yoou can use Visual Studio to write manage ed code whenn you have cleearly defined requirements
r upon
whhich to base your implemen ntation. Howe ever, sometim
mes you may w want to generaate code at ru
un time
based on a varyying set of req quirements. In this scenario,, you need a framework
f that enables you to define
insstructions thatt a process can translate into executable
e code. The .NNET Frameworrk provides the
CoodeDOM featu ure for this ve
ery purpose.

In this lesson, yo how to generaate managed code at run tiime by using CodeDOM.
ou will learn h

Le
esson Obje
ectives
Aftter 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 sourrce 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 Frameework that ennables you to generate codde at run time. CodeDOM
e
enables you to del that represents the source code that you want to ccreate and then generate
o build a mod
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 inccludes code g
generators for Visual C#, Microsoft Visual Basic, and Microsoft JSccript.

CodeDOM is a powerful feaature that you


C u can use for generating te emplate sourcce files that co
ontain
b
boilerplate co
ode or even ge
enerating sou
urce code filess that serve ass 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 namespacee contains typ


pes that enable ne a model that represents
e you to defin
the sourcce code you w
want to generaate.
System.C
CodeDom.Co ompiler. This n
namespace co
ontains types that enable you to generatte and
manage ccompiled code.

Microsofft.CSharp.CSh
harpCodePro
ovider. This naamespace con
ntains the Visu
ual C# code compiler
c and
generator.

Microsofft.JScript.JScriptCodeProv
vider. This naamespace con
ntains the JScrript code compiler and
generator.
Microsofft.VisualBasicc.VBCodePro
ovider. This naamespace con
ntains the Visu
ual Basic code
e compiler
and gene
erator.

You can use the classes in tthe System.CodeDom nam


Y mespace to crreate a model that represen nts the code
y want to ccreate. The mo
you ude anything ffrom a complex class hierarrchy to a single class with
odel can inclu
s
some membe ers. For exampple, you can usse the CodeN
Namespace cllass to represe ent a namespaace, and you
c use the CodeMemberMethod classs to representt a method.
can
T following table describ
The bes some of th
he classes you
u can use to crreate your mo
odel.

Class Description

CodeCompileUnit Enables yoou to encapsu ulate a collectiion of types


that ultimaately will com
mpile into an aassembly.

CodeNamespace Enables yo
ou to define a namespace tthat you can
12-28 Creating Reusable Types and Assemblies

Class Description
use to organize your class hierarchy.

CodeTypeDeclaration Enables you to define a class, structure, interface,


or enumeration in your model.

CodeMemberMethod Enables you to define a method in your model


and add it to a type, such as a class or an
interface.

CodeMemberField Enables you to define a field, such as an int


variable, and add it to a type, such as a class or
struct.

CodeMemberProperty Enables you to define a property with get and set


accessors and add it to a type, such as a class or
struct.

CodeConstructor Enables you to define a constructor so that you


can create an instance type in your model.

CodeTypeConstructor Enables you to define a static constructor so that


you can create a singleton type in your model.

CodeEntryPoint Enables you to define an entry point in your type,


which is typically a static method with the name
Main.

CodeMethodInvokeExpression Enables you to create a set of instructions that


represents an expression that you want to
execute.

CodeMethodReferenceExpression 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.

CodeTypeReferenceExpression 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.

CodePrimitiveExpression Enables you to define an expression value, which


you may want to pass as a parameter to a
method or store in a variable.

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 CodeDOOM, you writee a set of instrructions that a code generaator
pro
ovider will intterpret to gen
nerate the source code thatt represents yoour model.
The System.Cod deDOM namespace includ des the types that
t you can use
u to write th
hese instructio
ons. The
folllowing steps describe how
w to use some of the System
m.CodeDOM types to define a type thatt contains
an entry point method
m nameed Main:

1. Create a Co
odeCompileU e assembly that will contain
Unit object to represent the n the type. The following
code exampple shows how
w to create a C
CodeCompile eUnit object.

var unit = new CodeC


CompileUnit();

2. Create a Co
odeNamespace object to rrepresent the namespace th hat the type w
will be scoped
d to and
add the nammespace to th
he CodeComp pileUnit obje
ect. The follow
wing code example shows h how to
define the F
FourthCoffeee.Dynamic naamespace.

var dynam
micNamespace
e = new CodeNamespace("F
FourthCoffee
e.Dynamic");
unit.Name
espaces.Add(
(dynamicNamespace);

3. Import any additional na


amespaces thaat the types in
n the namespaace will use. T
The following code
example shows how to b bring the Systtem namespacce into scope.

dynamicNa
amespace.Imp
ports.Add(new
w CodeNamesp
paceImport("
"System"));

4. Create a Co
odeTypeDeclaration objecct that represe
ents the type you want to aadd 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
odeEntryPoinntMethod objject to represent the static main method
d in the Progrram type.
The followin
ng code exam
mple shows ho
ow to define aan entry pointt 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

Aftter you have defined


d the co
ontents of you
ur assembly bby using the tyypes in the Sy
ystem.CodeD DOM
namespace, you u can then commpile and gennerate an asse
embly. You caan split the proocess for com
mpiling and
ge
enerating an aassembly into the following
g parts:
1. Compiling tthe model and generating source code files
f for each ttype.

2. Generating an assembly that contains the necessaryy 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 sourrce code files, perform the following step
ps:

1. nstance of the
Create an in e code generaator provider yyou want to u
use. The follow
wing code exaample
shows how to create an instance
i of th
he CSharpCod deProvider class that will pproduce Visuaal C# code.

var provi
ider = new C
CSharpCodePro
ovider();

2. Create a StrreamWriter o
object that the code generrator will use tto write the co
ompiled code
e to a file.
The followin
ng code exam
mple shows ho ow to create a StreamWritter object.

var fileN
Name = "prog
gram.cs";
var strea
am = new Str
reamWriter(fileName);

3. Create an In
ndentedTexttWriter objecct that will writte 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 encappsulates your code generattion settings. The
ode example shows how to
following co o create a Cod
deGeneratorO Options obje
ect and set the e
BlankLinessBetweenMem mbers property so that meembers 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 aan Assemb
bly

Aftter 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 asssembly that ccontains the F
FourthCoffee
e.Dynamic.Prrogram type from
f a
source code file
e, perform the
e following ste
eps:

1. Create an in
nstance of the
e code generaator provider yyou want to u
use. The follow
wing code exaample
shows how to create an instance
i of th
he CSharpCod deProvider class that will pproduce the executable
assembly.

var provi
ider = new C
CSharpCodePro
ovider();

2. Create a Co
ompilerParam meters objectt that you will use to define
e the settings for the compiler, such as
which assemmblies to reference, and whhether to generate a .dll orr 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 instructt 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 emblyFromFiile method onn the CSharpC CodeProvide er object to ge
enerate the
assembly. T
The following code example
e shows how tto invoke the CompileAssemblyFromF File
method, paassing the Com a a string vvariable that contains the path to the
mpilerParameters object and
source codee file.

var sourc
ceCodeFileNa
ame = "program.cs";
var compi
ilationResults = provider.CompileAs
ssemblyFromF
File(
compil
lerSettings,
source
eCodeFileNam
me);

Note: Thee CompileAsssemblyFromF 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 applicationn, you should sign and verssion the assem
mbly before yo ou
disstribute it to u
users. You must also consid
der how and wwhere the asseembly is goingg to be installed.

In this lesson, yo
ou will learn h
how to version
n assemblies aand install an assembly into
o the GAC.

Le
esson Obje
ectives
Aftter completing this lesson, you will be ab
ble to:

Describe the key features of assemblie


es.

Describe the GAC.


w to sign an assembly.
Explain how

Describe the key features of assemblyy versioning.

Install an asssembly in the


e GAC.
Programming in Visual C# 12-37
7

W
What Is an
n Assemb
bly?

An assembly iis a collection of types and resources thaat form a unit of functionality. An assembly might
A
c
consist of a single portable PE) file, such aas an executable (.exe) prog
e executable (P gram or dynamic link
l
library (.dll) fille, or it might consist of mu
ultiple PE filess and external resource filess, such as bitm
maps or data
f
files. An assem mbly is the building block of o a .NET Fram mework appliccation because e an application consists off
o or more aassemblies.
one

C
Contents of Assemblie
es
A assembly cconsists of the
An e following co
omponents:

Intermediiate languagee (IL) code. Thee compiler traanslates the so


ource code intto IL, which is the set of
instructio
ons that the ju
ust-in-time (JIT
T) compiler thhen translates to CPU-speciific code befo ore the
applicatio
on runs.

Resourcess. These includ


de images and
d assembly m
metadata. Asse
embly metadaata exists in th
he form of the
e
assembly manifest.
Type mettadata. Type m metadata provvides informattion about avvailable classess, interfaces, m
methods, and
propertie
es, similar to th
he way that a type library p
provides inforrmation aboutt COM compo onents.

The assem
mbly manifestt. This contains assembly metadata and p provides inforrmation aboutt the
assembly such as the title, the descrription, and ve ersion informaation. The manifest also contains
information about linkks to the otherr files in the assembly. The information in the manifesst is used at
run time to resolve references and vvalidate loade ed assemblies.. The assemblyy manifest cann be stored in
n
a separate file but is offten part of on
ne of the PE ffiles.

B
Boundaries
s of Assemb
blies
By arranging yyour code intto assemblies, you create a set of boundaries that you
B u can use to issolate
c
configuration to a particulaar assembly. T
The following list describes some of the boundaries
b th
hat assembliess
p
provide:

Security boundary.
b You
u set security permissions
p at an assemblyy level. You ca
an use these ppermissions to
o
request specific access for an application, for example, file I/O permissions if the applicattion must
write to a disk. When tthe assembly iis loaded at ru
un time, the permissions
p th
hat are requessted are
entered innto the securiity policy and used to determine whethe er permissionss can be grantted.
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 siingle applicattion can use.
I you need to
If o create an assembly that mmultiple appliccations can sh
hare, you shouuld give the assembly a
s
strong name aand install the
e assembly intto the GAC.
A strong name is a unique name for an aassembly thatt consists of th he assemblys name, versio
on number,
c
culture inform
mation, and a digital signatu
ure that contaains a public aand private ke
ey.

The GAC store


T es the assemb
blies that you want to sharee between mu ultiple applications. When yyou add an
a
assembly to th
he GAC, the GAC
G performss integrity che
ecks on all of tthe files that fform the assemmbly. These
c
checks ensure
e that nothing
g has tampere ed with an assembly. For exxample, the GA AC checks forr 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:

al assembly name
The globa
The versio
on number off the assemblyy

The culture of the asse


embly, if applicable

The publiic key token o


of the assembly in the stron
ng name

The type of assembly

B
Benefits off Using the GAC
Although you
A u can install strong-named assemblies in directories on
n the computter, the GAC o
offers several
b
benefits, inclu
uding the folloowing:

Side-by-side deploymen nt and executtion. Different versions of an assembly in n the GAC do not affect
each othe er. Therefore, applications that
t referencee different verrsions of an asssembly do no
ot fail if a
later inco
ompatible verssion of the asssembly is instaalled into the cache.

Improved d loading time. When you in nstall a strongg-named assem mbly in the GAC, it undergoes strong-
name validation, which h ensures thatt the digital signature is vallid. The verificcation processs occurs at
installatio
on time, so strrong-named aassemblies in the GAC load faster at run time than asssemblies that
are not innstalled 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
Assembliess

When you sig


W gn an assemblyy, you give th
he assembly a strong name.. A strong namme provides an assembly
w a globally unique nam
with hen they reference your asssembly. This ensures that
me that applicaations use wh
n one else ca
no an compile an
n assembly with the same n name as yourss and impersoonate your asssembly. This
h
helps to avoid
d malicious co
ode overwritin
ng one of your assemblies aand then beinng run from an n application
t
that our authentic code.
expects to be using yo

A strong name requires two o cryptographhic keys, a public key and a private key, known as a keey pair. The
c
compiler usess the key pair at build time to create the strong name. The strong n name consists of the simplee
t
text name of tthe 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 havve a key pair to
Y o sign an asse
embly with a strong
s name. To create a kkey pair, use th
he Strong
N
Name tool (Sn
n.exe) that the
e .NET Framewwork providess. To create a key pair file, p
perform the following
f
s
steps:

1
1. Open the
e Visual Studio
o 2012 command prompt.

2
2. In the Co
ommand Prom mpt window, use the Sn.exxe 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 wiith the name FourthCoffee eKeyFile.

sn -k FourthCoffee
F KeyFile.snk

A
After you havve created a ke
ey file, you can then sign yo
our assembly..

S
Signing an Assembly
When you havve created the
W e key pair, you can then associate the keey file with yo
our assembly. Y You can
a
achieve this using the Sign
ning tab in thee project prop
perties pane. W
When you spe ecify a key file
e in the
p
properties pane, Visual Studio adds the AAssemblyKey yFileAttributte attribute too the AssemblyInfo class
i your appliccation.
in

The following code example shows how to associate tthe FourthCofffeeKeyFile.sn


T nk file with you
ur assembly
b using the A
by AssemblyKeyyFileAttribute
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 strong-
name 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. In Solution Explorer, right-click the project, and then click Properties.

2. In the properties window of the project, click the Signing tab.


3. Select the Sign the assembly check box.

4. Specify a key file.

5. 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 strong-
name 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

All assembliess are given a vversion number by Visual SStudio, which iis typically 1.0
A 0.0.0. It is the responsibility
o the develop
of per to increment the assemmblys version number as th he assembly e evolves.

IIt is importantt to version asssemblies so tthat you can kkeep track of w


which version
n of your application users
a using. Witthout a version number, de
are ebugging and reproducing production isssues 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 formmat: <major
v
version>.<min nor version>.<
<build numbeer>.<revision> >. For examplee, 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 revisioon number.

The assembly manifest storres the version


T n number along with otherr identity information such as the
a
assembly namme and public key. The CLR uses the verssion number, iin conjunctionn with the avaailable
c
configuration information, to load the p
proper version
n of a referencced assembly.

By default, ap
B pplications onlly run with the version of aan assembly with
w which the ey were built. To
T change an
n
a
application to
o use a differeent version of an assembly, you can creatte a version policy in one o of the
c
configuration files: the app
plication config
guration file, the publisher policy file, orr the computeer's
a
administrator configuration n file.

R
Redirecting
g Binding R
Requests
When you waant to update a strong-nam
W med component without red deploying thee client appliccation that
u
uses it, you caan use a publisher policy file to redirect a binding request to a new
wer instance off the
c
component.

W
When a clientt application m
makes a binding request, th
he runtime pe ollowing tasks:
erforms the fo

It checks the original aassembly referrence for the version


v to be bound.

It checks the configura


ation files for version
v policyy instructions.

The following code example shows a publisher policyy file. To redire


T ect one versio on to another, use the
<bindingRed direct> eleme ent. The oldVe
ersion attribuute can specifyy either a sing
gle version or a range of
v
versions. For e
example, <bin ndingRedirecct oldVersion n="1.1.0.0-1..2.0.0" newV Version="2.0.0.0"/>
s
specifies that the runtime sshould use version 2.0.0.0 in
nstead of the assembly verrsions 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 ffolder on file system where


T e you can instaall your assem
mblies. You can install your assemblies
i
into the GAC in a variety off ways, which include the fo
ollowing:

Global Asssembly Cachee tool (Gacutill.exe). You can


n use Gacutil.eexe to add strrong-named aassemblies to
the GAC aand to view th he contents oof the GAC. Gaacutil.exe is fo
or developmen nt purposes. Y
You should
not use th
he tool to insttall production assemblies into the GAC..

Microsoftt Windows Installer 2.0. Thiss is the recom


mmended and most commo on way to add d assemblies
to the GA
AC. The installer provides benefits such aas reference co
ounting of asssemblies in th
he GAC.

I
Installing a
an Assembly
y into the G
GAC by Using Gacutil..exe
To install an aassembly into the GAC by using
T u the Gacu
util.exe comm
mand-line tooll, perform the
e following
s
steps:

1
1. Open the
e Visual Studio
o 2012 command prompt aas an administtrator.

2
2. 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 iss installed into
T o the GAC by using the Gaccutil.exe comm
mand-line too
ol, perform
t following steps:
the

1
1. Open the
e Visual Studio
o 2012 command prompt aas an administtrator.

2
2. In the Co
ommand Prom
mpt window, type the follo
owing comma
and:

gacutil l "<assemblyName>"

Additioonal Reading: For more infformation abo out the GAC, ssee the Globa
al Assembly Caache
p
page at http:///go.microsoftt.com/fwlink//?LinkID=2678
876.
12-46 Creating Reusable Types and Assemblies

Demonstration: Sign
ning and IInstalling an Assem
mbly into tthe GAC

In this demonstration, you wiill use the Sn.e


exe and Gacutil.exe commaand-line toolss to sign and install an
existing assemb
bly into the GA
AC.

De
emonstration Steps
1. Start the MSL-TMG1 virtual machine if it is not already running.

2. 0483A-SEA-DEEV11-12 virtual machine.


Start the 20

3. Log on to W
Windows 8 as Student with
h the password Pa$$w0rd.

Note: If necessary, clickk Switch Userr to display th


he list of userss.

4. he Windows 8 Start window


Switch to th w.

5. In the Searcch box, type ccommand, right-click VS201


12 x64 Cross Tools
T Comma
and Prompt, aand then
click Run ass administrato
or.

6. In the Userr Account Con


ntrol dialog b 0rd, and then click Yes.
box, in the Password box, type Pa$$w0
7. In the VS20
012 x64 Cross Tools Comm mand Promp pt window, ch hange to the
E:\Democod ore\FourthCofffee.Core directory.
de\Starter\FourthCoffee.Co

8. Run the gen


nerateKeyFile.cmd file. The
e generateKeyyFile.cmd file u
uses the Sn ap
pplication to g
generate a
key file.

9. he Windows 8 Start window


Switch to th w.

0. Click Visual Studio 2012.


10

File menu, point to Open, and


udio, on the F
11. In Visual Stu a then clickk Project/Solution.

12. In the Open


n Project diallog box, brow Democode\Staarter\FourthCoffee.Core folder, click
wse to the E:\D
FourthCofffee.Core.sln, and then click Open.
13. In Solution Explorer, righ
ht-click the Fo Core project, and then clickk Open Folde
ourthCoffee.C er in File
Explorer.

4. In File Explo
14 orer, highlightt the FourthCo
offeeKeyFile.ssnk file that th
he Sn applicattion generated
d.
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 wiill see the taskks that you wiill 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 GGrades applicaation 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 formmat them appropriately. This will enable further
r
reusability of the Microsoftt Word reportting functionaality.

You will host tthis code in th


Y he GAC to ensure that it is available to other
o applications that requ
uire its
s
services.

O
Objectives
A
After completting this lab, you
y will be able to:

Define cu
ustom attributtes.

Use reflecction to examine metadata at run time.

Sign an assembly and d


deploy it to th
he GAC.

E
Estimated Tim
me: 75 minutes

3-SEA-DEV11-12, MSL-TMG
Virtual Machine: 20483 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. Start the MSL-TMG1 virtual machine if it is not already running.

2. Start the 20483A-SEA-DEV11-12 virtual machine and log on as Student with the password
Pa$$w0rd.
3. Start Visual Studio, and then open the Grades.sln solution from the E:\Labfiles\Starter\Exercise 1
folder.

4. Set the following projects to start without debugging at startup:


a. Grades.Web

b. Grades.WPF

5. In the Grades.Utilities project, in the IncludeInReport.cs class, add code to specify that the
IncludeInReportAttribute class is an attribute class.

6. 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.

7. In the IncludeInReportAttribute class, define a private Boolean variable named _include to hold the
value of the attribute.

8. In the IncludeInReportAttribute class, define two public read/write Boolean properties named
Underline and Bold.

9. 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. Build the solution, and then resolve any compilation errors.

2. 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. In Visual Studio, open the Grades.sln solution from the E:\Labfiles\Starter\Exercise 2 folder.
2. In the Grades.Utilities project, open IncludeInReport.cs.

3. Locate the FormatField struct declaration, and then add two string members named Value and
Label and two Boolean members named IsBold and IsUnderlined.

4. 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.
5. Add code to iterate through all of the public fields and properties.

6. In the loop, add code to retrieve all the custom attributes applied to an item.

7. Then use the Array.Find method to test whether any of the custom attributes applied to the item are
the IncludeInReport attribute.

8. At the end of the loop, add code to find the value of the item that is tagged with the
IncludeInReport attribute.
9. 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.

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.

2. 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.

3. Build the solution, and then resolve any compilation errors.


4. Close the 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.
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. In Visual Studio, open the Grades.sln solution from the E:\Labfiles\Starter\Exercise 3 folder.

2. Set the following projects to start without debugging at startup:


a. Grades.Web

b. Grades.WPF

3. Run the VS2012 x86 Native Tools Command Prompt window as Administrator.
4. Run the Sn.exe utility to create a key pair file named GradesKey.snk in the E:\Labfiles\Starter folder.

5. 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.

6. Build the solution, and then resolve any compilation errors.

7. At the command prompt, use the Gacutil utility to add the Grades.Utilities assembly to the GAC.

8. Close the Command Prompt window.

X Task 2: Reference the Grades.Utilities assembly in the GAC from the application
1. In Visual Studio, remove the current reference to the Grades.Utilities project from the Grades.WPF
project.

2. Add a new reference to the signed Grades.Utilities.dll assembly.

3. Build the solution, and then resolve any compilation errors.

4. Run the application.

5. Log on as vallee with a password of password99.


6. Create and save a grades report for Kevin Liu.

7. Close the application, and then close the solution.

8. Open the grades report that you just created in Word and verify that the document contains a
correctly formatted report.

9. 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 Reviiew and
d Takea
aways

M
Module Revie
ew
In this module, yyou learned how
h to consumme existing asssemblies by uusing reflectio
on and how to o add
additional metaadata to typess and type me embers by usin ng attributes. You also learned how to g generate
code at run time e by using CoodeDOM and how you can ensure that yyour assemblie es are versioned and
avaailable to other application
ns by using the GAC.

Ve
erify the correcctness of the statement by placing a maark in the column to the rig
ght.

S
Statement Answer

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 attemptt to
e
execute any ccode; it will meerely serve as a viewer. Youu notice the co
ode that
l
loads the asseembly uses the e Assembly.L LoadFrom staatic method. T This is the
m
most suitable method takin ng into account the require ements of thee
a
application.

Test Your Know


wledge

Q
Question

Y
You are develooping a custo om attribute. You want to derive your custom
c attrib
bute class
frrom the abstract base classs that underp
pins all attributes. Which cclass should yyou use?

S
Select the corrrect answer.

Attribu
ute

ContexxtAttribute

ExtenssionAttribute

DataA
Attribute
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 Answer

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.

13-1

Module 13
Encrypting and Decrypting Data
Contents:
Module Overview 13-2

Lesson 1: Implementing Symmetric Encryption 13-3

Lesson 2: Implementing Asymmetric Encryption 13-15


Lab: Encrypting and Decrypting the Grades Report 13-26

Module Review and Takeaways 13-32


13-2 Encrypting and Decrypting Data

Modu
ule Ove
erview

It iis a common requirement forf applications to be able to secure info ormation, wheether it is a caase of
encrypting files saved to diskk or web requeests sent overr an untrusted d connection tto other remo ote systems.
The Microsoft .NET Framew work providess a variety of cclasses that en
nable you to secure
s your daata by
usiing encryption and hashing g.
In this module, yyou will learn how to impleement symme etric and asym
mmetric encryption and how w to use
hashes to generrate mathema atical represen will also learn how to create and
ntations of your data. You w
maanage X509 certificates and d how to use tthem in the asymmetric en ncryption proccess.

Ob
bjectives
e, you will be able to:
Aftter completing this module

Encrypt datta by using symmetric encryption.


Encrypt datta by using asyymmetric enccryption.
Program
mming in C# 13-3
3

Lesson 1
Implementiing Sym
mmetricc Encry
yption

SSymmetric en ncryption is the process of p


performing a cryptographicc transformation of data byy using a
m
mathematical algorithm. Syymmetric encryption is an e
established te
echnique and is used by maany
a
applications to provide a roobust way of protecting co
onfidential datta.

IIn this lesson, you will learn


n about severa
al .NET Frame
ework classes tthat enable applications to
o secure data
b means of e
by encryption and hashing.

L
Lesson Ob
bjectives
A
After completting this lesson, you will be able to:

Describe symmetric en
ncryption.

Encrypt aand decrypt daata by using ssymmetric enccryption.

Create dig
gital fingerpriints of data byy using hashe
es.
13-4 Encrypting and Decrypting Data

W
What Is Sym
mmetric Encryption
E n?

The name symm metric is deriveed from the faact that the saame secret ke
ey is used to e
encrypt and de
ecrypt the
data. Therefore,, when you usse symmetric e encryption, yoou must keep the secret ke ey secure.

To
o help improve e the effectiveeness of symm metric encrypttion, many sym mmetric encryyption algoritthms also
use
e an initializattion vector (IV
V) in addition to a secret ke
ey. The IV is an
n arbitrary bloock of bytes that helps to
ran
ndomize the ffirst encrypted d block of datta. The IV makkes it much m more difficult ffor a maliciouss user to
de
ecrypt your da ata.

Ad
dvantages a
and Disadv
vantages off Symmetric Encryptio
on
The following taable describess some of the advantages and
a disadvanttages of symm
metric encrypttion.

A
Advantage Disadvantage
e

There is no lim
T mit on the am
mount of data you can The same key is used to encrypt and de ecrypt the
e
encrypt. data. If the kkey is comprom
mised, anyone
e can
encrypt and decrypt the d data.

SSymmetric alggorithms are ffast and consu


ume far If you choosee to use a diffferent secret kkey for
f
fewer system resources thaan asymmetricc different data, you could end
e up with manym
a
algorithms. different secret keys that you
y need to manage.
m

Symmetric algorithms are perfect for quickkly 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.Seccurity.Crypto ography name espace,
whhich provide managed
m implementations of common ssymmetric enccryption algorrithms, such as a
Ad
dvanced Encryyption Standard (AES), Dataa Encryption SStandard (DESS), and TripleD
DES. Each .NET
T
Fraamework symmmetric encrypption class is d
derived from tthe abstract S
SymmetricAlg gorithm basee class.
The following taable describess the key charracteristics of tthe.NET Fram
mework encryp
ption classes.

Encryption
A
Algorithm .NET Frame
ework Class Block Size
S Key
y Size
Technique
Programming in C# 13-5

Encryption
Algorithm .NET Framework Class Block Size Key Size
Technique

DES DESCryptoServiceProvider Bit shifting 64 bits 64 bits


and bit
substitution

AES AesManaged Substitution- 128 bits 128, 192, or


Permutation 256 bits
Network (SPN)

Rivest Cipher RC2CryptoServiceProvider Feistel 64 bit 40-128 bits


2 (RC2) network (increments
of 8 bits)

Rijndael RijndaelManaged SPN 128-256 bits 128, 192, or


(increments 256 bits
of 32 bits)

TripleDES TripleDESCryptoServiceProvider Bit shifting 64 bit 128-192 bits


and bit
substitution

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 encryptt data by usinng any of the ssymmetric encryption classses in the
Sy
ystem.Securitty.Cryptograp phy namespaace. However, these classes only provide managed
implementation ns of a particular encryption n algorithm; for example, the AesManag
ged class provvides a
maanaged imple ementation of the AES algorithm. Aside ffrom encrypting and decrypting data byy using an
alg
gorithm, the encryption
e proocess typicallyy involves the following tassks:

Derive a seccret key and aan IV from a password


p or sa
alt. A salt is a random colle
ection of bits u
used in
combinatio on with a passwword to gene erate a secret key and an IV V. A salt makess it much morre 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 simplifyy the encryptio
on logic in yo
our application
ns, the .NET Framework inccludes a numb
ber of other
cryyptography classes that youu can use.

Th
he Rfc2898DeriveByte
es and Cryp
ptoStream C
Classes
The Rfc2898De eriveBytes claass provides an implementaation of the password-base ed key derivattion
fun
nction (PBKDFF2), which com
mplies with th PKCS). You can use the
he Public-Key Cryptographyy Standards (P
PB
BKDF2 functionality to derivve your secrett keys and you
ur IVs from a password and
d a salt.

Additionaal Reading: FFor more inforrmation about the Rfc2898 8DeriveBytess class, see the
Rfcc2898DeriveB
Bytes Class pagge at http://g
go.microsoft.com/fwlink/?LinkID=267878
8.

The CryptoStre eam class is de


erived from thhe abstract Sttream base claass in the Sysstem.IO nameespace, and
it p
provides strea
aming functionality specificc to reading and writing cryyptographic trransformation
ns.

Additionaal Reading: FFor more inforrmation about the CryptoSStream class, see the
CryyptoStream C
Class page at http://go.micr
h rosoft.com/fw
wlink/?LinkID=
=267879.

Sy
ymmetrically Encrypting and Deccrypting Da
ata
pt data by using the AesManaged class:
The following stteps describe how to encryypt and decryp
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 nnumerical reprresentation off your data. Tyypically, hash algorithms
c
compute hash
hes by mappin ng the binary representatio on of your datta to the binary values of a fixed-length
h
hash. If you use a proven hhash algorithm
m, it is consideered unlikely tthat you could
d compute the same hash
f
from two diffe
erent pieces of
o data. Thereffore, hashes are
a considered d a reliable waay to generate
e a unique
d
digital fingerp
print that can help to ensurre the integritty of data.

Consider the e
C example of th
he FourthCoffee.Beverage sservice, which sends messagges 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 wass not sabotage
ed during thee transmission
n? You could u
use hashes, ass
t following steps describe:
the
1
1. Compute
e a hash of the
e message beffore the FourtthCoffee.Beve
erage service sends
s the messsage.

2
2. Compute
e a hash of the
e message wh
hen the Fourth
hCoffee.Inventory service re
eceives the message.

3
3. Compare the two hashhes. 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 numberr of classes in the System.S
Security.Cryp
ptography namespace,
w
which encapsulate common hash algoritthms.

H
Hash Algorrithms in th
he .NET Framework
T following table describ
The bes some of th
he hash classe
es that the .NEET Frameworkk provides.

.NET Framew
work Class Descriptio
on

SHA512Ma
anaged The SHA5 512Managed d class is an im
mplementation of the
Secure Ha ash Algorithm
m (SHA) and iss able to comp
pute a 512-
bit hash. T
The .NET Frammework also includes classe
es that
implemen nt the SHA1, SSHA256, and SHA384 algorrithms.

HMACSHA
A512 The HMA ACSHA512 cla ass uses a com
mbination of tthe SHA512
hash algo
orithm and the
e Hash-Based d Message Autthentication
Code (HMMAC) to comp pute a 512-bitt hash.

MACTriple
eDES The MAC CTripleDES claass uses a com
mbination of the
t TripleDES
encryptio
on algorithm aand a Message Authenticattion Code
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.

RIPEMD160Managed The RIPEMD160Managed class is derived from the MD


algorithm and is able to compute a 160-bit hash.

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.
2. Create an instance of the hash algorithm.

3. 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.

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 Daata

I this demon
In nstration, you will use symm
metric encrypttion to encryp
pt and decryptt a message.

D
Demonstra
ation Steps
1
1. Start the MSL-TMG1 viirtual machine
e if it is not already running
g.

2
2. Start the 20483A-SEA
A-DEV11-13 vvirtual machine.

3
3. Log on to
o Windows 8 as Student with the passsword Pa$$w0rd.

Note: Iff necessary, click Switch Usser to display the list of use
ers.

4
4. Switch to the Windowss 8 Start wind
dow.

5
5. Click Visu
ual Studio 20
012.
6
6. In Microssoft Visual Studio, on the File menu, po
oint to Open,, and then clicck Project/So
olution.

7
7. In the Op
pen Project dialog box, bro
owse to the E::\Democode\\FourthCoffe
ee.MessageSa
afe folder,
click FourrthCoffee.Me
essageSafe.sln, and then cclick Open.

8
8. In Visual Studio, on the
e View menu,, click Task Liist.

9
9. In the Tassk List windo
ow, in the Cate
egories list, click Commen
nts.

1 Double-cclick the TODO


10. O: 01: Instanttiate the _alg
gorithm obje
ect. task.

1 Explain th
11. hat the follow
wing code crea
ates an instancce of the AesManaged claass.

this._al
lgorithm = new
n AesManaged();

1 Double-cclick the TODO


12. O: 02: Disposse of the _alg
gorithm object. task.

1 Explain th
13. hat the follow
wing code deteermines whethher the _algorithm object is not null and then
invokes th
he Dispose method
m to rele
ease any resou e algorithm may have used..
urces that the

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
Implementiing Asy
ymmetrric Encrryption

Asymmetric e
A encryption is the process off performing a cryptograph
hic transforma
ation of data b
by using an
a
asymmetric ncryption algo
en orithm and a combination of public andd private keys..

IIn this lesson, you will learn


n about the classes and too
ols that you caan use to implement asymm
metric
e
encryption in your applicattions.

L
Lesson Ob
bjectives
A
After completting this lesson, you will be able to:

Describe asymmetric e
encryption.
Encrypt aand decrypt daata by using aasymmetric en
ncryption.

Create an
nd manage X5
509 certificate
es.

Manage encryption
e ke
eys in your app
plications.
13-16 Encryppting and Decrypting Data

W
What Is Asy
ymmetric Encryptio
on?

Un
nlike symmetrric encryption,, where one se
ecret key is ussed to perform
m both the en
ncryption and the
de
ecryption, asym
mmetric encryyption uses a public key to perform the encryption an nd a private ke
ey to
pe
erform the deccryption.

Note: Thee public and pprivate keys arre mathematiccally linked, in


n that the privvate key is use
ed
to derive the pu
ublic key. How
wever, you can nnot derive a private key frrom a public kkey. Also, you
can only decryppt data by usin
ng the privatee key that is lin
nked to the public key thatt was used to
encrypt the dataa.

In a system thatt uses asymme etric encryptioon, the publicc key is made available to any application
n that
quires the ability to encrypt data. Howevver, the privatte key is kept safe and is on
req nly distributed
d to
pplications thaat require the ability to decrypt the data.. For example, HTTPS uses asymmetric encryption
ap
to encrypt and d decrypt the browsers session key when establishing a secure connection betwee en the
bro
owser and the e server.

Note: Youu can also usee asymmetric algorithms


a to sign data. Siggning is the process of
ge
enerating a dig
gital signaturee so that you can ensure th
he integrity off the data. Wh
hen signing
data, you use th
he private keyy to perform th
he signing and then use the public key tto verify the
data.

Ad
dvantages a
and Disadv
vantages off Asymmetrric Encryption
a disadvanttages of asymmetric encryp
The following taable describess some of the advantages and ption.
Programming in C# 13-17

Advantage Disadvantage

Asymmetric encryption relies on two keys, so it is With asymmetric encryption, there is a limit on the
easier to distribute the keys and to enforce who amount of data that you can encrypt. The limit is
can encrypt and decrypt the data. 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 use larger keys than Asymmetric algorithms are very slow in
symmetric algorithms, and they are therefore less comparison to symmetric algorithms.
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. Encrypt the data by using a symmetric algorithm, such as the AesManaged class.

2. Encrypt the symmetric secret key by using an asymmetric algorithm.

3. 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
Encrypting Data by
y Using Assymmetricc Encryption

You can encryypt your data asymmetrically by using th


Y he RSACrypto
oServiceProv
vider class in tthe
S
System.Secur rity.Cryptogrraphy namesppace.

E
Encrypting Data by Ussing the RS
SACryptoSe
erviceProvid
der Class
The RSACryp
T ptoServiceProovider class provides a num mber of memb bers that enab ble you to imp
plement
a
asymmetric ncryption functionality in your
en y applicatio
ons, including
g the ability to
o import and e
export key
i
information and encrypt annd decrypt da ata.
You can creatte an instance of the RSACrryptoService
Y eProvider classs by using the
e default consstructor. If
y choose th
you his approach, the RSACrypptoServiceProovider 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 defaault constructtor.

I
Instantiating
g the RSACryp
ptoServicePrrovider Class
var rsaProv
vider = new RSACryptoServiceProvide
er();

After you havve created an iinstance of th


A he RSACrypto
oServiceProviider class, you
u can then use
e the Encryptt
a Decrypt methods to p
and protect your d data.

The following code example shows how you can use tthe Encrypt aand Decrypt m
T 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(plaiinText);
var decrypt
tedText = st
tring.Empty;
using (var rsaProvider
r = new RSACryptoServiceeProvider())
)
{
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.GetStrinng(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 aand Manaaging X509 Certificaates

An X509 certificate is a digital documentt that contain


A ns information n, such as the name of the organization
o
t
that X509 certificaates are normaally stored in ccertificate sto
is supplyiing the data. X ores. In a typiccal Windows
i
installation, th
here are user account,
a serviice account, and local computer machine certificate stores.
X509 certificates can also ccontain publicc and private kkeys, which yo
X ou can use in the asymmetric encryption
n
p
process. You ccan create and d manage you ur X509 certifficates by usin
ng the tools th
hat Windows and
a the .NET
F
Framework prrovide.

C
Creating a Certificate by Using M
MakeCert
MakeCert is a certificate cre
M eation tool th
hat the .NET Framework pro ovides. You caan access the tool by using
t Visual Studio command
the d prompt. Thee MakeCert to ool provides a number of command-line e switches
t
that enable yo
ou to configure the X509 certificate to mmeet the requirements of your applicatio on.

T following table describ


The bes some of th e switches.
he MakeCert ccommand-line

Switch Description

-n This enables you to


o specify the n
name of the ce
ertificate.

-a This enables you to


o specify the aalgorithm thatt the certificatte uses.

-pe This enables you to


o create a certtificate that allows you to export the privvate key.

-r This enables you to


o create a self--signed certifiicate.

-sr This enables you to


o specify the n
name of the ce
ertificate store
e where the M
MakeCert tool
mport the generated certificcate.
will im

-ss This enables you to


o specify the n
name of the coontainer in th
he certificate store
s where
the MakeCert tool wwill import the generated ccertificate.

-sky This enables you to


o specify the tyype of key tha
at the certifica
ate will contain.

The following code example shows how you can use tthe MakeCertt command-line tool to gen
T nerate a self-
s
signed certificcate, 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. 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.

2. In the Windows 8 Start window, use search to find mmc.exe, and then click mmc.exe.
3. In the MMC window, on the File menu, click Add/Remove Snap-in.

4. In the Add or Remove Snap-ins dialog box, in the Available snap-ins list, click Certificates, and
then click Add.
5. 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. If you chose My user account, click Finish.

b. If you chose Service account, click Next, and then perform the following steps:

i. In the Select Computer dialog box, click Next.

ii. In the Certificates snap-in dialog box, in the Service account list, click the service account
you want to manage, and then click Finish.

c. If you chose Computer account, click Next, and then click Finish.

6. 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 Encryptiion Keys

The .NET Fram


T mework provid des the Syste
em.Security.CCryptography y.X509Certifiicates namesp pace, which
c
contains a number of classees that enable
e you to use X509
X certificattes and their kkeys in your applications.
T
These classes include the fo
ollowing:
X509Storre. This class eenables you to access a cerrtificate store and perform operations, su
uch as
finding an
n X509 certificcate with a paarticular name
e.

X509Certtificate2. This class enable es you create aan in-memoryy representation of an X509 9 certificate
that curre ou have instantiated an X5
ently exists in a certificate sstore. When yo 509Certificate e2 object,
you can tthen use its members
m to access information, such as th
he X509 certifficates publicc and private
keys.
PublicKeey. This class e
enables you too manipulate the various pieces of metadata that are associated
X509 certificates public keyy, such as the public keys vvalue.
with an X

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, StoreeLocation.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.Certifficates)
{
if (stor
reCertificat
te.SubjectName.Name == ccertificateN
Name)
{
certi
ificate = st
toreCertificate;
conti
inue;
}
}
store.Close
e();

After you havve created an X


A X509Certifica ate2 object, yyou can use its members to o determine w
whether the
X
X509 certificate contains eiither a public or private keyy. 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 Graade Reports Lab

I this demon
In nstration, you will learn abo
out the tasks tthat you will p
perform in the
e lab for this module.
m
13-26 Encryppting and Decrypting Data

Lab: E
Encrypting and
d Decry
ypting tthe Gra
ades Re
eport

Sccenario
Yo
ou have been asked to updaate the Grade es application to ensure thaat reports are secure when they are
sto
ored on a userr's computer. You decide to o use asymme etric encryptioon to protect the report as it is
geenerated, befo
ore it is written
n to disk. Adm
ministrative sta
aff will need tto merge repoorts for each cclass into
onne document, so you decide e to develop a separate application that generates a combined
c rep
port and
priints it.

Ob
bjectives
Aftter completing this lab, you
u will be able to:

Encrypt datta by using asyymmetric enccryption.

Decrypt datta.

Esttimated Time:: 75 minutes

Virtual Macchine: 20483A


A-SEA-DEV11--13, MSL-TMG
G1

User Name: Student

Password: Pa$$w0rd
P
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. Start the MSL-TMG1 virtual machine if it is not already running.

2. Start the 20483A-SEA-DEV11-13 virtual machine and log on as Student with the password
Pa$$w0rd.

3. Start Visual Studio, and then open the Grades.sln solution from the E:\Labfiles\Starter\Exercise 1
folder.

4. Set the following projects to start without debugging at startup:

a. Grades.Web

b. Grades.WPF

5. In the Grades.Utilities project, review the contents of the CreateCertificate.cmd file.

6. In a command window running as Administrator, navigate to the E:\Labfiles\Starter\Exercise


1\Grades.Utilities folder and then run CreateCertificate.cmd.
7. 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. In the Grades.Utilities project, in the WordWrapper class, locate the GetCertificate method.

2. Add code to this method to loop through the certificates in the store.Certificates collection.

3. 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. In the Grades.Utilities project, in the WordWrapper class, locate the EncryptWithX509 method.

2. 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.

4. 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.
5. 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());

6. Add a closing brace for the using statement at the end of the method.
7. 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. The length of the secret key.

b. The length of the IV.

c. The encrypted secret key.

d. The IV.

e. 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. Build the solution and resolve any compilation errors.

2. Run the application.

3. Log on as vallee with a password of password99.

4. Generate grade reports for George Li and Kevin Liu, saving each report in the E:\Labfiles\Reports
folder.

5. Close the application, and then close the solution.


6. 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. In Visual Studio, open the School-Reports.sln solution from the E:\Labfiles\Starter\Exercise 2
folder.

2. In the WordWrapper class, locate the DecryptWithX509 method.

3. 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.
5. 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.
6. 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];

7. Add code to read the key and IV lengths from index 0 in the memory stream and then convert the
two lengths to integers.

8. Add code to determine the starting position and length of the encrypted data.

9. 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. Build the solution, and then resolve any compilation errors.

2. 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.

3. Close the application, close the solution, and then close Visual Studio.
4. 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 Encryppting and Decrypting Data

Modu
ule Reviiew and
d Takea
aways

M
Module Revie
ew
In this module, yyou learned how
h to implemment symmetric and asymm
metric encrypttion and how to use
hashes to generrate mathema atical represen
ntations of your data.
Test Your Know
wledge

Q
Question

FFourth Coffee
e wants you to o implement an encryptio on utility that can encrypt and
ddecrypt large image files. E
Each image wwill be more th han 200 meg gabytes (MB) in size.
FFourth Coffee
e envisages thhat only a sma all internal te
eam will use this tool, so co
ontrolling
wwho can encryypt and decry ypt the data iis not a conceern. Which off the following
teechniques will you choose e?

S
Select the corrrect answer.

Symm
metric encryption

Asymm
metric encryption

Hashin
ng

Ve
erify the correcctness of the statement by placing a maark in the column to the rig
ght.

S
Statement Answer

IIs the followin


ng statement true or false? Asymmetric e
encryption uses a
p
public key to encrypt data.
Programm
ming in C# 13-33
3

Courrse Evalluation

Y
Your evaluatio
on of this cou
urse will help M
Microsoft und
derstand the q
quality of yourr 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 aand honest fe
eedback is valuuable and apppreciated.

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. Start the MSL-TMG1 virtual machine if it is not already running.

2. Start the 20483A-SEA-DEV11-01 virtual machine.


3. 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. Switch to the Windows 8 Start window.

5. Click Visual Studio 2012.

6. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.
7. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click School.sln, and then
click Open.

8. In Solution Explorer, expand School, and then expand MainWindow.xaml.

9. 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. 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.
2. 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. 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.

4. 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. In the Task List window, double-click the TODO: Exercise 1: Task 3a: Display the form task.

2. 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. 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.

5. 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. 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.

7. In the code editor, click at the end of the comment line, press Enter, and then type the following
code:

8. 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. On the Debug menu, click Start Without Debugging.

3. 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. Click the row containing the name Kevin Liu.

5. 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. In the Last Name text box, delete the existing contents, type Cook, and then click OK.
7. Verify that Liu has changed to Cook in the students list, and that the Save Changes button is now
enabled.

8. Close the application.

X Task 5: Use the Visual Studio Debugger to step through the code.
1. 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.

2. 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.

3. On the Debug menu, click Start Debugging.


MCT USE ONLY. STUDENT USE PROHIBITED
L01-4 Programming in Visual C#

4. Click the row containing the name George Li, and then press Enter.

5. When Visual Studio enters break mode, in the bottom left window, click the Watch 1 tab.
6. In the Watch 1 window, click below Name to create a blank row.

7. In the Name column, type sf.Title, and then press Enter.

8. In the Watch 1 window, click below sf.Title to create a blank row.

9. 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 Value

First Name Dominik

Last Name Dubicki

Date of Birth 8/10/2005

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.


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. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

2. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click School.sln, and then
click Open.
3. In the Task List window, double-click the TODO: Exercise 2: Task 1a: If the user pressed Insert, add a
new student task.

4. 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. 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.
2. In the code editor, click at the end of the comment line, press Enter, and then type the following
code:

sf = new StudentForm();

3. 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.

4. 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. 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.

2. 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. 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.
5. 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. In the Task List window, double-click the TODO: Exercise 2: Task 4a: Assign the new student to the
current teacher task.
2. 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. In the Task List window, double-click the TODO: Exercise 2: Task 4b: Add the student to the list
displayed on the form task.

4. 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. 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.

6. 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. On the Build menu, click Build Solution.

2. On the Debug menu, click Start Without Debugging.


3. Verify that the application starts and displays the initial list of students.

4. Click the row containing the name Kevin Liu.

5. Press Insert and verify that the new student window appears:
6. In the First Name text box, type Darren.

7. In the Last Name text box, type Parker.

8. In the Date of Birth text box, type 02/03/2006, and then click OK.
9. 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. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

2. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 3, click School.sln, and then
click Open.
3. In the Task List window, double-click the TODO Exercise: 3: Task 1a: If the user pressed Delete,
remove the currently selected student task.

4. 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. 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.
2. 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. 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.

2. 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. 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.

5. 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. On the Debug menu, click Start Without Debugging.

3. Verify that the application starts and displays the initial list of students.
4. Click on the drop-down menu containing the text Esther Valle: Class 3C.

5. Click the list item containing the text David Waite : Class 4B.

6. Click the row containing the name Jon Orton.

7. Press Delete and verify that the confirmation prompt appears.

8. 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.
9. 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. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

2. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 4, click School.sln, and then
click Open.
3. On the Build menu, click Build Solution.

4. In Solution Explorer, expand the School, and then double-click the MainWindow.xaml and view the
XAML code.

5. 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. 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.

2. 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. In the Task List window, double-click the TODO: Exercise 4: Task 2b: Convert the value provided into a
DateTime value task.
5. 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. 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.

7. 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. In the Task List window, double-click the TODO: Exercise 4: Task 2d: Convert this result into a number
of years task.

9. 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. On the Build menu, click Build Solution.

2. On the Debug menu, click Start Without Debugging.

3. Verify that the application starts and displays the initial list of students, with their ages.

4. Click the row containing the name Kevin Liu.

5. Press Insert.
6. 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.

7. Click OK and verify that your name and age display correctly in the student list.
8. Close the application.

9. On the File menu, click Close Solution.

Results: After completing this exercise, the application will display a students age in years.
MCT USE ONLY. STUDENT USE PROHIBITED
L02-1

Module 02: Creating Methods, Handling Exceptions, and


Monitoring Applications
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. Start the MSL-TMG1 virtual machine if it is not already running.
2. Start the 20483A-SEA-DEV11-02 virtual machine.

3. 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. Switch to the Windows 8 Start window.

5. Click Visual Studio 2012.


6. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

7. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click School.sln, and then
click Open.

8. In Solution Explorer, expand School, expand MainWindow.xaml, and then double-click


MainWindow.xaml.cs.

9. 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. On the Build menu, click Build Solution.
2. On the Debug menu, click Start Without Debugging.

3. Click the row containing the name Kevin Liu and then press Enter.

4. Verify that the Edit Student Details window appears, displaying the correct details.
5. In the Last Name box, delete the existing contents, type Cook, and then click OK.

6. Verify that Liu has changed to Cook in the students list, and that the Save Changes button is now
enabled.
7. Double-click the row containing the name George Li.

8. Verify that the Edit Student Details window appears, displaying the correct details.

9. 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. On the Analyze menu, click Analyze Solution for Code Clones.

2. In the Code Clone Analysis Results window, expand Exact Match.

3. Double-click the second row containing the text MainWindow:studentsList_MouseDoubleClick.

4. 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
MCT USE ONLY. STUDENT USE PROHIBITED
L02-3

// 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;
}

6. On the Edit menu, point to Refactor, and then click Extract Method.
7. In the Extract Method dialog box, in the New method name box, delete the existing contents, type
editStudent, and then click OK.

8. 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. In the Task List window, double-click the TODO: Exercise 1: Task 4a: Refactor as the addNewStudent
method task.

2. 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. On the Edit menu, point to Refactor, and then click Extract Method.

4. In the Extract Method dialog box, in the New method name box, type addNewStudent, and then
click OK.
5. 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. In the Task List window, double-click the TODO: Exercise 1: Task 4b: Refactor as the removeStudent
method task.

7. 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. On the Build menu, click Build Solution.

2. On the Debug Menu, click Start Without Debugging.


MCT USE ONLY. STUDENT USE PROHIBITED
L02-5

3. Click the row containing the name Kevin Liu, and then press Insert.

4. Verify that the New Student for Class 3C window appears.


5. In the First Name box, type Dominik.

6. In the Last Name box, type Dubicki.

7. In the Date of Birth box, type 02/03/2006 and then click OK.

8. Verify that Dominik Dubicki has been added to the students list.

9. 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. 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.

2. On the Debug menu, click Start Debugging.

3. Click the row containing the name Kevin Liu and press Enter.
4. In the Immediate window, click the Call Stack tab.

5. Note that the current method name is displayed in the window.

6. In the Watch 1 window, click the Locals tab.


7. Note the local variables this, sender, e, and student are displayed in the window.

8. On the Debug menu, click Step Over.

9. 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. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

2. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click School.sln, and then
click Open.
3. On the Build menu, click Build Solution.

4. On the Debug menu, click Start Without Debugging.

5. Click on the row containing the name Kevin Liu, and then press Insert.
6. Leave the First Name and Last Name boxes empty.

7. In the Date of Birth box, type 10/06/3012, and then click OK.

8. Verify that a new row has been added to the student list, containing a blank first name, blank last
name, and a negative age.

9. Close the application.

X Task 2: Add code to validate the first name and last name fields
1. In the Task List window, double-click the TODO: Exercise 2: Task 2a: Check that the user has provided
a first name task.

2. 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. In the Task List window, double-click the TODO: Exercise 2: Task 2b: Check that the user has provided
a last name task.

4. 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. 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.

2. 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. In the Task List window, double-click the TODO: Exercise 2: Task 3b: Verify that the student is at least
5 years old task.

4. 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. On the Build menu, click Build Solution.

2. On the Debug menu, click Start Without Debugging.


3. Click on the row containing the name Kevin Liu, and then press Insert.

4. Leave the First Name, Last Name, and Date of Birth boxes empty and click OK.

5. Verify that an error message appears containing the text The student must have a first name.

6. In the Error message box, click OK.

7. In the new student window, in the First Name box, type Darren, and then click OK.

8. Verify that an error message appears containing the text The student must have a last name.

9. 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. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

2. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 3, click School.sln, and then
click Open.
3. On the Build menu, click Build Solution.

4. On the Debug menu, click Start Without Debugging.

5. Click the row containing the name Kevin Liu.


6. Press Enter and verify that the Edit Student Details window appears displaying the correct details.

7. In the Last Name box, delete the existing contents, type Cook, and then click OK.

8. Verify that Liu has changed to Cook in the students list, and that the Save Changes button is now
enabled.

9. 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. 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.

2. 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. 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.

4. 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.
3. 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();
}

4. 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.

5. 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.

7. 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);
}
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. On the Build menu, click Build Solution.

2. On the Debug menu, click Start Without Debugging.

3. Click the row containing the student Kevin Liu.

4. Press Enter, in the Last Name box delete the existing contents, type Cook, and then click OK.

5. Verify that Liu has changed to Cook in the students list, and that the Save Changes button is now
enabled.

6. Click Save Changes and verify that the Save Changes button is now disabled.

7. Click the row containing the student George Li and press Delete.
8. Verify that the confirmation prompt appears, and then click Yes.

9. 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

MCT USE ONLY. STUDENT USE PROHIBITED
L3-1

Module 3: Developing the Code for a Graphical Application


Lab: Writing the Code for the Grades
Prototype Application
Exercise 1: Adding navigation logic to the Grades Prototype Application
X Task 1: Examine the window and views in the application
1. Start the MSL-TMG1 virtual machine if it is not already running.

2. Start the 20483A-SEA-DEV11-03 virtual machine.


3. 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. Switch to the Windows 8 Start window.

5. Click Visual Studio 2012.

6. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.
7. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click
GradesPrototype.sln, and then click Open.

8. On the Build menu, click Build Solution.

9. In Solution Explorer, expand GradesPrototype, and then double-click MainWindow.xaml.

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. In the Task List window, in the Categories list, click Comments.

3. Double-click the TODO: Exercise 1: Task 2a: Define the LogonSuccess event handler task.
4. In the code editor, click in the blank line below the comment, and then type the following code:

5. public event EventHandler LogonSuccess;

6. In the Task List window double-click the TODO: Exercise 1: Task 2b: Implement the Logon_Click
event handler for the Logon button task.

7. 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. In Solution Explorer, double-click LogonPage.xaml.

9. 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. 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.

2. 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. studentProfile.Visibility = Visibility.Collapsed;

4. In the Task List window, double-click the TODO: Exercise 1: Task 3b: Handle successful logon
task.

5. 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. In Solution Explorer, double-click MainWindow.xaml.


7. 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.

8. 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. 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.

2. 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. In the Task List window, double-click the TODO: Exercise 1: Task 4b: Display the details for a
single student task.

4. 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. In the Task List window, double-click the TODO: Exercise 1: Task 4c: Display the list of students
task.

6. 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. 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.

8. 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. In the Task List window, double-click the TODO: Exercise 1: Task 5a: Handle the click event for a
student task.

2. 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. In Solution Explorer, double-click MainWindow.xaml.

6. In the XAML editor, locate the task TODO: Exercise 1: Task 5c: Catch the StudentSelected event
and call the studentsPage_StudentSelected event handler task.

7. 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. On the Build menu, click Build Solution.

2. On the Debug menu, click Start Without Debugging.

3. When the application loads, in the Username box, type vallee, and in the Password box, type
password.

4. Select the Teacher check box, and then click Log on.
5. 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. Click Log off.
8. In the Username box, delete the existing contents, and then type grubere.

9. 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


X Task 1: Define basic structs for holding Grade, Student, and Teacher information
1. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

2. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click


GradesPrototype.sln, and then click Open.
3. On the View menu, click Task List.

4. In the Task List window, double-click the TODO: Exercise 2: Task 1a: Create the Grade struct task.

5. 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. In the Task List window, double-click the TODO: Exercise 2: Task 1b: Create the Student struct
task.
7. 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. In the Task List window, double-click the TODO: Exercise 2: Task 1c: Create the Teacher struct
task.

9. 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. On the File menu, point to Add, and then click New Project.

2. In the Add New Project dialog box, in the Installed Templates list, click Test, and then in the
Templates list, click Unit Test Project.

3. In the Name box, type GradesTest, and then click OK.


MCT USE ONLY. STUDENT USE PROHIBITED
L3-8 Programming in Visual C#

4. In Solution Explorer, right-click GradesTest, and then click Add Reference.

5. In the Reference Manager GradesTest dialog box, expand Solution.


6. Select the GradesPrototype check box, and then click OK.

7. In Solution Explorer, right-click UnitTest1.cs, and then click Rename.

8. Type GradesUnitTests, and then press Enter.

9. 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()
{
MCT USE ONLY. STUDENT USE PROHIBITED
L3-9

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);
}

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. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

2. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 3, click


GradesPrototype.sln, and then click Open.
3. In Solution Explorer, expand GradesPrototype, expand Data, and then double-click DataSource.cs.

4. In the code editor, expand the region Sample Data, and then locate the method CreateData.

5. Note how the Teachers ArrayList is populated with Teacher data, each containing TeacherID,
UserName, Password, FirstName, LastName, and Class fields.

6. Note how the Students ArrayList is populated with Student data, each containing a StudentID,
UserName, Password, TeacherID, FirstName, and LastName fields.
7. 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. In the Task List window, double-click the TODO: Exercise 3: Task 2a: Define LogonFailed event
task.

2. In the code editor, click in the blank line below the comment, and then type the following code:

public event EventHandler LogonFailed;

3. 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.

4. 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 user is a
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 the user is
a teacher
if (!String.IsNullOrEmpty(teacher.UserName))
{
// Save the UserID and Role (teacher or student) and UserName in the global
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 match those
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) == 0
MCT USE ONLY. STUDENT USE PROHIBITED
L3-11

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);

X Task 3: Add the Logon_Failed event handler


1. In the Task List window, double-click the TODO: Exercise 3: Task 3a: Handle logon failure task.

2. 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. In Solution Explorer, double-click MainWindow.xaml.


4. 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.

5. 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. 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.

7. 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. 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.
9. 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. In Solution Explorer, expand Views, and then double-click StudentsPage.xaml.

2. 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. In the Task List window, double-click the TODO: Exercise 3: Task 4a: Display students for the
current teacher (held in SessionContext.CurrentTeacher) task.

4. 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. 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.

6. 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. 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.
8. 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. 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.
2. 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. In Solution Explorer, expand Views and then double-click StudentProfile.xaml.


4. 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.

5. 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. 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.

7. 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. 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.

9. 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. On the Build menu, click Build Solution.

2. On the Debug menu, click Start Without Debugging.


MCT USE ONLY. STUDENT USE PROHIBITED
L3-14 Programming in Visual C#

3. When the application loads, in the Username box, type parkerd, in the Password box, type
password, and then click Log on.

4. Verify that the Logon Failed dialog box appears, and then click OK.

5. In the Username box, delete the existing contents, type vallee, and then click Log on.

6. Verify that the Students page appears, displaying a list of students.


7. Click the student Kevin Liu and verify the Student Profile page for Kevin Liu is displayed.

8. Click Log off.

9. 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 Type-
Safety 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. Start the MSL-TNG1 virtual machine if it is not already running.

2. Start the 20483A-SEA-DEV11-04 virtual machine.


3. 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. Switch to the Windows 8 Start window.

5. Click Visual Studio 2012.

6. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.
7. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click
GradesPrototype.sln, and then click Open.

8. On the View menu, click Task List.

9. 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. In the Task List window, in the Categories list, click Comments.
2. 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.

3. 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. In the Task List window, in the Categories list, click Comments.

8. 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.

9. 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. 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.
2. 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. In the Task List window, double-click the TODO: Exercise 1: Task 3b: Check whether teacher is null
before examining the UserName property task.

4. 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. 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.

6. 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:

7. s.VerifyPassword(password.Password)

8. In the Task List window, double-click the TODO: Exercise 1: Task 3d: Check whether student is
null before examining the UserName property task.

9. 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. On the Build menu, click Build Solution.

2. On the Debug Menu, click Start Without Debugging.

3. In the Username box, type vallee.


4. In the Password box, type password, and then click Log on.

5. Verify that the welcome screen appears, displaying the list of students

6. Click Log off.


7. In the Username box, delete the existing contents, type grubere, and then click Log on.

8. Verify that the welcome screen appears, displaying the list of subjects and grades.

9. Click Log off.


10. Close the application.

11. On the File menu, click Close Solution.


MCT USE ONLY. STUDENT USE PROHIBITED
L4-5

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-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. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

2. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click


GradesPrototype.sln, and then click Open.
3. 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.

4. 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. In the Task List window, double-click the TODO: Exercise 2: Task 1b: Populate the list of valid
subjects with sample data task.

6. 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. In the Task List window, double-click the TODO: Exercise 2: Task 2a: Add validation to the
AssessmentDate property task.

2. 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. In the Task List window, double-click the TODO: Exercise 2: Task 2b: Add validation to the
SubjectName property task.
4. 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. In the Task List window, double-click the TODO: Exercise 2: Task 2c: Add validation to the
Assessment property task.

6. 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. On the File menu, point to Add, and then click New Project.

2. 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.

3. In the Name box, type GradesTest, and then click OK.

4. In Solution Explorer, right-click GradesTest, and then click Add Reference.


5. In the Reference Manager GradesTest dialog box, expand Solution.

6. Select the GradesPrototype check box, and then click OK.

7. 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 E-
GradesPrototype.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. On the Build menu, click Build Solution.

9. 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. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

2. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 3, click


GradesPrototype.sln, and then click Open.
3. On the Build menu, click Build Solution.

4. On the Debug Menu, click Start Without Debugging.

5. In the Username box, type vallee.


6. In the Password box, type password, and then click Log on.

7. Verify that the students are not displayed in any specific order.

8. Close the application.

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


students
1. In the Task List window, double-click the TODO: Exercise 3: Task 2a: Specify that the Student class
implements the IComparable<Student> interface task.

2. In the code editor, click at the end of the public class Student declaration, and then type the
following code:

: IComparable<Student>

3. In the Task List window, double-click the TODO: Exercise 3: Task 2b: Compare Student objects
based on their LastName and FirstName properties task.
4. 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. In the Task List window, double-click the TODO: Exercise 3: Task 3a: Change the Students
collection into a List<Student> task.
2. 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. In the Task List window, double-click the TODO: Exercise 3: Task 4a: Sort the data in the Students
collection task.

2. 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. On the Build menu, click Build Solution.

2. On the Debug menu, click Start Without Debugging.


3. In the Username box, type vallee.

4. In the Password box, type password, and then click Log on.

5. Verify that the students are displayed in order of ascending last name.
6. Log off and then close the application.

7. 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


X Task 1: Change the Teachers and Grades collections to be generic List collections
1. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

2. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 4, click


GradesPrototype.sln, and then click Open.
3. In the Task List window, double-click the TODO: Exercise 4: Task 1a: Change the Teachers
collection into a generic List task.

4. 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. In the Task List window, double-click the TODO: Exercise 4: Task 1b: Change the Grades collection
into a generic List task.

6. 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. In the Task List window, double-click the TODO: Exercise 4: Task 1c: Populate the Teachers
collection task.

8. 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. In the Task List window, double-click the TODO: Exercise 4: Task 2a: Enroll a student in the class
for this teacher task.
2. 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. In the Task List window, double-click the TODO: Exercise 4: Task 2b: Remove a student from the
class for this teacher task.

4. 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. 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.

6. 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. In the Task List window, double-click the TODO: Exercise 4: Task 3a: Enroll a student in the
teachers class task.

2. 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. In the Task List window, double-click the TODO: Exercise 4: Task 3b: Refresh the display of
unassigned students task.

4. 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. In the Task List window, double-click the TODO: Exercise 4: Task 3c: Enroll a student in the
teachers class task.
6. In the code editor, below the comment, click in the blank line in the EnrollStudent_Click method,
and then type the following code:
MCT USE ONLY. STUDENT USE PROHIBITED
L4-15

// 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. In the Task List window, double-click the TODO: Exercise 4: Task 4a: Enable a teacher to remove a
student from a class task.
2. 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);
}

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


1. In the Task List window, double-click the TODO: Exercise 4: Task 5a: Enable a teacher to add a
grade to a student task.

2. 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. On the Build menu, click Build Solution.

2. On the Debug menu, click Start Without Debugging.


3. In the Username box, type vallee.

4. In the Password box, type password, and then click Log on.

5. Click New Student.


6. In the First Name box, type Darren.

7. In the Last Name box, type Parker.

8. In the Password box, type password, and then click OK.

9. 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

MCT USE ONLY. STUDENT USE PROHIBITED
L5-1

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. Start the MSL-TMG1 virtual machine if it is not already running.

2. Start the 20483A-SEA-DEV11-05 virtual machine.


3. Log on to Windows 8 as Student with password Pa$$w0rd

Note: If necessary, click Switch User to display the list of users.

4. Switch to the Windows 8 Start window.

5. Click Visual Studio 2012.

6. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.
7. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click GradesPrototype.sln, and
then click Open.

8. In Visual Studio, on the View menu, click Task List.

9. In the Task List window, in the Categories list, click Comments.

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. In the Task List window, double-click the TODO: Exercise 1: Task 2a: Inherit from the User class task.

2. In the code editor, modify the statement below this comment as shown below in bold:

public class Student: User, IComparable<Student>

3. In the Task List window, double-click the TODO: Exercise 1: Task 2b: Remove the UserName property
(now inherited from User) task.
4. In the code editor, delete the following statement from below the comment:

public string UserName { get; set; }

5. In the Task List window, double-click the TODO: Exercise 1: Task 2c: Remove the Password property
(now inherited from User) task.
6. 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. In the Task List window, double-click the TODO: Exercise 1: Task 2d Remove the VerifyPassword
method (now inherited from User) task.

8. 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


MCT USE ONLY. STUDENT USE PROHIBITED
L5-3

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);
}

X Task 3: Run the application and test the log on functionality


1. On the Build menu, click Build Solution.

2. On the Debug menu, click Start Without Debugging.

3. When the application starts, in the Username box, type vallee, in the Password box, type password,
and then click Log on.

4. Verify that the list of students for teacher Esther Valle is displayed.

5. Click Kevin Liu, and verify that the report card displaying the grades for Kevin Liu is displayed.
6. Click Log off.

7. In the Username box, type liuk, in the Password box, type password, and then click Log on.

8. Verify that the report card showing the grades for Kevin Liu is displayed again.
9. 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. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.
2. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click GradesPrototype.sln, and
then click Open.

3. In Visual Studio, on the View menu, click Task List.


4. In the Task List window, in the Categories list, click Comments.

5. Double-click the TODO: Exercise 2: Task 1a: Define an abstract method for setting the password task.

6. 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. In the Task List window, double-click the TODO: Exercise 2: Task 1b: Use the SetPassword method to
set the password task.
8. 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. In the Task List window, double-click the TODO: Exercise 2: Task 2a: Make _password a protected field
rather than private task.

2. 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. In the Task List window, double-click the TODO: Exercise 2: Task 2b: Implement SetPassword to set
the password for the student task.

4. 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. In the Task List window, double-click the TODO: Exercise 2: Task 2c: Implement SetPassword to set the
password for the teacher task.

6. 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. In the Task List window, double-click the TODO: Exercise 2: Task 3a: Use the SetPassword method to
set the password. task.
2. 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. On the Build menu, click Build Solution.

2. In Solution Explorer, expand the GradesPrototype project, and then double-click


MainWindow.xaml.

3. 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. In Solution Explorer, expand MainWindow.xaml and then double-click MainWindow.xaml.cs.

5. In the code editor, expand the Event Handlers region, and locate the ChangePassword_Click
method.

6. 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. In Solution Explorer, expand Controls, and then double-click ChangePasswordDialog.xaml.

8. In Solution Explorer, expand ChangePasswordDialog.xaml and then double-click


ChangePasswordDialog.xaml.cs.

9. 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;


MCT USE ONLY. STUDENT USE PROHIBITED
L5-7

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;
}

X Task 5: Run the application and test the change password functionality
1. On the Build menu, click Build Solution.

2. On the Debug menu, click Start Without Debugging.

3. When the application starts, in the Username box, type vallee, in the Password box, type
password99, and then click Log on.

4. In The School of Fine Arts window, click Change Password.


5. 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.

6. Verify that the message The password is not sufficiently complex is displayed, and then click OK.
7. In the New Password box, type password101, in the Confirm box, type password101, and then
click OK.

8. Verify that the message Password changed is displayed, and then click OK.

9. 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. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

2. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 3, click GradesPrototype.sln, and
then click Open.
3. In Visual Studio, on the View menu, click Task List.

4. In the Task List window, in the Categories list, click Comments.

5. Double-click the TODO: Exercise 3: Task 1a: Add custom data: the name of the class that is full task.
6. 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. 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.

8. 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. 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.

4. 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. In the Task List window, double-click the TODO: Exercise 3: Task 2c: Catch and handle the
ClassFullException task.
6. 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. On the Build menu, click Build Solution.

2. On the Debug menu, click Start Without Debugging.

3. When the application starts, in the Username box, type vallee, in the Password box, type
password99, and then click Log on.
4. In The School of Fine Arts window, click New Student.

5. In the New Student Details window, enter the following details, and then click OK.

Field Value

First Name Walter

Last Name Harp

Password abcdef

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. In The School of Fine Arts window, click New Student.

7. In the New Student Details window, enter the following details, and then click OK.
MCT USE ONLY. STUDENT USE PROHIBITED
L5-11

Field Value

First Name Andrew

Last Name Harris

Password abcdef

8. In The School of Fine Arts window, click New Student.

9. In the New Student Details window, enter the following details, and then click OK.

Field Value

First Name Toni

Last Name Poe

Password abcdef

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 Value

First Name Ben

Last Name Andrews

Password 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. Start the MSL-TMG1 virtual machine if it is not already running.

2. Start the 20483A-SEA-DEV11-06 virtual machine.


3. 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. Switch to the Windows 8 Start window.

5. Click Visual Studio 2012.

6. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.
7. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click GradesPrototype.sln, and
then click Open.

8. In Solution Explorer, expand GradesPrototype, expand Views, and then double-click


StudentProfile.xaml.

9. 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. 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.
2. 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. In the Task List window, double-click the TODO: Exercise 1: Task 2b: Create the root node of the XML
document. task.

4. 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. 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.

6. 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. In the Task List window, double-click the TODO: Exercise 1: Task 2d: Finish the XML document with
the appropriate end elements task.

8. 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();
MCT USE ONLY. STUDENT USE PROHIBITED
L06-3

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;

13. Delete the following line of code from the end of the method:

throw new NotImplementedException();

X Task 3: Debug the application


1. On the Build menu, click Build Solution.

2. In the Task List window, double-click the TODO: Exercise 1: Task 1c: Serialize the grades to a
MemoryStream task.
3. In the code editor, select the closing brace immediately below the following line of code:

MemoryStream ms = FormatAsXMLStream(grades);

4. On the Debug menu, click Toggle Breakpoint.

5. On the Debug menu, click Start Debugging.


6. In the Username box, type vallee.

7. In the Password box, type password99, and then click Log on.

8. In the main application window, click Kevin Liu.


9. 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. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

2. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click GradesPrototype.sln, and
then click Open.
3. On the View menu, click Task List.

4. In the Task List window, in the Categories list, click Comments.

5. Double-click the TODO: Exercise 2: Task 1a: Generate a string representation of the report data task.
6. In the code editor, click in the blank line below the comment, and then type the following code:

7. string formattedReportData = FormatXMLData(ms);

8. 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.

9. 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. In the Task List window, double-click the TODO: Exercise 2: Task 2a: Use a StringBuilder to construct
the string task.

2. In the code editor, click in the blank line below the comment, and then type the following code:

StringBuilder builder = new StringBuilder();

3. 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.

4. In the code editor, click in the blank line below the comment, and then type the following code:

XmlTextReader reader = new XmlTextReader(stream);

5. 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.

6. 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. 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.

8. 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. On the Build menu, click Build Solution.

2. On the Debug menu, click Start Without Debugging.


3. In the Username box, type vallee.

4. In the Password box, type password99, and then click Log on.

5. In the main application window, click Kevin Liu.

6. In the Report Card view, click Save Report.

7. 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. Review the XML data displayed in the message box, and then click OK.

9. 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. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

2. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 3, click GradesPrototype.sln, and
then click Open.
3. On the View menu, click Task List.

4. In the Task List window, in the Categories list, click Comments.

5. Double-click the TODO: Exercise 3: Task 1a: Modify the message box and ask the user whether they
wish to save the report task.

6. In the code editor, delete the line of code below the comment, and then type the following code:

7. MessageBoxResult reply = MessageBox.Show(formattedReportData, "Save Report?",


MessageBoxButton.YesNo, MessageBoxImage.Question);

8. 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.
9. 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. On the Build menu, click Build Solution.

2. On the Debug menu, click Start Without Debugging.

3. In the Username box, type vallee.

4. In the Password box, type password99, and then click Log on.

5. In the main application window, click Kevin Liu.

6. In the Report Card view, click Save Report.

7. In the Save As dialog box, browse to the Documents folder, and then click Save.
8. Review the XML data displayed in the message box, and then click Yes.

9. 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. Start the MSL-TMG1 virtual machine if it is not already running.

2. Start the 20483A-SEA-DEV11-07 virtual machine.

3. 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. Switch to the Windows 8 Start window.


5. Click Visual Studio 2012.

6. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

7. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click GradesPrototype.sln, and
then click Open.

8. On the File menu, point to Add, and then click New Project.

9. 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. In the designer window, review the entities that have been generated.

2. Review the properties and navigation properties of the Grade entity.

3. Right-click the heading of the Grade entity, and then click Table Mapping.

4. In the Mapping Details Grade pane, review the mappings between the columns in the database
table and the properties of the entity.

5. In Solution Explorer, expand GradesModel.edmx, expand GradesModel.Context.tt, and then


double-click GradesModel.Context.cs.

6. In the code window, note that the wizard has created a DbContext object named
SchoolGradesDBEntities.

7. In Solution Explorer, expand GradesModel.tt, and then double-click Grade.cs.

8. Note that the wizard has created one property for each column in the Grades database table.

9. 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. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.
2. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click GradesPrototype.sln, and
then click Open.

3. In Solution Explorer, right-click GradesPrototype, and then click Set as StartUp Project.
4. On the View menu, click Task List.

5. In the Task List window, in the Categories List, click Comments.

6. Double-click the TODO: Exercise 2: Task 1a: Find all the grades for the student. task.
7. 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. In the Task List window, double-click the TODO: Exercise 2: Task 1b: Display the grades in the
studentGrades ItemsControl by using databinding. task.

9. 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. 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.
2. 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. 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.

2. In the code editor, click in the blank line below the comment, and then type the following code:

GradeDialog gd = new GradeDialog();

3. 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.

4. 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.

7. 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;

8. In the Task List window, double-click the TODO: Exercise 2: Task 3d: Save the grade. task.

9. 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. On the Debug menu, click Start Without Debugging.

3. When the application loads, in the Username box, type vallee, and in the Password box, type
password99, and then click Log on.

4. In the Class 3C view, click Kevin Liu.

5. Verify that the list of grades now displays the subject name, not the subject ID.
6. In the Report Card view, click Add Grade.

7. 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.
8. Verify that the new grade is added to the list, and then close the application.

9. 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. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

2. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 3, click GradesPrototype.sln, and
then click Open.
3. In Solution Explorer, right-click GradesPrototype, and then click Set as StartUp Project.

4. In Solution Explorer, right-click Grades.DataModel, point to Add, and then click Class.

5. In the Add New Item Grades.DataModel dialog box, in the Name box, type customTeacher.cs,
and then click Add.

6. 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.
MCT USE ONLY. STUDENT USE PROHIBITED
L7-7

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. In Solution Explorer, right-click Grades.DataModel, point to Add, and then click Class.
2. In the Add New Item Grades.DataModel dialog box, in the Name box, type customGrade.cs,
and then click Add.

3. In the code editor, modify the class declaration as shown in the following code:

public partial class Grade

4. In the code editor, in the Grade class, type the following code:

public bool ValidateAssessmentDate(DateTime assessmentDate)


{
// Verify that the user has provided a valid date.
// 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("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. In the Task List window, double-click the TODO: Exercise 3: Task 2a: Create a Grade object. task.

8. 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. On the Build menu, click Build Solution.

2. On the Debug menu, click Start Without Debugging.

3. When the application loads, in the Username box, type vallee, and in the Password box, type
password99, and then click Log on.

4. When the application loads, click Enroll Student.


5. 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.

6. In the Assign Student dialog box, click Close.


7. In the Class 3C view, click Kevin Liu, and then click Add Grade.

8. In the New Grade Details dialog box, in the Date box, type tomorrows date, and then click OK.

9. 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. Start the 20483A-SEA-DEV11-08 virtual machine.

2. 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. Switch to the Windows 8 Start window.


4. Click Visual Studio 2012.

5. In Microsoft Visual Studio, on the File menu, point to Open, and then click Project/Solution.

6. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click


GradesPrototype.sln, and then click Open.

7. In Solution Explorer, right-click the GradesPrototype solution, point to Add, and then click New
Project.

8. In the Add New Project dialog box, in the left pane expand Visual C#, and then click Web.

9. 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. In Solution Explorer, right-click the Grades.Web project, point to Add, and then click New Folder.

2. Delete the existing folder name, type Services, and then press Enter.
3. Right-click Services, point to Add, and then click New Item.

4. In the templates list, click WCF Data Service.


MCT USE ONLY. STUDENT USE PROHIBITED
L08-2 Programming in Visual C#

5. In the Name box, type GradesWebDataService, and then click Add.

6. Right-click Grades.Web, and then click Add Reference.


7. In the Reference Manager Grades.Web dialog box, expand Solution, and then select
Grades.DataModel.

8. Click Browse.
9. 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. In Solution Explorer, in Grades.Web, expand Services, and then double-click
GradesWebDataService.svc.

2. 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. On the View menu, click Task List.

4. In the Task List window, in the Categories list, click Comments.


5. Double-click the TODO: put your data source class name here task.

6. In the code editor, delete the code /* TODO: put your data source class name here */, and then
type the following code:

SchoolGradesDBEntities

7. In the Task List window, double-click the TODO: set rules to indicate which entity sets and service
operations are visible, updatable, etc. task.

8. 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. In the Task List window, double-click the TODO: set rules to indicate which entity sets and service
operations are visible, updatable, etc. task.

3. 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. On the Build menu, click Build Solution.
2. In Solution Explorer, in the Grades.Web project, in the Services folder, right-click
GradesWebDataService.svc, and then click View in Browser (Internet Explorer).

3. In Internet Explorer, if the message Intranet settings are turned off by default, click Don't show this
message again.

4. Verify that Internet Explorer displays an XML description of the entities that the data service
exposes.
5. Close Internet Explorer.

6. 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. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

2. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click


GradesPrototype.sln, and then click Open.
3. In Solution Explorer, expand GradesPrototype, expand References, right-click Grades.DataModel,
and then click Remove.

4. Right-click References, and then click Add Service Reference.


5. In the Add Service Reference dialog box, in the Address box, type http://localhost:1650, and then click
Discover.

6. In the Namespace box, type Grades.DataModel, and then click OK.


7. In the Solution Explorer toolbar, click Show All Files.

8. In Solution Explorer, in the GradesPrototype project, in the Service References folder, expand
Grades.DataModel, expand Reference.datasvcmap, and then double-click Reference.cs.
9. 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. In the Task List window, double-click the TODO: Exercise 2: Task 2a: Specify the URL of the
GradesWebDataService task.

2. 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. In the Task List window, double-click the TODO: Exercise 2: Task 2b: Load User and Grades data with
Students task.

5. 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. In the Task List window, double-click the TODO: Exercise 2: Task 2c: Load User and Students data with
Teachers task.

7. 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. In the Task List window, double-click the TODO: Exercise 2: Task 2d: Load User and Grades data with
Students task.

9. 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. In the Task List window, double-click the TODO: Exercise 2: Task 3a: Specify that the selected student
has been changed task.

2. In the code editor, click in the blank space below the comment, and then type the following code:

3. SessionContext.DBContext.UpdateObject(student);
4. In the Task List window, double-click the TODO: Exercise 2: Task 3b: Specify that the current student
has been changed task.

5. In the code editor, click in the blank space below the comment, and then type the following code:

SessionContext.DBContext.UpdateObject(SessionContext.CurrentStudent);

6. In the Task List window, double-click the TODO: Exercise 2: Task 3c: Specify that the current user has
been changed task.

7. 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. On the Build menu, click Build Solution.

2. On the Debug menu, click Start Without Debugging.

3. In the Username box, type vallee.


4. In the Password box, type password99, and then click Log on.

5. In the students list, click Eric Gruber, click Remove Student, and then in the Confirm dialog box,
click Yes.

6. Verify that Eric Gruber is removed from the student list.

7. Click Enroll Student, click Jon Orton, and then in the Confirm dialog box, click Yes.

8. Click Close, and then verify that Jon Orton is added to the student list.

9. 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. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

2. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 3, click


GradesPrototype.sln, and then click Open.
3. 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. Right-click the IValueConverter keyword, point to Implement Interface, and then click Implement
Interface.

7. 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. In Solution Explorer, in the GradesPrototype project, expand Views, and then double-click
StudentsPage.xaml.

2. 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. 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.

6. 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. In Solution Explorer, double-click StudentProfile.xaml.

2. Locate the TODO: Exercise 3: Task 3a. Add an instance of the ImageNameConverter class as a
resource to the view comment.

3. 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.
5. Click at the end of the comment, press Enter, and then type the following markup:

<Image Height="150" Source="{Binding ImageName, Converter={StaticResource


ImageNameConverter}}" />

X Task 4: Add an Image control to the AssignStudentDialog control and bind it to the
ImageName property
1. In Solution Explorer, expand Controls, and then double-click AssignStudentDialog.xaml.
2. 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. Locate the TODO: Exercise 3: Task 4a. Add an instance of the ImageNameConverter class as a
resource to the view comment.

4. 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.

6. Click at the end of the comment, press Enter, and then type the following markup:
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. On the Build menu, click Build Solution.
2. On the Debug menu, click Start Without Debugging.

3. In the Username box, type vallee.

4. In the Password box, type password88, and then click Log on.
5. Verify that the students list now includes images.

6. Click George Li, and then verify that the student profile appears with an image.

7. Click Remove Student, and then in the Confirm dialog box, click Yes.
8. Click Enroll Student, and then verify that in the Assign Student dialog box, the unassigned students
each have an image.

9. 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. Start the MSL-TMG1 virtual machine if it is not already running.
2. Start the 20483A-SEA-DEV11-09 virtual machine.

3. 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. Switch to the Windows 8 Start window.

5. Click Visual Studio 2012.


6. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

7. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click Grades.sln, and then
click Open.
8. In Solution Explorer, right-click Solution Grades, and then click Properties.

9. 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. In Solution Explorer, expand Views, and then double-click StudentsPage.xaml.
2. 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.

3. 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. In Solution Explorer, expand StudentsPage.xaml, and then double-click StudentsPage.xaml.cs.

2. On the View menu, click Task List.

3. In the Task List window, in the Categories list, click Comments.


4. 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. In Solution Explorer, double-click StudentsPage.xaml.

7. 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.

8. 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. 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.

3. 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. 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.
5. 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. In Solution Explorer, double-click StudentsPage.xaml.

7. 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. In Solution Explorer, double-click StudentsPage.xaml.cs.

2. In the Task List window, double-click the TODO: Exercise 1: Task 5a: Find all students for the current
teacher task.
3. 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. 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.

5. 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. In the Task List window, double-click the TODO: Exercise 1: Task 5c: Bind the list of students to the
"list" ItemsControl task.
7. 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. On the Build menu, click Build Solution.

2. On the Debug menu, click Start Without Debugging.


3. When the application starts, in the Username box, type vallee, in the Password box, type
password99, and then click Log on.

4. Verify that the students list appears with photographs.

5. In the student list, hover over the red x for the student Martin Weber.
MCT USE ONLY. STUDENT USE PROHIBITED
L9-5

6. Verify that the student photograph for Martin Weber becomes transparent and that the red x
becomes opaque.

7. Move the cursor away from the red x and verify that the student photograph becomes opaque and
that the red x becomes transparent.

8. Click the red x for Martin Weber, verify that the Student message box appears, and then click Yes.
9. 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. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

2. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click Grades.sln, and then
click Open.
3. In Solution Explorer, right-click Solutions Grades, and then click Properties.

4. On the Startup Project page, click Multiple startup projects. Set Grades.Web and Grades.WPF to Start
without debugging, and then click OK.

5. In Solution Explorer, expand Grades.WPF, expand Views, and then double-click LogonPage.xaml.

6. In the XAML editor, locate the <!-- TODO: Exercise 2: Task 1a: Define the LoginTextBoxStyle -->
comment.
7. 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. Locate the <!-- TODO: Exercise 2: Task 1b: Apply the LoginTextBoxStyle to the "username" TextBox --
> comment.
9. 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. 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.

3. Click in the blank line below the comment, and type the following markup:

<Setter Property="TextWrapping" Value="NoWrap"/>


<Setter Property="FontFamily" Value="../Assets/#Buxton Sketch"/>
<Setter Property="FontSize" Value="19"/>
<Setter Property="Foreground" Value="#FF303030" />

4. Locate the <!-- TODO: Exercise 2: Task 2b: Define the text styling used throughout the application -->
comment.
5. Click in the blank line below the comment, then type the following markup:

<Setter Property="TextWrapping" Value="NoWrap"/>


<Setter Property="FontFamily" Value="../Assets/#Buxton Sketch"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="TextAlignment" Value="Left" />
<Setter Property="Foreground" Value="#FF303030" />

X Task 3: Define animations for the StudentPhoto control


1. In Solution Explorer, expand Controls, and then double-click StudentPhoto.xaml.
2. In the XAML editor, locate the <!-- TODO: Exercise 2: Task 3a: Define a ScaleTransform called "scale" -
-> comment.

3. Click in the blank line below the comment, then type the following markup:

<UserControl.RenderTransform>
<ScaleTransform x:Name="scale" />
</UserControl.RenderTransform>

4. In the XAML editor, locate the <!-- TODO: Exercise 2: Task 3b: Define animations for the "scale"
transform--> comment.

5. 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. In Solution Explorer, expand StudentPhoto.xaml, and then double-click StudentPhoto.xaml.cs.

2. 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.
3. 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. In Solution Explorer, in Views, expand StudentsPage.xaml, and then double-click


StudentsPage.xaml.cs.

5. In the Task List window, double-click the TODO: Exercise 2: Task 4b: Forward the MouseEnter and
MouseLeave events to the photograph control task.

6. 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. In Solution Explorer, double-click StudentsPage.xaml.

8. In the XAML editor, locate the <!-- TODO: Exercise 2: Task 4c: Specify the handlers for the
MouseEnter and MouseLeave events --> comment.

9. 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. On the Build menu, click Build Solution.

2. On the Debug menu, click Start Without Debugging.

3. When the application starts, in the Username box, type vallee, and in the Password box, type
password99, and then click Log on.

4. 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. 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.

6. Close the application.


7. 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. Start the MSL-TMG1 virtual machine if it is not already running.

2. Start the 20483A-SEA-DEV11-10 virtual machine.


3. 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. Switch to the Windows 8 Start window.

5. Click Visual Studio 2012.

6. In Microsoft Visual Studio, on the File menu, point to Open, and then click Project/Solution.
7. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click Grades.sln, and then
click Open.

8. In Solution Explorer, right-click Solutions Grades, and then click Properties.

9. 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. On the View menu, click Task List.

2. In the Task List window, in the Categories list, select Comments.

3. Double-click the TODO: Exercise 1: Task 2a: Convert GetTeacher into an async method that
returns a Task<Teacher> task.

4. 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. In the Task List window, double-click the TODO: Exercise 1: Task 2b: Perform the LINQ query to
fetch Teacher information asynchronously task.

7. 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. In the Task List window, double-click the TODO: Exercise 1: Task 2c: Mark MainWindow.Refresh
as an asynchronous method task.

9. 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. In the Task List window, double-click the TODO: Exercise 1: Task 3a: Mark StudentsPage.Refresh
as an asynchronous method task.

2. In the code editor, modify the statement below the comment as shown in bold below:

public async void Refresh()

3. 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.

4. 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.

6. In the code editor, move all of the code between the comment and the end of the Refresh method
to the Clipboard.

7. 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.

8. Click in the blank line between the curly braces and paste the code from the Clipboard.
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. On the Build menu, click Build Solution.

2. On the Debug menu, click Start Without Debugging.

3. When the application loads, in the Username box, type vallee, and in the Password box, type
password99, and then click Log on.

4. Verify that the application is more responsive than before while fetching the list of students for Esther
Valle, and then close the application window.

5. On the File menu, click Close Solution.

Results: After completing this exercise, you should have updated the Grades application to retrieve data
asynchronously.
MCT USE ONLY. STUDENT USE PROHIBITED
L10-5

Exercise 2: Providing Visual Feedback During Long-Running Operations


X Task 1: Create the BusyIndicator user control
1. Start the MSL-TMG1 virtual machine if it is not already running.

2. Start the 20483A-SEA-DEV11-10 virtual machine.

3. 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. Switch to the Windows 8 Start window.


5. Click Visual Studio 2012.

6. In Microsoft Visual Studio, on the File menu, point to Open, and then click Project/Solution.

7. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click Grades.sln, and then
click Open.

8. In Solution Explorer, right-click Solutions Grades, and then click Properties.

9. 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. 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. In the Task List window, double-click the TODO: Exercise 2: Task 2a: Implement the StartBusy
event handler task.
2. 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. In the Task List window, double-click the TODO: Exercise 2: Task 2b: Implement the EndBusy
event handler task.
4. 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. In the Task List window, double-click the TODO: Exercise 2: Task 3a: Add the StartBusy public
event task.
2. In the blank line below the comment, type the following code:

public event EventHandler StartBusy;

3. In the Task List window, double-click the TODO: Exercise 2: Task 3b: Add the EndBusy public
event task.
4. In the blank line below the comment, type the following code:

public event EventHandler EndBusy;

5. In the Task List window, double-click the TODO: Exercise 2: Task 3c: Implement the
StartBusyEvent method to raise the StartBusy event task.

6. In the blank line below the comment, type the following code:

private void StartBusyEvent()


{
if (StartBusy != null)
StartBusy(this, new EventArgs());
}

7. In the Task List window, double-click the TODO: Exercise 2: Task 3d: Implement the
EndBusyEvent method to raise the EndBusy event task.

8. 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. On the Build menu, click Build Solution.

2. On the Debug menu, click Start Without Debugging.

3. When the application loads, in the Username box, type vallee, and in the Password box, type
password99, and then click Log on.

4. Verify that the application displays the busy indicator while waiting for the list of students to load,
and then close the application window.

5. 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. Start the MSL-TMG1 virtual machine if it is not already running.

2. Start the 20483A-SEA-DEV11-11 virtual machine.


3. 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. Switch to the Windows 8 Start window.

5. Click Visual Studio 2012.

6. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.
7. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click Grades.sln, and then
click Open.

8. In Solution Explorer, right-click Solutions Grades, and then click Properties.


9. 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. In the Task List window, double-click the TODO: Exercise 1: Task 2a: Generate a student grade report
as a Word document. task.
2. 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. In the Task List window, double-click the TODO: Exercise 1: Task 2b: Generate the report by using a
separate task task.

4. 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. On the Build menu, click Build Solution.
2. On the Debug menu, click Start Without Debugging.

3. When the application loads, in the Username box, type vallee, and in the Password box, type
password99, and then click Log on.

4. Click Kevin Liu, and then click save report.

5. In the Save As dialog box, browse to E:\Labfiles\Starter\Exercise 1.

6. In the File name box, delete the existing contents, type Kevin Liu Grades Report, and then click
Save.

7. Close the application, and then in Microsoft Visual Studio, on the File menu, click Close Solution.

8. Open File Explorer, browse to the E:\Labfiles\Starter\Exercise 1 folder, and then verify that the
report has been generated.

9. 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. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.
2. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click Grades.sln, and then
click Open.

3. In Solution Explorer, right-click Solutions Grades, and then click Properties.


4. On the Startup Project page, click Multiple startup projects. Set Grades.Web and Grades.WPF to Start
without debugging, and then click OK.

5. On the Build menu, click Build Solution.

6. On the Debug menu, click Start Without Debugging.

7. When the application loads, in the Username box, type vallee, and in the Password box, type
password99, and then click Log on.
8. Click Kevin Liu, and then click save report.

9. 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. 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.
2. 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. In the Task List window, double-click the TODO: Exercise 2: Task 2b: Create the protected
Dispose(bool) method task.

4. 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. In the Task List window, double-click the TODO: Exercise 2: Task 2c: Create the public Dispose method
task.

6. 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. In the Task List window, double-click the TODO: Exercise 2: Task 2d: Create a finalizer that calls the
Dispose method task.

8. 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. In the Task List window, double-click the TODO: Exercise 2: Task 3: Ensure that the WordWrapper is
disposed when the method finishes task.

2. Below the comment, modify the WordWrapper wrapper = new WordWrapper(); code to look like
the following:

using (var wrapper = new WordWrapper())


{

3. At the end of the method, after the wrapper.SaveAs(reportPath); line of code, add a closing brace
to end the using block.
4. 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. On the Build menu, click Build Solution.

2. Right-click the taskbar, and then click Task Manager.

3. In Visual Studio, on the Debug menu, click Start Without Debugging.

4. When the application loads, in the Username box, type vallee, and in the Password box, type
password99, and then click Log on.
5. Click George Li, and then click save report.

6. In the Save As dialog box, browse to E:\Labfiles\Starter\Exercise 2.

7. In the File name box, delete the existing contents, and then type George Li Grades Report.
8. 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.

9. 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. Start the 20483A-SEA-DEV11-12 virtual machine.

2. 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. Switch to the Windows 8 Start window.


4. Click Visual Studio 2012.

5. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

6. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click Grades.sln, and then
click Open.

7. In Solution Explorer, right-click Solutions Grades, and then click Properties.

8. On the Startup Project page, click Multiple startup projects. Set Grades.Web and Grades.WPF to Start
without debugging, and then click OK.

9. 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. In Solution Explorer, expand Grades.WPF, and then double-click Data.cs.
2. 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.

3. In the LocalGrade method, expand the Properties region, and then expand the Readonly
Properties region.

4. 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. Expand the Form Properties region.


7. 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. On the Build menu, click Build Solution.

2. Open File Explorer and browse to the C:\Program Files (x86)\Microsoft


SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools folder.
3. Right-click ildasm.exe, and then click Open.

4. In the IL DASM window, on the File menu, click Open.

5. In the Open dialog box, browse to E:\Labfiles\Starter\Exercise 1\Grades.WPF\bin\Debug, click


Grades.WPF.exe, and then click Open.

6. In the IL DASM application window, expand Grades.WPF, expand Grades.WPF.LocalGrade, and then
double-click Assessment : instance string();.
7. 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.
8. In the IL DASM application window, double-click AssessmentDateString : instance string();.

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. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

2. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click Grades.sln, and then
click Open.
3. In Solution Explorer, expand Grades.Utilities, and then double-click IncludeInReport.cs.

4. Below the Output window, click Task List.

5. 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.

6. In the code editor, click in the blank line in the FormatField struct, and then type the following code:

public string Value;


public string Label;
public bool IsBold;
public bool IsUnderlined;

7. 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.

8. 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. In Solution Explorer, expand Grades.WPF, expand Views, expand StudentProfile.xaml, and then
double-click StudentProfile.xaml.cs.
2. 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.

3. 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. 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.

5. 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. On the Build menu, click Build Solution.

7. 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. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

2. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 3, click Grades.sln, and then
click Open.
3. In Solution Explorer, right-click Solutions Grades, and then click Properties.

4. On the Startup Project page, click Multiple startup projects. Set Grades.Web and Grades.WPF to Start
without debugging, and then click OK.

5. Switch to the Windows 8 Start window.

6. In the Start window, right-click the background to display the taskbar.

7. On the taskbar, click All apps.

8. In the Start window, right-click the VS2012 x86 Native Tools Command icon.

9. 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.
MCT USE ONLY. STUDENT USE PROHIBITED
L12-7

X Task 2: Reference the Grades.Utilities assembly in the GAC from the application
1. In Visual Studio, in Solution Explorer, expand Grades.WPF, expand References, right-click
Grades.Utilities, and then click Remove.
2. Right-click References, and then click Add Reference.

3. In the Reference Manager Grades.WPF dialog box, click the Browse button.

4. 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.

5. In the Reference Manager Grades.WPF dialog box, click OK.

6. On the Build menu, click Build Solution.


7. On the Debug menu, click Start Without Debugging.

8. In the Username box, type vallee, and in the Password box, type password99, and then click Log
on.
9. In the Class 3C view, click Kevin Liu.

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. Start the MSL-TMG1 virtual machine if it is not already running.

2. Start the 20483A-SEA-DEV11-13 virtual machine.


3. 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. Switch to the Windows 8 Start window.

5. Click Visual Studio 2012.

6. In Microsoft Visual Studio, on the File menu, point to Open, and then click Project/Solution.
7. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 1, click Grades.sln, and then
click Open.

8. In Solution Explorer, right-click Solutions Grades, and then click Properties.

9. 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. In Visual Studio, on the View menu, click Task List.
2. In the Task List window, in the Categories list, click Comments.

3. Double-click the TODO: Exercise 1: Task 2a: Loop through the certificates in the X509 store to
return the one matching _certificateSubjectName. task.
4. 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. In the Task List window, double-click the TODO: Exercise 1: Task 3a: Get the public key from the
X509 certificate. task.

2. In the code editor, delete the following line of code:

throw new NotImplementedException();

3. In the blank line below the comment, type the following code:

4. var provider = (RSACryptoServiceProvider)this._certificate.PublicKey.Key;


5. In the Task List window, double-click the TODO: Exercise 1: Task 3b: Create an instance of the
AesManaged algorithm. task.

6. In the code editor, click in the blank line below the comment, and then type the following code:

using (var algorithm = new AesManaged())


{

7. In the Task List window, double-click the TODO: Exercise 1: Task 3c: Create an underlying stream
for the unencrypted data. task.
8. 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. In the Task List window, double-click the TODO: Exercise 1: Task 4a: Write the encrypted bytes to
disk. task.

2. 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. On the Build menu, click Build Solution.
2. On the Debug menu, click Start Without Debugging.

3. When the application loads, in the Username box, type vallee, and in the Password box, type
password99, and then click Log on.
4. In the Class 3C view, click George Li.

5. In the Report Card view, click save report.


MCT USE ONLY. STUDENT USE PROHIBITED
L13-4 Programming in C#

6. In the Save As dialog box, browse to the E:\Labfiles\Reports folder, in the File name box, type
GeorgeLi, and then click Save.

7. In the Report Card view, click Back.

8. In the Class 3C view, click Kevin Liu.

9. 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. In Visual Studio, on the File menu, point to Open, and then click Project/Solution.

2. In the Open Project dialog box, browse to E:\Labfiles\Starter\Exercise 2, click School-Reports.sln,


and then click Open.
3. In the Task List window, double-click the TODO: Exercise 2: Task 1a: Get the private key from the
X509 certificate. task.

4. 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. 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.

7. In the blank line below the comment, type the following code:

using (var algorithm = new AesManaged())


{

8. In the Task List window, double-click the TODO: Exercise 2: Task 1c: Create a stream to process
the bytes. task.

9. 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. On the Build menu, click Build Solution.

2. On the Debug menu, click Start Without Debugging.

3. When the application loads, click Browse.

4. In the Browse For Folder dialog box, browse to the E:\Labfiles\Reports folder, and then click OK.
5. Click Print.

6. 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.
7. In the The School of Fine Arts dialog box, click OK, and then close the application.

8. Open File Explorer, and browse to the E:\Labfiles\Reports\ClassReport folder.

9. 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.

You might also like